From 31a1162733f22c86152ed1d2e0d8b92914c0a6a8 Mon Sep 17 00:00:00 2001 From: Ethan Buchman <ethan@coinculture.info> Date: Sat, 5 Mar 2016 23:18:01 -0500 Subject: [PATCH] add genesis hash to p2p handshake. closes #56 --- .../tendermint/tendermint/node/node.go | 6 ++- .../tendermint/tendermint/node/node_test.go | 49 +++++++++++++++++++ .../tendermint/tendermint/p2p/switch.go | 2 +- .../tendermint/tendermint/types/node.go | 12 ++++- 4 files changed, 64 insertions(+), 5 deletions(-) diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/node/node.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/node/node.go index 7c50d842..7185f88a 100644 --- a/Godeps/_workspace/src/github.com/tendermint/tendermint/node/node.go +++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/node/node.go @@ -152,7 +152,8 @@ func NewNode(privValidator *types.PrivValidator) *Node { // Call Start() after adding the listeners. func (n *Node) Start() error { n.book.Start() - n.sw.SetNodeInfo(makeNodeInfo(n.sw, n.privKey)) + genState := sm.MakeGenesisState(dbm.NewMemDB(), n.genDoc) + n.sw.SetNodeInfo(makeNodeInfo(n.sw, n.privKey, genState.Hash())) n.sw.SetNodePrivKey(n.privKey) _, err := n.sw.Start() return err @@ -247,12 +248,13 @@ func (n *Node) EventSwitch() *events.EventSwitch { return n.evsw } -func makeNodeInfo(sw *p2p.Switch, privKey acm.PrivKeyEd25519) *types.NodeInfo { +func makeNodeInfo(sw *p2p.Switch, privKey acm.PrivKeyEd25519, genesisRoot []byte) *types.NodeInfo { nodeInfo := &types.NodeInfo{ PubKey: privKey.PubKey().(acm.PubKeyEd25519), Moniker: config.GetString("moniker"), ChainID: config.GetString("chain_id"), + Genesis: genesisRoot, Version: types.Versions{ Tendermint: Version, P2P: p2p.Version, diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/node/node_test.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/node/node_test.go index 84eb1014..a77d4ac9 100644 --- a/Godeps/_workspace/src/github.com/tendermint/tendermint/node/node_test.go +++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/node/node_test.go @@ -1,11 +1,17 @@ package node import ( + "strconv" + "strings" "testing" "time" _ "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/config/tendermint_test" + dbm "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/db" "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/p2p" + sm "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/state" + stypes "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/state/types" + "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/types" ) func TestNodeStartStop(t *testing.T) { @@ -28,3 +34,46 @@ func TestNodeStartStop(t *testing.T) { t.Fatal("timed out waiting for shutdown") } } + +func TestCompatibleNodeInfo(t *testing.T) { + sw := p2p.NewSwitch() + priv1, priv2 := types.GenPrivValidator(), types.GenPrivValidator() + genDoc1, _, _ := stypes.RandGenesisDoc(5, true, 100, 4, true, 1000) + genState1 := sm.MakeGenesisState(dbm.NewMemDB(), genDoc1) + genDoc2, _, _ := stypes.RandGenesisDoc(5, true, 100, 4, true, 1000) + genState2 := sm.MakeGenesisState(dbm.NewMemDB(), genDoc2) + + // incompatible genesis states + n1 := makeNodeInfo(sw, priv1.PrivKey, genState1.Hash()) + n2 := makeNodeInfo(sw, priv2.PrivKey, genState2.Hash()) + if err := n1.CompatibleWith(n2); err == nil { + t.Fatalf("Expected nodes to be incompatible due to genesis state") + } + + // incompatible chain ids + copy(n2.Genesis, n1.Genesis) + n2.ChainID = "incryptowetrust" + if err := n1.CompatibleWith(n2); err == nil { + t.Fatalf("Expected nodes to be incompatible due to chain ID") + } + + // incompatible versions + n2.ChainID = n1.ChainID + v := n1.Version.Tendermint + spl := strings.Split(v, ".") + n, err := strconv.Atoi(spl[0]) + if err != nil { + t.Fatalf(err.Error()) + } + spl[0] = strconv.Itoa(n + 1) + n2.Version.Tendermint = strings.Join(spl, ".") + if err := n1.CompatibleWith(n2); err == nil { + t.Fatalf("Expected nodes to be incompatible due to major version") + } + + // compatible + n2.Version.Tendermint = n1.Version.Tendermint + if err := n1.CompatibleWith(n2); err != nil { + t.Fatalf("Expected nodes to be compatible") + } +} diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/p2p/switch.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/p2p/switch.go index 661aee12..fb03ca8e 100644 --- a/Godeps/_workspace/src/github.com/tendermint/tendermint/p2p/switch.go +++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/p2p/switch.go @@ -220,7 +220,7 @@ func (sw *Switch) AddPeerWithConnection(conn net.Conn, outbound bool) (*Peer, er sconn.Close() return nil, fmt.Errorf("Ignoring connection from self") } - // Check version, chain id + // Check version, chain id, genesis hash if err := sw.nodeInfo.CompatibleWith(peerNodeInfo); err != nil { sconn.Close() return nil, err diff --git a/Godeps/_workspace/src/github.com/tendermint/tendermint/types/node.go b/Godeps/_workspace/src/github.com/tendermint/tendermint/types/node.go index 8e320cba..52a93c5c 100644 --- a/Godeps/_workspace/src/github.com/tendermint/tendermint/types/node.go +++ b/Godeps/_workspace/src/github.com/tendermint/tendermint/types/node.go @@ -1,15 +1,18 @@ package types import ( + "bytes" "fmt" - acm "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/account" "strings" + + acm "github.com/eris-ltd/eris-db/Godeps/_workspace/src/github.com/tendermint/tendermint/account" ) type NodeInfo struct { PubKey acm.PubKeyEd25519 `json:"pub_key"` Moniker string `json:"moniker"` ChainID string `json:"chain_id"` + Genesis []byte `json:"genesis"` Host string `json:"host"` P2PPort uint16 `json:"p2p_port"` RPCPort uint16 `json:"rpc_port"` @@ -25,7 +28,7 @@ type Versions struct { Wire string `json:"wire"` } -// CONTRACT: two nodes with the same Tendermint major and minor version and with the same ChainID are compatible +// CONTRACT: two nodes with the same Tendermint major and minor version and with the same ChainID and Genesis are compatible func (ni *NodeInfo) CompatibleWith(no *NodeInfo) error { iM, im, _, ie := splitVersion(ni.Version.Tendermint) oM, om, _, oe := splitVersion(no.Version.Tendermint) @@ -55,6 +58,11 @@ func (ni *NodeInfo) CompatibleWith(no *NodeInfo) error { return fmt.Errorf("Peer is on a different chain_id. Got %v, expected %v", no.ChainID, ni.ChainID) } + // nodes must share a common genesis root + if !bytes.Equal(ni.Genesis, no.Genesis) { + return fmt.Errorf("Peer has a different genesis root. Got %v, expected %v", no.Genesis, ni.Genesis) + } + return nil } -- GitLab