Put a SecretConnection before the MConnection; Node Priv/PubKeys
This commit is contained in:
parent
a8d03bddc9
commit
fd64547ce7
|
@ -54,3 +54,10 @@ func (privKey PrivKeyEd25519) ToCurve25519() *[32]byte {
|
|||
func (privKey PrivKeyEd25519) String() string {
|
||||
return Fmt("PrivKeyEd25519{*****}")
|
||||
}
|
||||
|
||||
func GenPrivKeyEd25519() PrivKeyEd25519 {
|
||||
privKeyBytes := new([64]byte)
|
||||
copy(privKeyBytes[:32], CRandBytes(32))
|
||||
ed25519.MakePublicKey(privKeyBytes)
|
||||
return PrivKeyEd25519(privKeyBytes[:])
|
||||
}
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package account
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
|
||||
"github.com/tendermint/tendermint/Godeps/_workspace/src/github.com/tendermint/ed25519"
|
||||
"github.com/tendermint/tendermint/Godeps/_workspace/src/github.com/tendermint/ed25519/extra25519"
|
||||
"github.com/tendermint/tendermint/binary"
|
||||
|
@ -71,3 +73,11 @@ func (pubKey PubKeyEd25519) ValidateBasic() error {
|
|||
func (pubKey PubKeyEd25519) String() string {
|
||||
return Fmt("PubKeyEd25519{%X}", []byte(pubKey))
|
||||
}
|
||||
|
||||
func (pubKey PubKeyEd25519) Equals(other PubKey) bool {
|
||||
if _, ok := other.(PubKeyEd25519); ok {
|
||||
return bytes.Equal(pubKey, other.(PubKeyEd25519))
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
|
17
node/node.go
17
node/node.go
|
@ -12,6 +12,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/tendermint/tendermint/Godeps/_workspace/src/code.google.com/p/go-uuid/uuid"
|
||||
acm "github.com/tendermint/tendermint/account"
|
||||
"github.com/tendermint/tendermint/binary"
|
||||
bc "github.com/tendermint/tendermint/blockchain"
|
||||
. "github.com/tendermint/tendermint/common"
|
||||
|
@ -46,6 +47,7 @@ type Node struct {
|
|||
consensusReactor *consensus.ConsensusReactor
|
||||
privValidator *sm.PrivValidator
|
||||
genDoc *sm.GenesisDoc
|
||||
privKey acm.PrivKeyEd25519
|
||||
}
|
||||
|
||||
func NewNode() *Node {
|
||||
|
@ -92,6 +94,10 @@ func NewNode() *Node {
|
|||
log.Info("Generated PrivValidator", "file", privValidatorFile)
|
||||
}
|
||||
|
||||
// Generate node PrivKey
|
||||
privKey := acm.GenPrivKeyEd25519()
|
||||
|
||||
// Make event switch
|
||||
eventSwitch := new(events.EventSwitch)
|
||||
eventSwitch.Start()
|
||||
|
||||
|
@ -113,6 +119,7 @@ func NewNode() *Node {
|
|||
consensusReactor.SetPrivValidator(privValidator)
|
||||
}
|
||||
|
||||
// Make Switch
|
||||
sw := p2p.NewSwitch()
|
||||
sw.AddReactor("PEX", pexReactor)
|
||||
sw.AddReactor("MEMPOOL", mempoolReactor)
|
||||
|
@ -135,6 +142,7 @@ func NewNode() *Node {
|
|||
consensusReactor: consensusReactor,
|
||||
privValidator: privValidator,
|
||||
genDoc: genDoc,
|
||||
privKey: privKey,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -142,7 +150,8 @@ func NewNode() *Node {
|
|||
func (n *Node) Start() {
|
||||
log.Info("Starting Node", "chainID", config.GetString("chain_id"))
|
||||
n.book.Start()
|
||||
n.sw.SetNodeInfo(makeNodeInfo(n.sw))
|
||||
n.sw.SetNodeInfo(makeNodeInfo(n.sw, n.privKey))
|
||||
n.sw.SetNodePrivKey(n.privKey)
|
||||
n.sw.Start()
|
||||
}
|
||||
|
||||
|
@ -237,10 +246,12 @@ func (n *Node) EventSwitch() *events.EventSwitch {
|
|||
return n.evsw
|
||||
}
|
||||
|
||||
func makeNodeInfo(sw *p2p.Switch) *types.NodeInfo {
|
||||
func makeNodeInfo(sw *p2p.Switch, privKey acm.PrivKeyEd25519) *types.NodeInfo {
|
||||
|
||||
nodeInfo := &types.NodeInfo{
|
||||
ChainID: config.GetString("chain_id"),
|
||||
PubKey: privKey.PubKey().(acm.PubKeyEd25519),
|
||||
Moniker: config.GetString("moniker"),
|
||||
ChainID: config.GetString("chain_id"),
|
||||
Version: config.GetString("version"),
|
||||
UUID: uuid.New(),
|
||||
}
|
||||
|
|
|
@ -9,11 +9,10 @@ import (
|
|||
"crypto/sha256"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"net"
|
||||
"time"
|
||||
//"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"golang.org/x/crypto/nacl/box"
|
||||
"golang.org/x/crypto/nacl/secretbox"
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
acm "github.com/tendermint/tendermint/account"
|
||||
. "github.com/tendermint/tendermint/common"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
)
|
||||
|
@ -48,7 +49,8 @@ type Switch struct {
|
|||
peers *PeerSet
|
||||
dialing *CMap
|
||||
running uint32
|
||||
nodeInfo *types.NodeInfo // our node info
|
||||
nodeInfo *types.NodeInfo // our node info
|
||||
nodePrivKey acm.PrivKeyEd25519 // our node privkey
|
||||
}
|
||||
|
||||
var (
|
||||
|
@ -70,6 +72,7 @@ func NewSwitch() *Switch {
|
|||
dialing: NewCMap(),
|
||||
running: 0,
|
||||
nodeInfo: nil,
|
||||
nodePrivKey: nil,
|
||||
}
|
||||
return sw
|
||||
}
|
||||
|
@ -126,6 +129,15 @@ func (sw *Switch) NodeInfo() *types.NodeInfo {
|
|||
return sw.nodeInfo
|
||||
}
|
||||
|
||||
// Not goroutine safe.
|
||||
// NOTE: Overwrites sw.nodeInfo.PubKey
|
||||
func (sw *Switch) SetNodePrivKey(nodePrivKey acm.PrivKeyEd25519) {
|
||||
sw.nodePrivKey = nodePrivKey
|
||||
if sw.nodeInfo != nil {
|
||||
sw.nodeInfo.PubKey = nodePrivKey.PubKey().(acm.PubKeyEd25519)
|
||||
}
|
||||
}
|
||||
|
||||
func (sw *Switch) Start() {
|
||||
if atomic.CompareAndSwapUint32(&sw.running, 0, 1) {
|
||||
// Start reactors
|
||||
|
@ -165,40 +177,51 @@ func (sw *Switch) Stop() {
|
|||
// NOTE: This performs a blocking handshake before the peer is added.
|
||||
// CONTRACT: Iff error is returned, peer is nil, and conn is immediately closed.
|
||||
func (sw *Switch) AddPeerWithConnection(conn net.Conn, outbound bool) (*Peer, error) {
|
||||
// First, perform handshake
|
||||
peerNodeInfo, err := peerHandshake(conn, sw.nodeInfo)
|
||||
// First, encrypt the connection.
|
||||
sconn, err := MakeSecretConnection(conn, sw.nodePrivKey)
|
||||
if err != nil {
|
||||
conn.Close()
|
||||
return nil, err
|
||||
}
|
||||
// check version, chain id
|
||||
// Then, perform node handshake
|
||||
peerNodeInfo, err := peerHandshake(sconn, sw.nodeInfo)
|
||||
if err != nil {
|
||||
sconn.Close()
|
||||
return nil, err
|
||||
}
|
||||
// Check that the professed PubKey matches the sconn's.
|
||||
if !peerNodeInfo.PubKey.Equals(sconn.RemotePubKey()) {
|
||||
sconn.Close()
|
||||
return nil, fmt.Errorf("Ignoring connection with unmatching pubkey: %v vs %v",
|
||||
peerNodeInfo.PubKey, sconn.RemotePubKey())
|
||||
}
|
||||
// Check version, chain id
|
||||
if err := sw.nodeInfo.CompatibleWith(peerNodeInfo); err != nil {
|
||||
conn.Close()
|
||||
sconn.Close()
|
||||
return nil, err
|
||||
}
|
||||
// avoid self
|
||||
// Avoid self
|
||||
if peerNodeInfo.UUID == sw.nodeInfo.UUID {
|
||||
conn.Close()
|
||||
sconn.Close()
|
||||
return nil, fmt.Errorf("Ignoring connection from self")
|
||||
}
|
||||
|
||||
// the peerNodeInfo is not verified,
|
||||
// so we overwrite the IP with that from the conn
|
||||
// The peerNodeInfo is not verified, so overwrite.
|
||||
// Overwrite the IP with that from the conn
|
||||
// and if we dialed out, the port too
|
||||
// everything else we just have to trust
|
||||
ip, port, _ := net.SplitHostPort(conn.RemoteAddr().String())
|
||||
// Everything else we just have to trust
|
||||
ip, port, _ := net.SplitHostPort(sconn.RemoteAddr().String())
|
||||
peerNodeInfo.Host = ip
|
||||
if outbound {
|
||||
porti, _ := strconv.Atoi(port)
|
||||
peerNodeInfo.P2PPort = uint16(porti)
|
||||
}
|
||||
peer := newPeer(conn, peerNodeInfo, outbound, sw.reactorsByCh, sw.chDescs, sw.StopPeerForError)
|
||||
peer := newPeer(sconn, peerNodeInfo, outbound, sw.reactorsByCh, sw.chDescs, sw.StopPeerForError)
|
||||
|
||||
// Add the peer to .peers
|
||||
// ignore if duplicate or if we already have too many for that IP range
|
||||
if err := sw.peers.Add(peer); err != nil {
|
||||
log.Info("Ignoring peer", "error", err, "peer", peer)
|
||||
peer.stop() // will also close conn
|
||||
peer.stop() // will also close sconn
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
acm "github.com/tendermint/tendermint/account"
|
||||
"github.com/tendermint/tendermint/binary"
|
||||
. "github.com/tendermint/tendermint/common"
|
||||
"github.com/tendermint/tendermint/types"
|
||||
|
@ -74,21 +75,28 @@ func (tr *TestReactor) Receive(chId byte, peer *Peer, msgBytes []byte) {
|
|||
// convenience method for creating two switches connected to each other.
|
||||
func makeSwitchPair(t testing.TB, initSwitch func(*Switch) *Switch) (*Switch, *Switch) {
|
||||
|
||||
s1PrivKey := acm.GenPrivKeyEd25519()
|
||||
s2PrivKey := acm.GenPrivKeyEd25519()
|
||||
|
||||
// Create two switches that will be interconnected.
|
||||
s1 := initSwitch(NewSwitch())
|
||||
s1.SetNodeInfo(&types.NodeInfo{
|
||||
PubKey: s1PrivKey.PubKey().(acm.PubKeyEd25519),
|
||||
Moniker: "switch1",
|
||||
ChainID: "testing",
|
||||
Version: "123.123.123",
|
||||
UUID: uuid.New(),
|
||||
})
|
||||
s1.SetNodePrivKey(s1PrivKey)
|
||||
s2 := initSwitch(NewSwitch())
|
||||
s2.SetNodeInfo(&types.NodeInfo{
|
||||
PubKey: s2PrivKey.PubKey().(acm.PubKeyEd25519),
|
||||
Moniker: "switch2",
|
||||
ChainID: "testing",
|
||||
Version: "123.123.123",
|
||||
UUID: uuid.New(),
|
||||
})
|
||||
s2.SetNodePrivKey(s2PrivKey)
|
||||
|
||||
// Start switches
|
||||
s1.Start()
|
||||
|
|
|
@ -2,19 +2,20 @@ package types
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
acm "github.com/tendermint/tendermint/account"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type NodeInfo struct {
|
||||
Moniker string `json:"moniker"`
|
||||
ChainID string `json:"chain_id"`
|
||||
Version string `json:"version"`
|
||||
Revision string `json:"revision"`
|
||||
|
||||
UUID string `json:"uuid"`
|
||||
Host string `json:"host"`
|
||||
P2PPort uint16 `json:"p2p_port"`
|
||||
RPCPort uint16 `json:"rpc_port"`
|
||||
PubKey acm.PubKeyEd25519 `json:"pub_key"`
|
||||
Moniker string `json:"moniker"`
|
||||
ChainID string `json:"chain_id"`
|
||||
Version string `json:"version"`
|
||||
Revision string `json:"revision"`
|
||||
UUID string `json:"uuid"`
|
||||
Host string `json:"host"`
|
||||
P2PPort uint16 `json:"p2p_port"`
|
||||
RPCPort uint16 `json:"rpc_port"`
|
||||
}
|
||||
|
||||
func (ni *NodeInfo) CompatibleWith(no *NodeInfo) error {
|
||||
|
|
Loading…
Reference in New Issue