working pow

pull/62/head
ak 6 years ago
parent c7b63df577
commit 6632cea6de
  1. 12
      identitychain/identityblock.go
  2. 23
      identitychain/identitychain.go
  3. 77
      identitychain/identitychain_handler.go
  4. 58
      node/node.go
  5. 2
      node/node_handler.go
  6. 82
      waitnode/wait_node.go
  7. 18
      waitnode/wait_node_test.go

@ -7,8 +7,8 @@ import (
"log"
"time"
"github.com/simple-rules/harmony-benchmark/node"
"github.com/simple-rules/harmony-benchmark/utils"
"github.com/simple-rules/harmony-benchmark/waitnode"
)
// IdentityBlock has the information of one node
@ -16,7 +16,7 @@ type IdentityBlock struct {
Timestamp int64
PrevBlockHash [32]byte
NumIdentities int32
Identities []*waitnode.WaitNode
Identities []*node.Node
}
// Serialize serializes the block
@ -31,7 +31,7 @@ func (b *IdentityBlock) Serialize() []byte {
}
//Get Identities
func (b *IdentityBlock) GetIdentities() []*waitnode.WaitNode {
func (b *IdentityBlock) GetIdentities() []*node.Node {
return b.Identities
}
@ -47,7 +47,7 @@ func DeserializeBlock(d []byte) *IdentityBlock {
}
// NewBlock creates and returns a new block.
func NewBlock(Identities []*waitnode.WaitNode, prevBlockHash [32]byte) *IdentityBlock {
func NewBlock(Identities []*node.Node, prevBlockHash [32]byte) *IdentityBlock {
block := &IdentityBlock{Timestamp: time.Now().Unix(), PrevBlockHash: prevBlockHash, NumIdentities: int32(len(Identities)), Identities: Identities}
return block
}
@ -59,7 +59,7 @@ func (b *IdentityBlock) CalculateBlockHash() [32]byte {
hashes = append(hashes, utils.ConvertFixedDataIntoByteArray(b.Timestamp))
hashes = append(hashes, b.PrevBlockHash[:])
for _, id := range b.Identities {
hashes = append(hashes, utils.ConvertFixedDataIntoByteArray(id.ID))
hashes = append(hashes, utils.ConvertFixedDataIntoByteArray(id))
}
hashes = append(hashes, utils.ConvertFixedDataIntoByteArray(b.NumIdentities))
blockHash = sha256.Sum256(bytes.Join(hashes, []byte{}))
@ -68,7 +68,7 @@ func (b *IdentityBlock) CalculateBlockHash() [32]byte {
// NewGenesisBlock creates and returns genesis Block.
func NewGenesisBlock() *IdentityBlock {
var Ids []*waitnode.WaitNode
var Ids []*node.Node
block := &IdentityBlock{Timestamp: time.Now().Unix(), PrevBlockHash: [32]byte{}, NumIdentities: 1, Identities: Ids}
return block
}

@ -9,8 +9,8 @@ import (
"sync"
"github.com/simple-rules/harmony-benchmark/log"
"github.com/simple-rules/harmony-benchmark/node"
"github.com/simple-rules/harmony-benchmark/p2p"
"github.com/simple-rules/harmony-benchmark/waitnode"
)
var mutex sync.Mutex
@ -19,13 +19,13 @@ var identityPerBlock = 100000
// IdentityChain (Blockchain) keeps Identities per epoch, currently centralized!
type IdentityChain struct {
Identities []*IdentityBlock
PendingIdentities []*waitnode.WaitNode
PendingIdentities []*node.Node
log log.Logger
Peer p2p.Peer
SelectedIdentitites []*waitnode.WaitNode
SelectedIdentitites []*node.Node
EpochNum int
PeerToShardMap map[*waitnode.WaitNode]int
ShardLeaderMap map[int]*waitnode.WaitNode
PeerToShardMap map[*node.Node]int
ShardLeaderMap map[int]*node.Node
PubKey string
CurrentEpochStartTime int64
NumberOfShards int
@ -33,7 +33,7 @@ type IdentityChain struct {
PowMap map[p2p.Peer]uint32
}
func seekRandomNumber(EpochNum int, SelectedIdentitites []*waitnode.WaitNode) int {
func seekRandomNumber(EpochNum int, SelectedIdentitites []*node.Node) int {
// Broadcast message to all nodes and collect back their numbers, do consensus and get a leader.
// Use leader to generate a random number.
//all here mocked
@ -72,18 +72,18 @@ func (IDC *IdentityChain) CreateShardAssignment() {
num := seekRandomNumber(IDC.EpochNum, IDC.SelectedIdentitites)
IDC.NumberOfShards = IDC.NumberOfShards + needNewShards()
IDC.SelectedIdentitites = generateRandomPermutations(num, IDC.SelectedIdentitites)
IDC.PeerToShardMap = make(map[*waitnode.WaitNode]int)
IDC.PeerToShardMap = make(map[*node.Node]int)
numberInOneShard := len(IDC.SelectedIdentitites) / IDC.NumberOfShards
for peerNum := 1; peerNum <= len(IDC.SelectedIdentitites); peerNum++ {
IDC.PeerToShardMap[IDC.SelectedIdentitites[peerNum]] = peerNum / numberInOneShard
}
}
func generateRandomPermutations(num int, SelectedIdentitites []*waitnode.WaitNode) []*waitnode.WaitNode {
func generateRandomPermutations(num int, SelectedIdentitites []*node.Node) []*node.Node {
src := rand.NewSource(int64(num))
rnd := rand.New(src)
perm := rnd.Perm(len(SelectedIdentitites))
SelectedIdentititesCopy := make([]*waitnode.WaitNode, len(SelectedIdentitites))
SelectedIdentititesCopy := make([]*node.Node, len(SelectedIdentitites))
for j, i := range perm {
SelectedIdentititesCopy[j] = SelectedIdentitites[i]
}
@ -98,7 +98,7 @@ func (IDC *IdentityChain) SelectIds() {
selectNumber = int(math.Min(float64(len(IDC.PendingIdentities)), float64(selectNumber)))
pending := IDC.PendingIdentities[:selectNumber]
IDC.SelectedIdentitites = append(currentIDS, pending...)
IDC.PendingIdentities = []*waitnode.WaitNode{}
IDC.PendingIdentities = []*node.Node{}
}
//Checks how many new shards we need. Currently we say 0.
@ -129,7 +129,7 @@ func (IDC *IdentityChain) UpdateIdentityChain() {
prevBlock := IDC.GetLatestBlock()
prevBlockHash := prevBlock.CalculateBlockHash()
NewIdentities := IDC.PendingIdentities[:identityPerBlock]
IDC.PendingIdentities = []*waitnode.WaitNode{}
IDC.PendingIdentities = []*node.Node{}
//All other blocks are dropped, we need to inform them that they are dropped?
IDBlock := NewBlock(NewIdentities, prevBlockHash)
IDC.Identities = append(IDC.Identities, IDBlock)
@ -171,5 +171,6 @@ func New(Peer p2p.Peer) *IdentityChain {
IDC := IdentityChain{}
IDC.Peer = Peer
IDC.log = log.New()
IDC.PowMap = make(map[p2p.Peer]uint32)
return &IDC
}

@ -7,9 +7,12 @@ import (
"math/rand"
"net"
"os"
"strconv"
"time"
"github.com/simple-rules/harmony-benchmark/node"
"github.com/simple-rules/harmony-benchmark/p2p"
"github.com/simple-rules/harmony-benchmark/pow"
"github.com/simple-rules/harmony-benchmark/proto"
proto_identity "github.com/simple-rules/harmony-benchmark/proto/identity"
)
@ -30,6 +33,8 @@ func (IDC *IdentityChain) IdentityChainHandler(conn net.Conn) {
if msgCategory != proto.IDENTITY {
IDC.log.Error("Identity Chain Recieved incorrect protocol message")
os.Exit(1)
} else {
fmt.Println("Message category is correct")
}
msgType, err := proto.GetMessageType(content)
if err != nil {
@ -43,12 +48,20 @@ func (IDC *IdentityChain) IdentityChainHandler(conn net.Conn) {
}
switch msgCategory {
case proto.IDENTITY:
actionType := proto_identity.MessageType(msgType)
actionType := proto_identity.IdentityMessageType(msgType)
switch actionType {
case proto_identity.REGISTER:
IDC.registerIdentity(msgPayload)
case proto_identity.ANNOUNCE:
IDC.acceptNewConnection(msgPayload)
case proto_identity.IDENTITY:
idMsgType, err := proto_identity.GetIdentityMessageType(msgPayload)
if err != nil {
fmt.Println("Error finding the identity message type")
}
switch idMsgType {
case proto_identity.REGISTER:
IDC.registerIdentity(msgPayload)
case proto_identity.ANNOUNCE:
IDC.acceptNewConnection(msgPayload)
}
}
}
@ -61,23 +74,23 @@ func (IDC *IdentityChain) registerIdentity(msgPayload []byte) {
} else {
fmt.Println("identity payload read")
}
fmt.Println("we are now registering identities")
//reconstruct the challenge and check whether its correct
offset := 0
//proof := payload[offset : offset+64]
offset = offset + 64
Node := node.DeserializeNode(payload[offset:])
fmt.Println(Node.Self)
os.Exit(1)
// id := []byte(IDC.PowMap[Node.Self])
// req := pow.NewRequest(5, id)
// ok, _ := pow.Check(req, string(proof), []byte("This is blockchash data"))
// if ok {
// IDC.PendingIdentities = append(IDC.PendingIdentities, Node)
// fmt.Println(len(IDC.PendingIdentities)) //Fix why IDC does not have log working.
// } else {
// fmt.Println("identity proof of work not accepted")
// }
proof := payload[offset : offset+32]
offset = offset + 32
Node := node.DeserializeWaitNode(payload[offset:])
id := int(IDC.PowMap[Node.Self])
req := pow.NewRequest(5, []byte(strconv.Itoa(id)))
ok, err := pow.Check(req, string(proof), []byte(""))
fmt.Println(err)
if ok {
fmt.Println("Proof of work accepted")
IDC.PendingIdentities = append(IDC.PendingIdentities, Node)
fmt.Println(len(IDC.PendingIdentities)) //Fix why IDC does not have log working.
} else {
fmt.Println("identity proof of work not accepted")
}
}
func (IDC *IdentityChain) acceptNewConnection(msgPayload []byte) {
@ -85,19 +98,25 @@ func (IDC *IdentityChain) acceptNewConnection(msgPayload []byte) {
identityPayload, err := proto_identity.GetIdentityMessagePayload(msgPayload)
if err != nil {
fmt.Println("There was a error in reading the identity payload")
} else {
fmt.Println("accepted new connection")
}
Node := node.DeserializeNode(identityPayload)
fmt.Println("Sleeping for 2 secs ...")
time.Sleep(5 * time.Second)
Node := node.DeserializeWaitNode(identityPayload)
buffer := bytes.NewBuffer([]byte{})
challengeNonce := uint32(rand.Intn(1000))
src := rand.NewSource(time.Now().UnixNano())
rnd := rand.New(src)
challengeNonce := uint32(rnd.Int31())
//challengeNonce := uint32(rand.Intn(1000)) //fix so that different nonce is sent everytime.
fmt.Println("Challenge Nonce Sent:")
fmt.Println(challengeNonce)
IDC.PowMap[Node.Self] = challengeNonce
// 4 byte length of challengeNonce
// 64 byte length of challenge
fourBytes := make([]byte, 64)
fourBytes := make([]byte, 4)
binary.BigEndian.PutUint32(fourBytes, challengeNonce)
buffer.Write(fourBytes)
sendMsgPayload := buffer.Bytes()
// 32 byte block hash
// buffer.Write(prevBlockHash)
// The message is missing previous BlockHash, this is because we don't actively maintain a identitychain
@ -106,7 +125,7 @@ func (IDC *IdentityChain) acceptNewConnection(msgPayload []byte) {
// Message should be encrypted and then signed to follow PKE.
//IDC should accept node publickey, encrypt the nonce and blockhash
// Then sign the message by own private key and send the message back.
msgToSend := proto_identity.ConstructIdentityMessage(proto_identity.REGISTER, sendMsgPayload)
fmt.Println("Done sleeping. Ready or not here i come!")
msgToSend := proto_identity.ConstructIdentityMessage(proto_identity.REGISTER, buffer.Bytes())
p2p.SendMessage(Node.Self, msgToSend)
}

@ -2,8 +2,11 @@ package node
import (
"bytes"
"encoding/binary"
"encoding/gob"
"fmt"
"net"
"strconv"
"sync"
"github.com/simple-rules/harmony-benchmark/crypto/pki"
@ -68,6 +71,7 @@ func (node *Node) getTransactionsForNewBlock(maxNumTxs int) ([]*blockchain.Trans
// Start a server and process the request by a handler.
func (node *Node) StartServer(port string) {
fmt.Println("Hello in server now")
node.log.Debug("Starting server", "node", node, "port", port)
node.listenOnPort(port)
@ -111,7 +115,8 @@ func (node *Node) countNumTransactionsInBlockchain() int {
//ConnectIdentityChain connects to identity chain
func (node *Node) ConnectIdentityChain() {
IDCPeer := node.IDCPeer
p2p.SendMessage(IDCPeer, identity.ConstructIdentityMessage(identity.ANNOUNCE, node.SerializeNode()))
p2p.SendMessage(IDCPeer, identity.ConstructIdentityMessage(identity.ANNOUNCE, node.SerializeWaitNode()))
return
}
//NewWaitNode is a way to initiate a waiting no
@ -119,6 +124,7 @@ func NewWaitNode(peer, IDCPeer p2p.Peer) Node {
node := Node{}
node.Self = peer
node.IDCPeer = IDCPeer
node.log = log.New()
return node
}
@ -152,40 +158,54 @@ func NewNodefromIDC(node Node, consensus *consensus.Consensus, db *db.LDBDatabas
return &node
}
func (node *Node) processPOWMessage(payload []byte) {
func (node *Node) processPOWMessage(message []byte) {
payload, err := identity.GetIdentityMessagePayload(message)
if err != nil {
fmt.Println("Could not read payload")
}
IDCPeer := node.IDCPeer
offset := 0
// 4 byte challenge nonce id
req := pow.NewRequest(5, payload[offset:offset+64])
proof, _ := pow.Fulfil(req, []byte("This is blockchash data")) //"some bound dat"
proofBytes := make([]byte, 64)
copy(proofBytes[:], proof)
// 4 byte challengeNonce id
challengeNonce := int(binary.BigEndian.Uint32(payload[offset : offset+4]))
offset += 4
fmt.Println(challengeNonce)
req := pow.NewRequest(5, []byte(strconv.Itoa(challengeNonce)))
proof, _ := pow.Fulfil(req, []byte("")) //"This could be blockhasdata"
buffer := bytes.NewBuffer([]byte{})
proofBytes := make([]byte, 32) //proof seems to be 32 byte here
copy(proofBytes[:], proof)
buffer.Write(proofBytes)
buffer.Write(node.SerializeNode())
buffer.Write(node.SerializeWaitNode())
msgPayload := buffer.Bytes()
p2p.SendMessage(IDCPeer, identity.ConstructIdentityMessage(identity.REGISTER, msgPayload))
}
//https://stackoverflow.com/questions/12854125/how-do-i-dump-the-struct-into-the-byte-array-without-reflection/12854659#12854659
//SerializeWaitNode serializes the node
func (node *Node) SerializeNode() []byte {
var result bytes.Buffer
encoder := gob.NewEncoder(&result)
err := encoder.Encode(node)
func (node *Node) SerializeWaitNode() []byte {
//Needs to escape the serialization of unexported fields
result := new(bytes.Buffer)
encoder := gob.NewEncoder(result)
err := encoder.Encode(node.Self)
if err != nil {
node.log.Error("Could not serialize node")
fmt.Println("Could not serialize node")
fmt.Println("ERROR", err)
//node.log.Error("Could not serialize node")
}
err = encoder.Encode(node.IDCPeer)
return result.Bytes()
}
// DeserializeWaitNode deserializes the node
func DeserializeNode(d []byte) *Node {
func DeserializeWaitNode(d []byte) *Node {
var wn Node
decoder := gob.NewDecoder(bytes.NewReader(d))
err := decoder.Decode(&wn)
r := bytes.NewBuffer(d)
decoder := gob.NewDecoder(r)
err := decoder.Decode(&wn.Self)
if err != nil {
log.Error("Could not de-serialize node")
}
err = decoder.Decode(&wn.IDCPeer)
if err != nil {
log.Error("Could not de-serialize node")
}

@ -3,6 +3,7 @@ package node
import (
"bytes"
"encoding/gob"
"fmt"
"net"
"os"
"strconv"
@ -63,6 +64,7 @@ func (node *Node) NodeHandler(conn net.Conn) {
messageType := proto_identity.MessageType(msgPayload[0])
switch messageType {
case proto_identity.REGISTER:
fmt.Println("received a identity message")
node.processPOWMessage(msgPayload)
case proto_identity.ANNOUNCE:
node.log.Error("Announce message should be sent to IdentityChain")

@ -1,82 +0,0 @@
package waitnode
import (
"bytes"
"crypto/sha256"
"encoding/gob"
"log"
"github.com/simple-rules/harmony-benchmark/p2p"
"github.com/simple-rules/harmony-benchmark/utils"
)
//WaitNode is for nodes waiting to join consensus
type WaitNode struct {
Peer p2p.Peer
ID uint16
SeedPeers p2p.Peer
}
// StartServer a server and process the request by a handler.
func (node *WaitNode) StartServer() {
log.Printf("Starting waitnode on server %s and port %s", node.Peer.Ip, node.Peer.Port)
}
// //ConnectIdentityChain connects to identity chain
// func (node *WaitNode) ConnectIdentityChain(peer p2p.Peer) {
// pow := NewProofOfWork(10)
// nonce := pow.Run()
// if pow.FinalNonce != uint32(nonce) {
// fmt.Println("Something wrong with POW")
// }
// p2p.SendMessage(peer, identity.ConstructIdentityMessage(identity.REGISTER, node.SerializeWaitNode()))
// }
//Constructs node-id by hashing the IP.
func calculateHash(num string) []byte {
var hashes [][]byte
hashes = append(hashes, utils.ConvertFixedDataIntoByteArray(num))
hash := sha256.Sum256(bytes.Join(hashes, []byte{}))
return hash[:]
}
// //SerializePOW serializes the node
// func SerializePOW(pow ProofOfWork) []byte {
// var result bytes.Buffer
// encoder := gob.NewEncoder(&pow)
// err := encoder.Encode(pow)
// if err != nil {
// log.Panic(err.Error())
// }
// return pow.Bytes()
// }
//SerializeWaitNode serializes the node
func (node *WaitNode) SerializeWaitNode() []byte {
var result bytes.Buffer
encoder := gob.NewEncoder(&result)
err := encoder.Encode(node)
if err != nil {
log.Panic(err.Error())
}
return result.Bytes()
}
// DeserializeWaitNode deserializes the node
func DeserializeWaitNode(d []byte) *WaitNode {
var wn WaitNode
decoder := gob.NewDecoder(bytes.NewReader(d))
err := decoder.Decode(&wn)
if err != nil {
log.Panic(err)
}
return &wn
}
// New Create a new Node
func New(Peer p2p.Peer) *WaitNode {
node := WaitNode{}
node.Peer = Peer
node.ID = utils.GetUniqueIdFromPeer(Peer)
return &node
}

@ -1,18 +0,0 @@
package waitnode
import (
"testing"
"github.com/simple-rules/harmony-benchmark/p2p"
)
func TestNewNode(test *testing.T) {
p := p2p.Peer{Ip: "127.0.0.1", Port: "8080"}
wn := New(p)
b := wn.SerializeWaitNode()
wnd := DeserializeWaitNode(b)
if *wn != *wnd {
test.Error("Serialization is not working")
}
}
Loading…
Cancel
Save