Browse Source

p2p: PrivKey need not be Ed25519

pull/1048/head
Ethan Buchman 7 years ago
parent
commit
528154f1a2
9 changed files with 56 additions and 59 deletions
  1. +9
    -10
      node/node.go
  2. +0
    -1
      p2p/README.md
  3. +4
    -4
      p2p/peer.go
  4. +9
    -9
      p2p/peer_test.go
  5. +8
    -8
      p2p/secret_connection.go
  6. +7
    -8
      p2p/secret_connection_test.go
  7. +9
    -9
      p2p/switch.go
  8. +3
    -3
      p2p/switch_test.go
  9. +7
    -7
      p2p/types.go

+ 9
- 10
node/node.go View File

@ -96,7 +96,6 @@ type Node struct {
privValidator types.PrivValidator // local node's validator key privValidator types.PrivValidator // local node's validator key
// network // network
privKey crypto.PrivKeyEd25519 // local node's p2p key
sw *p2p.Switch // p2p connections sw *p2p.Switch // p2p connections
addrBook *p2p.AddrBook // known peers addrBook *p2p.AddrBook // known peers
trustMetricStore *trust.TrustMetricStore // trust metrics for all peers trustMetricStore *trust.TrustMetricStore // trust metrics for all peers
@ -170,9 +169,6 @@ func NewNode(config *cfg.Config,
// reload the state (it may have been updated by the handshake) // reload the state (it may have been updated by the handshake)
state = sm.LoadState(stateDB) state = sm.LoadState(stateDB)
// Generate node PrivKey
privKey := crypto.GenPrivKeyEd25519()
// Decide whether to fast-sync or not // Decide whether to fast-sync or not
// We don't fast-sync when the only validator is us. // We don't fast-sync when the only validator is us.
fastSync := config.FastSync fastSync := config.FastSync
@ -275,7 +271,7 @@ func NewNode(config *cfg.Config,
} }
return nil return nil
}) })
sw.SetPubKeyFilter(func(pubkey crypto.PubKeyEd25519) error {
sw.SetPubKeyFilter(func(pubkey crypto.PubKey) error {
resQuery, err := proxyApp.Query().QuerySync(abci.RequestQuery{Path: cmn.Fmt("/p2p/filter/pubkey/%X", pubkey.Bytes())}) resQuery, err := proxyApp.Query().QuerySync(abci.RequestQuery{Path: cmn.Fmt("/p2p/filter/pubkey/%X", pubkey.Bytes())})
if err != nil { if err != nil {
return err return err
@ -328,7 +324,6 @@ func NewNode(config *cfg.Config,
genesisDoc: genDoc, genesisDoc: genDoc,
privValidator: privValidator, privValidator: privValidator,
privKey: privKey,
sw: sw, sw: sw,
addrBook: addrBook, addrBook: addrBook,
trustMetricStore: trustMetricStore, trustMetricStore: trustMetricStore,
@ -371,9 +366,13 @@ func (n *Node) OnStart() error {
l := p2p.NewDefaultListener(protocol, address, n.config.P2P.SkipUPNP, n.Logger.With("module", "p2p")) l := p2p.NewDefaultListener(protocol, address, n.config.P2P.SkipUPNP, n.Logger.With("module", "p2p"))
n.sw.AddListener(l) n.sw.AddListener(l)
// Generate node PrivKey
// TODO: Load
privKey := crypto.GenPrivKeyEd25519().Wrap()
// Start the switch // Start the switch
n.sw.SetNodeInfo(n.makeNodeInfo())
n.sw.SetNodePrivKey(n.privKey)
n.sw.SetNodeInfo(n.makeNodeInfo(privKey.PubKey()))
n.sw.SetNodePrivKey(privKey)
err = n.sw.Start() err = n.sw.Start()
if err != nil { if err != nil {
return err return err
@ -534,13 +533,13 @@ func (n *Node) ProxyApp() proxy.AppConns {
return n.proxyApp return n.proxyApp
} }
func (n *Node) makeNodeInfo() *p2p.NodeInfo {
func (n *Node) makeNodeInfo(pubKey crypto.PubKey) *p2p.NodeInfo {
txIndexerStatus := "on" txIndexerStatus := "on"
if _, ok := n.txIndexer.(*null.TxIndex); ok { if _, ok := n.txIndexer.(*null.TxIndex); ok {
txIndexerStatus = "off" txIndexerStatus = "off"
} }
nodeInfo := &p2p.NodeInfo{ nodeInfo := &p2p.NodeInfo{
PubKey: n.privKey.PubKey().Unwrap().(crypto.PubKeyEd25519),
PubKey: pubKey,
Moniker: n.config.Moniker, Moniker: n.config.Moniker,
Network: n.genesisDoc.ChainID, Network: n.genesisDoc.ChainID,
Version: version.Version, Version: version.Version,


+ 0
- 1
p2p/README.md View File

@ -11,4 +11,3 @@ See:
- [docs/node] for details about different types of nodes and how they should work - [docs/node] for details about different types of nodes and how they should work
- [docs/pex] for details on peer discovery and exchange - [docs/pex] for details on peer discovery and exchange
- [docs/config] for details on some config options - [docs/config] for details on some config options

+ 4
- 4
p2p/peer.go View File

@ -77,7 +77,7 @@ func DefaultPeerConfig() *PeerConfig {
} }
func newOutboundPeer(addr *NetAddress, reactorsByCh map[byte]Reactor, chDescs []*ChannelDescriptor, func newOutboundPeer(addr *NetAddress, reactorsByCh map[byte]Reactor, chDescs []*ChannelDescriptor,
onPeerError func(Peer, interface{}), ourNodePrivKey crypto.PrivKeyEd25519, config *PeerConfig) (*peer, error) {
onPeerError func(Peer, interface{}), ourNodePrivKey crypto.PrivKey, config *PeerConfig) (*peer, error) {
conn, err := dial(addr, config) conn, err := dial(addr, config)
if err != nil { if err != nil {
@ -95,13 +95,13 @@ func newOutboundPeer(addr *NetAddress, reactorsByCh map[byte]Reactor, chDescs []
} }
func newInboundPeer(conn net.Conn, reactorsByCh map[byte]Reactor, chDescs []*ChannelDescriptor, func newInboundPeer(conn net.Conn, reactorsByCh map[byte]Reactor, chDescs []*ChannelDescriptor,
onPeerError func(Peer, interface{}), ourNodePrivKey crypto.PrivKeyEd25519, config *PeerConfig) (*peer, error) {
onPeerError func(Peer, interface{}), ourNodePrivKey crypto.PrivKey, config *PeerConfig) (*peer, error) {
return newPeerFromConnAndConfig(conn, false, reactorsByCh, chDescs, onPeerError, ourNodePrivKey, config) return newPeerFromConnAndConfig(conn, false, reactorsByCh, chDescs, onPeerError, ourNodePrivKey, config)
} }
func newPeerFromConnAndConfig(rawConn net.Conn, outbound bool, reactorsByCh map[byte]Reactor, chDescs []*ChannelDescriptor, func newPeerFromConnAndConfig(rawConn net.Conn, outbound bool, reactorsByCh map[byte]Reactor, chDescs []*ChannelDescriptor,
onPeerError func(Peer, interface{}), ourNodePrivKey crypto.PrivKeyEd25519, config *PeerConfig) (*peer, error) {
onPeerError func(Peer, interface{}), ourNodePrivKey crypto.PrivKey, config *PeerConfig) (*peer, error) {
conn := rawConn conn := rawConn
@ -216,7 +216,7 @@ func (p *peer) Addr() net.Addr {
} }
// PubKey returns peer's public key. // PubKey returns peer's public key.
func (p *peer) PubKey() crypto.PubKeyEd25519 {
func (p *peer) PubKey() crypto.PubKey {
if p.config.AuthEnc { if p.config.AuthEnc {
return p.conn.(*SecretConnection).RemotePubKey() return p.conn.(*SecretConnection).RemotePubKey()
} }


+ 9
- 9
p2p/peer_test.go View File

@ -16,7 +16,7 @@ func TestPeerBasic(t *testing.T) {
assert, require := assert.New(t), require.New(t) assert, require := assert.New(t), require.New(t)
// simulate remote peer // simulate remote peer
rp := &remotePeer{PrivKey: crypto.GenPrivKeyEd25519(), Config: DefaultPeerConfig()}
rp := &remotePeer{PrivKey: crypto.GenPrivKeyEd25519().Wrap(), Config: DefaultPeerConfig()}
rp.Start() rp.Start()
defer rp.Stop() defer rp.Stop()
@ -43,7 +43,7 @@ func TestPeerWithoutAuthEnc(t *testing.T) {
config.AuthEnc = false config.AuthEnc = false
// simulate remote peer // simulate remote peer
rp := &remotePeer{PrivKey: crypto.GenPrivKeyEd25519(), Config: config}
rp := &remotePeer{PrivKey: crypto.GenPrivKeyEd25519().Wrap(), Config: config}
rp.Start() rp.Start()
defer rp.Stop() defer rp.Stop()
@ -64,7 +64,7 @@ func TestPeerSend(t *testing.T) {
config.AuthEnc = false config.AuthEnc = false
// simulate remote peer // simulate remote peer
rp := &remotePeer{PrivKey: crypto.GenPrivKeyEd25519(), Config: config}
rp := &remotePeer{PrivKey: crypto.GenPrivKeyEd25519().Wrap(), Config: config}
rp.Start() rp.Start()
defer rp.Stop() defer rp.Stop()
@ -85,13 +85,13 @@ func createOutboundPeerAndPerformHandshake(addr *NetAddress, config *PeerConfig)
{ID: 0x01, Priority: 1}, {ID: 0x01, Priority: 1},
} }
reactorsByCh := map[byte]Reactor{0x01: NewTestReactor(chDescs, true)} reactorsByCh := map[byte]Reactor{0x01: NewTestReactor(chDescs, true)}
pk := crypto.GenPrivKeyEd25519()
pk := crypto.GenPrivKeyEd25519().Wrap()
p, err := newOutboundPeer(addr, reactorsByCh, chDescs, func(p Peer, r interface{}) {}, pk, config) p, err := newOutboundPeer(addr, reactorsByCh, chDescs, func(p Peer, r interface{}) {}, pk, config)
if err != nil { if err != nil {
return nil, err return nil, err
} }
err = p.HandshakeTimeout(&NodeInfo{ err = p.HandshakeTimeout(&NodeInfo{
PubKey: pk.PubKey().Unwrap().(crypto.PubKeyEd25519),
PubKey: pk.PubKey(),
Moniker: "host_peer", Moniker: "host_peer",
Network: "testing", Network: "testing",
Version: "123.123.123", Version: "123.123.123",
@ -103,7 +103,7 @@ func createOutboundPeerAndPerformHandshake(addr *NetAddress, config *PeerConfig)
} }
type remotePeer struct { type remotePeer struct {
PrivKey crypto.PrivKeyEd25519
PrivKey crypto.PrivKey
Config *PeerConfig Config *PeerConfig
addr *NetAddress addr *NetAddress
quit chan struct{} quit chan struct{}
@ -113,8 +113,8 @@ func (p *remotePeer) Addr() *NetAddress {
return p.addr return p.addr
} }
func (p *remotePeer) PubKey() crypto.PubKeyEd25519 {
return p.PrivKey.PubKey().Unwrap().(crypto.PubKeyEd25519)
func (p *remotePeer) PubKey() crypto.PubKey {
return p.PrivKey.PubKey()
} }
func (p *remotePeer) Start() { func (p *remotePeer) Start() {
@ -142,7 +142,7 @@ func (p *remotePeer) accept(l net.Listener) {
golog.Fatalf("Failed to create a peer: %+v", err) golog.Fatalf("Failed to create a peer: %+v", err)
} }
err = peer.HandshakeTimeout(&NodeInfo{ err = peer.HandshakeTimeout(&NodeInfo{
PubKey: p.PrivKey.PubKey().Unwrap().(crypto.PubKeyEd25519),
PubKey: p.PrivKey.PubKey(),
Moniker: "remote_peer", Moniker: "remote_peer",
Network: "testing", Network: "testing",
Version: "123.123.123", Version: "123.123.123",


+ 8
- 8
p2p/secret_connection.go View File

@ -38,7 +38,7 @@ type SecretConnection struct {
recvBuffer []byte recvBuffer []byte
recvNonce *[24]byte recvNonce *[24]byte
sendNonce *[24]byte sendNonce *[24]byte
remPubKey crypto.PubKeyEd25519
remPubKey crypto.PubKey
shrSecret *[32]byte // shared secret shrSecret *[32]byte // shared secret
} }
@ -46,9 +46,9 @@ type SecretConnection struct {
// Returns nil if error in handshake. // Returns nil if error in handshake.
// Caller should call conn.Close() // Caller should call conn.Close()
// See docs/sts-final.pdf for more information. // See docs/sts-final.pdf for more information.
func MakeSecretConnection(conn io.ReadWriteCloser, locPrivKey crypto.PrivKeyEd25519) (*SecretConnection, error) {
func MakeSecretConnection(conn io.ReadWriteCloser, locPrivKey crypto.PrivKey) (*SecretConnection, error) {
locPubKey := locPrivKey.PubKey().Unwrap().(crypto.PubKeyEd25519)
locPubKey := locPrivKey.PubKey()
// Generate ephemeral keys for perfect forward secrecy. // Generate ephemeral keys for perfect forward secrecy.
locEphPub, locEphPriv := genEphKeys() locEphPub, locEphPriv := genEphKeys()
@ -100,12 +100,12 @@ func MakeSecretConnection(conn io.ReadWriteCloser, locPrivKey crypto.PrivKeyEd25
} }
// We've authorized. // We've authorized.
sc.remPubKey = remPubKey.Unwrap().(crypto.PubKeyEd25519)
sc.remPubKey = remPubKey
return sc, nil return sc, nil
} }
// Returns authenticated remote pubkey // Returns authenticated remote pubkey
func (sc *SecretConnection) RemotePubKey() crypto.PubKeyEd25519 {
func (sc *SecretConnection) RemotePubKey() crypto.PubKey {
return sc.remPubKey return sc.remPubKey
} }
@ -258,8 +258,8 @@ func genChallenge(loPubKey, hiPubKey *[32]byte) (challenge *[32]byte) {
return hash32(append(loPubKey[:], hiPubKey[:]...)) return hash32(append(loPubKey[:], hiPubKey[:]...))
} }
func signChallenge(challenge *[32]byte, locPrivKey crypto.PrivKeyEd25519) (signature crypto.SignatureEd25519) {
signature = locPrivKey.Sign(challenge[:]).Unwrap().(crypto.SignatureEd25519)
func signChallenge(challenge *[32]byte, locPrivKey crypto.PrivKey) (signature crypto.Signature) {
signature = locPrivKey.Sign(challenge[:])
return return
} }
@ -268,7 +268,7 @@ type authSigMessage struct {
Sig crypto.Signature Sig crypto.Signature
} }
func shareAuthSignature(sc *SecretConnection, pubKey crypto.PubKeyEd25519, signature crypto.SignatureEd25519) (*authSigMessage, error) {
func shareAuthSignature(sc *SecretConnection, pubKey crypto.PubKey, signature crypto.Signature) (*authSigMessage, error) {
var recvMsg authSigMessage var recvMsg authSigMessage
var err1, err2 error var err1, err2 error


+ 7
- 8
p2p/secret_connection_test.go View File

@ -1,7 +1,6 @@
package p2p package p2p
import ( import (
"bytes"
"io" "io"
"testing" "testing"
@ -32,10 +31,10 @@ func makeDummyConnPair() (fooConn, barConn dummyConn) {
func makeSecretConnPair(tb testing.TB) (fooSecConn, barSecConn *SecretConnection) { func makeSecretConnPair(tb testing.TB) (fooSecConn, barSecConn *SecretConnection) {
fooConn, barConn := makeDummyConnPair() fooConn, barConn := makeDummyConnPair()
fooPrvKey := crypto.GenPrivKeyEd25519()
fooPubKey := fooPrvKey.PubKey().Unwrap().(crypto.PubKeyEd25519)
barPrvKey := crypto.GenPrivKeyEd25519()
barPubKey := barPrvKey.PubKey().Unwrap().(crypto.PubKeyEd25519)
fooPrvKey := crypto.GenPrivKeyEd25519().Wrap()
fooPubKey := fooPrvKey.PubKey()
barPrvKey := crypto.GenPrivKeyEd25519().Wrap()
barPubKey := barPrvKey.PubKey()
cmn.Parallel( cmn.Parallel(
func() { func() {
@ -46,7 +45,7 @@ func makeSecretConnPair(tb testing.TB) (fooSecConn, barSecConn *SecretConnection
return return
} }
remotePubBytes := fooSecConn.RemotePubKey() remotePubBytes := fooSecConn.RemotePubKey()
if !bytes.Equal(remotePubBytes[:], barPubKey[:]) {
if !remotePubBytes.Equals(barPubKey) {
tb.Errorf("Unexpected fooSecConn.RemotePubKey. Expected %v, got %v", tb.Errorf("Unexpected fooSecConn.RemotePubKey. Expected %v, got %v",
barPubKey, fooSecConn.RemotePubKey()) barPubKey, fooSecConn.RemotePubKey())
} }
@ -59,7 +58,7 @@ func makeSecretConnPair(tb testing.TB) (fooSecConn, barSecConn *SecretConnection
return return
} }
remotePubBytes := barSecConn.RemotePubKey() remotePubBytes := barSecConn.RemotePubKey()
if !bytes.Equal(remotePubBytes[:], fooPubKey[:]) {
if !remotePubBytes.Equals(fooPubKey) {
tb.Errorf("Unexpected barSecConn.RemotePubKey. Expected %v, got %v", tb.Errorf("Unexpected barSecConn.RemotePubKey. Expected %v, got %v",
fooPubKey, barSecConn.RemotePubKey()) fooPubKey, barSecConn.RemotePubKey())
} }
@ -93,7 +92,7 @@ func TestSecretConnectionReadWrite(t *testing.T) {
genNodeRunner := func(nodeConn dummyConn, nodeWrites []string, nodeReads *[]string) func() { genNodeRunner := func(nodeConn dummyConn, nodeWrites []string, nodeReads *[]string) func() {
return func() { return func() {
// Node handskae // Node handskae
nodePrvKey := crypto.GenPrivKeyEd25519()
nodePrvKey := crypto.GenPrivKeyEd25519().Wrap()
nodeSecretConn, err := MakeSecretConnection(nodeConn, nodePrvKey) nodeSecretConn, err := MakeSecretConnection(nodeConn, nodePrvKey)
if err != nil { if err != nil {
t.Errorf("Failed to establish SecretConnection for node: %v", err) t.Errorf("Failed to establish SecretConnection for node: %v", err)


+ 9
- 9
p2p/switch.go View File

@ -81,11 +81,11 @@ type Switch struct {
reactorsByCh map[byte]Reactor reactorsByCh map[byte]Reactor
peers *PeerSet peers *PeerSet
dialing *cmn.CMap dialing *cmn.CMap
nodeInfo *NodeInfo // our node info
nodePrivKey crypto.PrivKeyEd25519 // our node privkey
nodeInfo *NodeInfo // our node info
nodePrivKey crypto.PrivKey // our node privkey
filterConnByAddr func(net.Addr) error filterConnByAddr func(net.Addr) error
filterConnByPubKey func(crypto.PubKeyEd25519) error
filterConnByPubKey func(crypto.PubKey) error
rng *rand.Rand // seed for randomizing dial times and orders rng *rand.Rand // seed for randomizing dial times and orders
} }
@ -184,10 +184,10 @@ func (sw *Switch) NodeInfo() *NodeInfo {
// SetNodePrivKey sets the switch's private key for authenticated encryption. // SetNodePrivKey sets the switch's private key for authenticated encryption.
// NOTE: Overwrites sw.nodeInfo.PubKey. // NOTE: Overwrites sw.nodeInfo.PubKey.
// NOTE: Not goroutine safe. // NOTE: Not goroutine safe.
func (sw *Switch) SetNodePrivKey(nodePrivKey crypto.PrivKeyEd25519) {
func (sw *Switch) SetNodePrivKey(nodePrivKey crypto.PrivKey) {
sw.nodePrivKey = nodePrivKey sw.nodePrivKey = nodePrivKey
if sw.nodeInfo != nil { if sw.nodeInfo != nil {
sw.nodeInfo.PubKey = nodePrivKey.PubKey().Unwrap().(crypto.PubKeyEd25519)
sw.nodeInfo.PubKey = nodePrivKey.PubKey()
} }
} }
@ -285,7 +285,7 @@ func (sw *Switch) FilterConnByAddr(addr net.Addr) error {
} }
// FilterConnByPubKey returns an error if connecting to the given public key is forbidden. // FilterConnByPubKey returns an error if connecting to the given public key is forbidden.
func (sw *Switch) FilterConnByPubKey(pubkey crypto.PubKeyEd25519) error {
func (sw *Switch) FilterConnByPubKey(pubkey crypto.PubKey) error {
if sw.filterConnByPubKey != nil { if sw.filterConnByPubKey != nil {
return sw.filterConnByPubKey(pubkey) return sw.filterConnByPubKey(pubkey)
} }
@ -299,7 +299,7 @@ func (sw *Switch) SetAddrFilter(f func(net.Addr) error) {
} }
// SetPubKeyFilter sets the function for filtering connections by public key. // SetPubKeyFilter sets the function for filtering connections by public key.
func (sw *Switch) SetPubKeyFilter(f func(crypto.PubKeyEd25519) error) {
func (sw *Switch) SetPubKeyFilter(f func(crypto.PubKey) error) {
sw.filterConnByPubKey = f sw.filterConnByPubKey = f
} }
@ -603,14 +603,14 @@ func makeSwitch(cfg *cfg.P2PConfig, i int, network, version string, initSwitch f
// TODO: let the config be passed in? // TODO: let the config be passed in?
s := initSwitch(i, NewSwitch(cfg)) s := initSwitch(i, NewSwitch(cfg))
s.SetNodeInfo(&NodeInfo{ s.SetNodeInfo(&NodeInfo{
PubKey: privKey.PubKey().Unwrap().(crypto.PubKeyEd25519),
PubKey: privKey.PubKey(),
Moniker: cmn.Fmt("switch%d", i), Moniker: cmn.Fmt("switch%d", i),
Network: network, Network: network,
Version: version, Version: version,
RemoteAddr: cmn.Fmt("%v:%v", network, rand.Intn(64512)+1023), RemoteAddr: cmn.Fmt("%v:%v", network, rand.Intn(64512)+1023),
ListenAddr: cmn.Fmt("%v:%v", network, rand.Intn(64512)+1023), ListenAddr: cmn.Fmt("%v:%v", network, rand.Intn(64512)+1023),
}) })
s.SetNodePrivKey(privKey)
s.SetNodePrivKey(privKey.Wrap())
return s return s
} }


+ 3
- 3
p2p/switch_test.go View File

@ -200,7 +200,7 @@ func TestConnPubKeyFilter(t *testing.T) {
c1, c2 := netPipe() c1, c2 := netPipe()
// set pubkey filter // set pubkey filter
s1.SetPubKeyFilter(func(pubkey crypto.PubKeyEd25519) error {
s1.SetPubKeyFilter(func(pubkey crypto.PubKey) error {
if bytes.Equal(pubkey.Bytes(), s2.nodeInfo.PubKey.Bytes()) { if bytes.Equal(pubkey.Bytes(), s2.nodeInfo.PubKey.Bytes()) {
return fmt.Errorf("Error: pipe is blacklisted") return fmt.Errorf("Error: pipe is blacklisted")
} }
@ -232,7 +232,7 @@ func TestSwitchStopsNonPersistentPeerOnError(t *testing.T) {
defer sw.Stop() defer sw.Stop()
// simulate remote peer // simulate remote peer
rp := &remotePeer{PrivKey: crypto.GenPrivKeyEd25519(), Config: DefaultPeerConfig()}
rp := &remotePeer{PrivKey: crypto.GenPrivKeyEd25519().Wrap(), Config: DefaultPeerConfig()}
rp.Start() rp.Start()
defer rp.Stop() defer rp.Stop()
@ -259,7 +259,7 @@ func TestSwitchReconnectsToPersistentPeer(t *testing.T) {
defer sw.Stop() defer sw.Stop()
// simulate remote peer // simulate remote peer
rp := &remotePeer{PrivKey: crypto.GenPrivKeyEd25519(), Config: DefaultPeerConfig()}
rp := &remotePeer{PrivKey: crypto.GenPrivKeyEd25519().Wrap(), Config: DefaultPeerConfig()}
rp.Start() rp.Start()
defer rp.Stop() defer rp.Stop()


+ 7
- 7
p2p/types.go View File

@ -12,13 +12,13 @@ import (
const maxNodeInfoSize = 10240 // 10Kb const maxNodeInfoSize = 10240 // 10Kb
type NodeInfo struct { type NodeInfo struct {
PubKey crypto.PubKeyEd25519 `json:"pub_key"`
Moniker string `json:"moniker"`
Network string `json:"network"`
RemoteAddr string `json:"remote_addr"`
ListenAddr string `json:"listen_addr"`
Version string `json:"version"` // major.minor.revision
Other []string `json:"other"` // other application specific data
PubKey crypto.PubKey `json:"pub_key"`
Moniker string `json:"moniker"`
Network string `json:"network"`
RemoteAddr string `json:"remote_addr"`
ListenAddr string `json:"listen_addr"`
Version string `json:"version"` // major.minor.revision
Other []string `json:"other"` // other application specific data
} }
// CONTRACT: two nodes are compatible if the major/minor versions match and network match // CONTRACT: two nodes are compatible if the major/minor versions match and network match


Loading…
Cancel
Save