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