Browse Source

Put a SecretConnection before the MConnection; Node Priv/PubKeys

pull/111/merge
Jae Kwon 9 years ago
parent
commit
fd64547ce7
7 changed files with 88 additions and 29 deletions
  1. +7
    -0
      account/priv_key.go
  2. +10
    -0
      account/pub_key.go
  3. +14
    -3
      node/node.go
  4. +2
    -3
      p2p/secret_connection.go
  5. +37
    -14
      p2p/switch.go
  6. +8
    -0
      p2p/switch_test.go
  7. +10
    -9
      types/node.go

+ 7
- 0
account/priv_key.go View File

@ -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[:])
}

+ 10
- 0
account/pub_key.go View File

@ -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
}
}

+ 14
- 3
node/node.go View File

@ -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(),
}


+ 2
- 3
p2p/secret_connection.go View File

@ -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"


+ 37
- 14
p2p/switch.go View File

@ -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
}


+ 8
- 0
p2p/switch_test.go View File

@ -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()


+ 10
- 9
types/node.go View File

@ -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…
Cancel
Save