From ac3f19ba5eabeef734579c9f7ee8a19ffa90e9a2 Mon Sep 17 00:00:00 2001 From: Leo Chen Date: Wed, 21 Nov 2018 17:07:54 -0800 Subject: [PATCH 1/4] add join shard support in node add State variable in to indicate the state of the node INIT: node just boot-up, to contact beacon chain WAIT: node contacted beacon chain, ready to join shard JOIN: node joined shard OFFLINE: node offline Signed-off-by: Leo Chen --- benchmark.go | 6 ++++++ node/node.go | 27 +++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/benchmark.go b/benchmark.go index 4f0e83014..bbce1fd0a 100644 --- a/benchmark.go +++ b/benchmark.go @@ -203,6 +203,8 @@ func main() { // Temporary testing code, to be removed. currentNode.AddTestingAddresses(10000) + currentNode.State = node.WAIT + if consensus.IsLeader { if *accountModel { // Let consensus run @@ -223,6 +225,10 @@ func main() { currentNode.WaitForConsensusReady(consensus.ReadySignal) }() } + } else { + go func() { + currentNode.JoinShard(leader) + }() } currentNode.StartServer(*port) diff --git a/node/node.go b/node/node.go index 37fc116fe..c8b4ce858 100644 --- a/node/node.go +++ b/node/node.go @@ -24,10 +24,20 @@ import ( "github.com/harmony-one/harmony/log" "github.com/harmony-one/harmony/p2p" proto_identity "github.com/harmony-one/harmony/proto/identity" + proto_node "github.com/harmony-one/harmony/proto/node" "github.com/jinzhu/copier" ) +type NodeState byte + +const ( + INIT NodeState = iota // Node just started, before contacting BeaconChain + WAIT // Node contacted BeaconChain, wait to join Shard + JOIN // Node joined Shard, ready for consensus + OFFLINE // Node is offline +) + type NetworkNode struct { SelfPeer p2p.Peer IDCPeer p2p.Peer @@ -57,6 +67,7 @@ type Node struct { SyncNode bool // TODO(minhdoan): Remove it later. chain *core.BlockChain // Account Model Neighbors map[string]*p2p.Peer // All the neighbor nodes, key is the sha256 of Peer IP/Port + State NodeState // State of the Node // Account Model Chain *core.BlockChain @@ -235,6 +246,7 @@ func New(consensus *bft.Consensus, db *hdb.LDBDatabase) *Node { // Logger node.log = log.New() node.Neighbors = make(map[string]*p2p.Peer) + node.State = INIT return &node } @@ -260,3 +272,18 @@ func (node *Node) AddPeers(peers []p2p.Peer) int { } return count } + +func (node *Node) JoinShard(leader p2p.Peer) { + // try to join the shard, with 10 minutes time-out + backoff := p2p.NewExpBackoff(500*time.Millisecond, 10*time.Minute, 2) + + for node.State == WAIT { + backoff.Sleep() + ping := proto_node.NewPingMessage(node.SelfPeer) + buffer := ping.ConstructPingMessage() + + p2p.SendMessage(leader, buffer) + node.log.Debug("Sent ping message") + } + +} From ed48168a0f5e0666af6cda54b7ea89a6dceab080 Mon Sep 17 00:00:00 2001 From: Leo Chen Date: Wed, 21 Nov 2018 18:22:16 -0800 Subject: [PATCH 2/4] use []byte to marshal/unmarshal pubkey in ping/pong messages go test passed Signed-off-by: Leo Chen --- proto/node/pingpong.go | 18 ++++++++++++++---- proto/node/pingpong_test.go | 2 +- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/proto/node/pingpong.go b/proto/node/pingpong.go index af0dbddff..3f17b5fac 100644 --- a/proto/node/pingpong.go +++ b/proto/node/pingpong.go @@ -22,7 +22,7 @@ import ( type nodeInfo struct { IP string Port string - PubKey string + PubKey []byte } type PingMessageType struct { @@ -50,10 +50,16 @@ func (p PongMessageType) String() string { func NewPingMessage(peer p2p.Peer) *PingMessageType { ping := new(PingMessageType) + var err error ping.Version = PROTOCOL_VERSION ping.Node.IP = peer.Ip ping.Node.Port = peer.Port - ping.Node.PubKey = fmt.Sprintf("%v", peer.PubKey) + ping.Node.PubKey, err = peer.PubKey.MarshalBinary() + + if err != nil { + fmt.Printf("Error Marshall PubKey: %v", err) + return nil + } return ping } @@ -64,12 +70,16 @@ func NewPongMessage(peers []p2p.Peer) *PongMessageType { pong.Version = PROTOCOL_VERSION pong.Peers = make([]nodeInfo, 0) + var err error for _, p := range peers { n := nodeInfo{} n.IP = p.Ip n.Port = p.Port - n.PubKey = fmt.Sprintf("%v", p.PubKey) - + n.PubKey, err = p.PubKey.MarshalBinary() + if err != nil { + fmt.Printf("Error Marshall PubKey: %v", err) + continue + } pong.Peers = append(pong.Peers, n) } diff --git a/proto/node/pingpong_test.go b/proto/node/pingpong_test.go index 1d6e71294..72542fde4 100644 --- a/proto/node/pingpong_test.go +++ b/proto/node/pingpong_test.go @@ -19,7 +19,7 @@ var ( Port: "9999", PubKey: pubKey1, } - e1 = "1=>127.0.0.1:9999/5ad91c4440d3a0e83df49ff4a0243da1edf2ec2d9376ed58ea7ac6bc9d745ae4" + e1 = "1=>127.0.0.1:9999/[90 217 28 68 64 211 160 232 61 244 159 244 160 36 61 161 237 242 236 45 147 118 237 88 234 122 198 188 157 116 90 228]" priKey2 = crypto.Ed25519Curve.Scalar().SetInt64(int64(999)) pubKey2 = pki.GetPublicKeyFromScalar(priKey2) From 443feac41d6c6ceb49a4d4f245a1fff79fa86419 Mon Sep 17 00:00:00 2001 From: Leo Chen Date: Wed, 21 Nov 2018 18:59:53 -0800 Subject: [PATCH 3/4] handle ping/pong message properly add peers into neighbors todo: add pubkeys todo: broadcast pong messages to all neighbors Signed-off-by: Leo Chen --- node/node_handler.go | 48 ++++++++++++++++++++++++++++++++++++++++++++ node/node_test.go | 2 +- 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/node/node_handler.go b/node/node_handler.go index afa0b1639..e72b03732 100644 --- a/node/node_handler.go +++ b/node/node_handler.go @@ -15,6 +15,7 @@ import ( "time" "github.com/harmony-one/harmony/blockchain" + hmy_crypto "github.com/harmony-one/harmony/crypto" "github.com/harmony-one/harmony/p2p" "github.com/harmony-one/harmony/proto" "github.com/harmony-one/harmony/proto/client" @@ -510,6 +511,33 @@ func (node *Node) pingMessageHandler(msgPayload []byte) { return } node.log.Info("Ping", "Msg", ping) + + peer := new(p2p.Peer) + peer.Ip = ping.Node.IP + peer.Port = ping.Node.Port + + peer.PubKey = hmy_crypto.Ed25519Curve.Point() + err = peer.PubKey.UnmarshalBinary(ping.Node.PubKey[:]) + if err != nil { + node.log.Error("UnmarshalBinary Failed", "error", err) + return + } + + node.AddPeers([]p2p.Peer{*peer}) + // TODO: add public key to consensus.pubkeys + + // Send a Pong message back + peers := make([]p2p.Peer, 0) + for _, v := range node.Neighbors { + peers = append(peers, *v) + } + pong := proto_node.NewPongMessage(peers) + buffer := pong.ConstructPongMessage() + + p2p.SendMessage(*peer, buffer) + + // TODO: broadcast pong messages to all neighbors + return } @@ -520,5 +548,25 @@ func (node *Node) pongMessageHandler(msgPayload []byte) { return } node.log.Info("Pong", "Msg", pong) + + peers := make([]p2p.Peer, 0) + + for _, p := range pong.Peers { + peer := new(p2p.Peer) + peer.Ip = p.IP + peer.Port = p.Port + + peer.PubKey = hmy_crypto.Ed25519Curve.Point() + err = peer.PubKey.UnmarshalBinary(p.PubKey[:]) + if err != nil { + node.log.Error("UnmarshalBinary Failed", "error", err) + continue + } + peers = append(peers, *peer) + } + + node.AddPeers(peers) + // TODO: add public key to consensus.pubkeys + return } diff --git a/node/node_test.go b/node/node_test.go index e637131b5..e2e2a0663 100644 --- a/node/node_test.go +++ b/node/node_test.go @@ -154,7 +154,7 @@ func TestPingPongHandler(test *testing.T) { node := New(consensus, nil) - go sendPingMessage(leader) + // go sendPingMessage(leader) go sendPongMessage(leader) go exitServer() From aa1648f581d0e3bb41abed06e52207f6753f6a1e Mon Sep 17 00:00:00 2001 From: Leo Chen Date: Thu, 22 Nov 2018 12:57:22 -0800 Subject: [PATCH 4/4] add a build step in test_before_submit.sh Signed-off-by: Leo Chen --- test_before_submit.sh | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/test_before_submit.sh b/test_before_submit.sh index c9496cb5b..394957157 100755 --- a/test_before_submit.sh +++ b/test_before_submit.sh @@ -1,6 +1,20 @@ #!/bin/bash DIRROOT=$(dirname $0) +OS=$(uname -s) go test ./... -$DIRROOT/.travis.gofmt.sh + +pushd $DIRROOT +./.travis.gofmt.sh + +case $OS in + Darwin) + ./go_executable_build.sh -o darwin + ;; + Linux) + ./go_executable_build.sh + ;; +esac + +popd