update spec and addrbook.go
This commit is contained in:
parent
6157c700dd
commit
3498b676a6
|
@ -12,7 +12,7 @@ Seeds should operate full nodes with the PEX reactor in a "crawler" mode
|
|||
that continuously explores to validate the availability of peers.
|
||||
|
||||
Seeds should only respond with some top percentile of the best peers it knows about.
|
||||
See [reputation](TODO) for details on peer quality.
|
||||
See [the peer-exchange docs](/docs/specification/new-spec/reactors/pex/pex.md)for details on peer quality.
|
||||
|
||||
## New Full Node
|
||||
|
||||
|
|
|
@ -2,24 +2,23 @@
|
|||
|
||||
This document explains how Tendermint Peers are identified and how they connect to one another.
|
||||
|
||||
For details on peer discovery, see the [peer exchange (PEX) reactor doc](pex.md).
|
||||
For details on peer discovery, see the [peer exchange (PEX) reactor doc](/docs/specification/new-spec/reactors/pex/pex.md).
|
||||
|
||||
## Peer Identity
|
||||
|
||||
Tendermint peers are expected to maintain long-term persistent identities in the form of a public key.
|
||||
Each peer has an ID defined as `peer.ID == peer.PubKey.Address()`, where `Address` uses the scheme defined in go-crypto.
|
||||
|
||||
A single peer ID can have multiple IP addresses associated with it.
|
||||
TODO: define how to deal with this.
|
||||
A single peer ID can have multiple IP addresses associated with it, but a node
|
||||
will only ever connect to one at a time.
|
||||
|
||||
When attempting to connect to a peer, we use the PeerURL: `<ID>@<IP>:<PORT>`.
|
||||
We will attempt to connect to the peer at IP:PORT, and verify,
|
||||
via authenticated encryption, that it is in possession of the private key
|
||||
corresponding to `<ID>`. This prevents man-in-the-middle attacks on the peer layer.
|
||||
|
||||
Peers can also be connected to without specifying an ID, ie. just `<IP>:<PORT>`.
|
||||
In this case, the peer must be authenticated out-of-band of Tendermint,
|
||||
for instance via VPN.
|
||||
If `auth_enc = false`, peers can use an arbitrary ID, but they must always use
|
||||
one. Authentication can then happen out-of-band of Tendermint, for instance via VPN.
|
||||
|
||||
## Connections
|
||||
|
||||
|
@ -84,12 +83,13 @@ The Tendermint Version Handshake allows the peers to exchange their NodeInfo:
|
|||
```golang
|
||||
type NodeInfo struct {
|
||||
ID p2p.ID
|
||||
Moniker string
|
||||
Network string
|
||||
RemoteAddr string
|
||||
ListenAddr string
|
||||
|
||||
Network string
|
||||
Version string
|
||||
Channels []int8
|
||||
|
||||
Moniker string
|
||||
Other []string
|
||||
}
|
||||
```
|
||||
|
@ -98,9 +98,10 @@ The connection is disconnected if:
|
|||
- `peer.NodeInfo.ID` is not equal `peerConn.ID`
|
||||
- `peer.NodeInfo.Version` is not formatted as `X.X.X` where X are integers known as Major, Minor, and Revision
|
||||
- `peer.NodeInfo.Version` Major is not the same as ours
|
||||
- `peer.NodeInfo.Version` Minor is not the same as ours
|
||||
- `peer.NodeInfo.Network` is not the same as ours
|
||||
- `peer.Channels` does not intersect with our known Channels.
|
||||
- `peer.NodeInfo.ListenAddr` is malformed or is a DNS host that cannot be
|
||||
resolved
|
||||
|
||||
|
||||
At this point, if we have not disconnected, the peer is valid.
|
||||
|
|
|
@ -31,8 +31,9 @@ we try the seeds again.
|
|||
|
||||
## Listening
|
||||
|
||||
Peers listen on a configurable ListenAddr that they self-report during
|
||||
handshakes with other peers.
|
||||
Peers listen on a configurable ListenAddr that they self-report in their
|
||||
NodeInfo during handshakes with other peers. Peers accept up to (MaxNumPeers -
|
||||
MinNumOutboundPeers) incoming peers.
|
||||
|
||||
|
||||
## Address Book
|
||||
|
|
|
@ -493,11 +493,11 @@ func (a *addrBook) getBucket(bucketType byte, bucketIdx int) map[string]*knownAd
|
|||
|
||||
// Adds ka to new bucket. Returns false if it couldn't do it cuz buckets full.
|
||||
// NOTE: currently it always returns true.
|
||||
func (a *addrBook) addToNewBucket(ka *knownAddress, bucketIdx int) bool {
|
||||
func (a *addrBook) addToNewBucket(ka *knownAddress, bucketIdx int) {
|
||||
// Sanity check
|
||||
if ka.isOld() {
|
||||
a.Logger.Error(cmn.Fmt("Cannot add address already in old bucket to a new bucket: %v", ka))
|
||||
return false
|
||||
a.Logger.Error("Failed Sanity Check! Cant add old address to new bucket", "ka", knownAddress, "bucket", bucketIdx)
|
||||
return
|
||||
}
|
||||
|
||||
addrStr := ka.Addr.String()
|
||||
|
@ -505,7 +505,7 @@ func (a *addrBook) addToNewBucket(ka *knownAddress, bucketIdx int) bool {
|
|||
|
||||
// Already exists?
|
||||
if _, ok := bucket[addrStr]; ok {
|
||||
return true
|
||||
return
|
||||
}
|
||||
|
||||
// Enforce max addresses.
|
||||
|
@ -523,8 +523,6 @@ func (a *addrBook) addToNewBucket(ka *knownAddress, bucketIdx int) bool {
|
|||
|
||||
// Add it to addrLookup
|
||||
a.addrLookup[ka.ID()] = ka
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// Adds ka to old bucket. Returns false if it couldn't do it cuz buckets full.
|
||||
|
@ -627,7 +625,6 @@ func (a *addrBook) addAddress(addr, src *p2p.NetAddress) error {
|
|||
}
|
||||
|
||||
ka := a.addrLookup[addr.ID]
|
||||
|
||||
if ka != nil {
|
||||
// Already old.
|
||||
if ka.isOld() {
|
||||
|
@ -647,10 +644,7 @@ func (a *addrBook) addAddress(addr, src *p2p.NetAddress) error {
|
|||
}
|
||||
|
||||
bucket := a.calcNewBucket(addr, src)
|
||||
added := a.addToNewBucket(ka, bucket)
|
||||
if !added {
|
||||
return ErrAddrBookFull{addr, a.size()}
|
||||
}
|
||||
a.addToNewBucket(ka, bucket)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -696,20 +690,13 @@ func (a *addrBook) moveToOld(ka *knownAddress) {
|
|||
oldBucketIdx := a.calcOldBucket(ka.Addr)
|
||||
added := a.addToOldBucket(ka, oldBucketIdx)
|
||||
if !added {
|
||||
// No room, must evict something
|
||||
// No room; move the oldest to a new bucket
|
||||
oldest := a.pickOldest(bucketTypeOld, oldBucketIdx)
|
||||
a.removeFromBucket(oldest, bucketTypeOld, oldBucketIdx)
|
||||
// Find new bucket to put oldest in
|
||||
newBucketIdx := a.calcNewBucket(oldest.Addr, oldest.Src)
|
||||
added := a.addToNewBucket(oldest, newBucketIdx)
|
||||
// No space in newBucket either, just put it in freedBucket from above.
|
||||
if !added {
|
||||
added := a.addToNewBucket(oldest, freedBucket)
|
||||
if !added {
|
||||
a.Logger.Error(cmn.Fmt("Could not migrate oldest %v to freedBucket %v", oldest, freedBucket))
|
||||
}
|
||||
}
|
||||
// Finally, add to bucket again.
|
||||
a.addToNewBucket(oldest, newBucketIdx)
|
||||
|
||||
// Finally, add our ka to old bucket again.
|
||||
added = a.addToOldBucket(ka, oldBucketIdx)
|
||||
if !added {
|
||||
a.Logger.Error(cmn.Fmt("Could not re-add ka %v to oldBucketIdx %v", ka, oldBucketIdx))
|
||||
|
|
|
@ -30,12 +30,3 @@ type ErrAddrBookNilAddr struct {
|
|||
func (err ErrAddrBookNilAddr) Error() string {
|
||||
return fmt.Sprintf("Cannot add a nil address. Got (addr, src) = (%v, %v)", err.Addr, err.Src)
|
||||
}
|
||||
|
||||
type ErrAddrBookFull struct {
|
||||
Addr *p2p.NetAddress
|
||||
Size int
|
||||
}
|
||||
|
||||
func (err ErrAddrBookFull) Error() string {
|
||||
return fmt.Sprintf("Can't add new address (%v), addr book is full (%d)", err.Addr, err.Size)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue