mirror of https://github.com/poanetwork/gecko.git
Merge branch 'master' into vms-avm-shutdown-locking
This commit is contained in:
commit
db56cccd4c
|
@ -10,14 +10,14 @@ import (
|
|||
)
|
||||
|
||||
// Peerable can return a group of peers
|
||||
type Peerable interface{ Peers() []utils.IPDesc }
|
||||
type Peerable interface{ IPs() []utils.IPDesc }
|
||||
|
||||
// Networking provides helper methods for tracking the current network state
|
||||
type Networking struct{ peers Peerable }
|
||||
|
||||
// Peers returns the current peers
|
||||
func (n *Networking) Peers() ([]string, error) {
|
||||
ipDescs := n.peers.Peers()
|
||||
ipDescs := n.peers.IPs()
|
||||
ips := make([]string, len(ipDescs))
|
||||
for i, ipDesc := range ipDescs {
|
||||
ips[i] = ipDesc.String()
|
||||
|
|
|
@ -150,9 +150,9 @@ func TestIDUnmarshalJSON(t *testing.T) {
|
|||
|
||||
func TestIDHex(t *testing.T) {
|
||||
id := NewID([32]byte{'a', 'v', 'a', ' ', 'l', 'a', 'b', 's'})
|
||||
expected := "617661206c61627300000000000000000000000000000000000000000000000000"
|
||||
expected := "617661206c616273000000000000000000000000000000000000000000000000"
|
||||
actual := id.Hex()
|
||||
if actual != actual {
|
||||
if actual != expected {
|
||||
t.Fatalf("got %s, expected %s", actual, expected)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,6 +40,10 @@ func main() {
|
|||
defer log.StopOnPanic()
|
||||
defer Config.DB.Close()
|
||||
|
||||
if Config.StakingIP.IsZero() {
|
||||
log.Warn("NAT traversal has failed. If this node becomes a staker, it may lose its reward due to being unreachable.")
|
||||
}
|
||||
|
||||
// Track if sybil control is enforced
|
||||
if !Config.EnableStaking {
|
||||
log.Warn("Staking and p2p encryption are disabled. Packet spoofing is possible.")
|
||||
|
|
|
@ -26,6 +26,10 @@ import (
|
|||
"github.com/ava-labs/gecko/utils/wrappers"
|
||||
)
|
||||
|
||||
const (
|
||||
dbVersion = "v0.1.0"
|
||||
)
|
||||
|
||||
// Results of parsing the CLI
|
||||
var (
|
||||
Config = node.Config{}
|
||||
|
@ -143,7 +147,7 @@ func init() {
|
|||
// DB:
|
||||
if *db && err == nil {
|
||||
// TODO: Add better params here
|
||||
dbPath := path.Join(*dbDir, genesis.NetworkName(Config.NetworkID))
|
||||
dbPath := path.Join(*dbDir, genesis.NetworkName(Config.NetworkID), dbVersion)
|
||||
db, err := leveldb.New(dbPath, 0, 0, 0)
|
||||
Config.DB = db
|
||||
errs.Add(err)
|
||||
|
@ -157,11 +161,9 @@ func init() {
|
|||
// If public IP is not specified, get it using shell command dig
|
||||
if *consensusIP == "" {
|
||||
ip, err = Config.Nat.IP()
|
||||
errs.Add(fmt.Errorf(
|
||||
"%s\n"+
|
||||
"If you are trying to create a local network, try adding --public-ip=127.0.0.1\n"+
|
||||
"If you are attempting to connect to a public network, you may need to manually report your IP and perform port forwarding",
|
||||
err))
|
||||
if err != nil {
|
||||
ip = net.IPv4zero
|
||||
}
|
||||
} else {
|
||||
ip = net.ParseIP(*consensusIP)
|
||||
}
|
||||
|
|
|
@ -1,288 +0,0 @@
|
|||
// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
|
||||
// See the file LICENSE for licensing terms.
|
||||
|
||||
package networking
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/ava-labs/salticidae-go"
|
||||
|
||||
"github.com/ava-labs/gecko/ids"
|
||||
"github.com/ava-labs/gecko/utils"
|
||||
)
|
||||
|
||||
// Connections provides an interface for what a group of connections will
|
||||
// support.
|
||||
type Connections interface {
|
||||
Add(salticidae.NetAddr, ids.ShortID)
|
||||
|
||||
GetIP(ids.ShortID) (salticidae.NetAddr, bool)
|
||||
GetID(salticidae.NetAddr) (ids.ShortID, bool)
|
||||
|
||||
ContainsIP(salticidae.NetAddr) bool
|
||||
ContainsID(ids.ShortID) bool
|
||||
|
||||
Remove(salticidae.NetAddr, ids.ShortID)
|
||||
RemoveIP(salticidae.NetAddr)
|
||||
RemoveID(ids.ShortID)
|
||||
|
||||
Peers() []utils.IPDesc
|
||||
IPs() []salticidae.NetAddr
|
||||
IDs() ids.ShortSet
|
||||
Conns() ([]utils.IPDesc, []ids.ShortID)
|
||||
RawConns() ([]salticidae.NetAddr, []ids.ShortID)
|
||||
|
||||
Len() int
|
||||
}
|
||||
|
||||
// AddrCert implements the Connections interface
|
||||
type AddrCert struct {
|
||||
// ip -> id
|
||||
ipToID map[uint64]ids.ShortID
|
||||
// id -> ip
|
||||
idToIP map[[20]byte]salticidae.NetAddr
|
||||
mux sync.Mutex
|
||||
}
|
||||
|
||||
// Add Assumes that addr is garbage collected normally
|
||||
func (ac *AddrCert) Add(ip salticidae.NetAddr, id ids.ShortID) {
|
||||
ac.mux.Lock()
|
||||
defer ac.mux.Unlock()
|
||||
|
||||
ac.add(ip, id)
|
||||
}
|
||||
|
||||
// GetIP returns the ip mapped to the id that is provided if one exists.
|
||||
func (ac *AddrCert) GetIP(id ids.ShortID) (salticidae.NetAddr, bool) {
|
||||
ac.mux.Lock()
|
||||
defer ac.mux.Unlock()
|
||||
|
||||
return ac.getIP(id)
|
||||
}
|
||||
|
||||
// GetID returns the id mapped to the ip that is provided if one exists.
|
||||
func (ac *AddrCert) GetID(ip salticidae.NetAddr) (ids.ShortID, bool) {
|
||||
ac.mux.Lock()
|
||||
defer ac.mux.Unlock()
|
||||
|
||||
return ac.getID(ip)
|
||||
}
|
||||
|
||||
// ContainsIP returns true if the ip is contained in the connection pool
|
||||
func (ac *AddrCert) ContainsIP(ip salticidae.NetAddr) bool {
|
||||
_, exists := ac.GetID(ip)
|
||||
return exists
|
||||
}
|
||||
|
||||
// ContainsID returns true if the id is contained in the connection pool
|
||||
func (ac *AddrCert) ContainsID(id ids.ShortID) bool {
|
||||
_, exists := ac.GetIP(id)
|
||||
return exists
|
||||
}
|
||||
|
||||
// Remove ensures that no connection will have any mapping containing [ip] or
|
||||
// [id].
|
||||
func (ac *AddrCert) Remove(ip salticidae.NetAddr, id ids.ShortID) {
|
||||
ac.mux.Lock()
|
||||
defer ac.mux.Unlock()
|
||||
|
||||
ac.remove(ip, id)
|
||||
}
|
||||
|
||||
// RemoveIP ensures that no connection will have a mapping containing [ip]
|
||||
func (ac *AddrCert) RemoveIP(ip salticidae.NetAddr) {
|
||||
ac.mux.Lock()
|
||||
defer ac.mux.Unlock()
|
||||
|
||||
ac.removeIP(ip)
|
||||
}
|
||||
|
||||
// RemoveID ensures that no connection will have a mapping containing [id]
|
||||
func (ac *AddrCert) RemoveID(id ids.ShortID) {
|
||||
ac.mux.Lock()
|
||||
defer ac.mux.Unlock()
|
||||
|
||||
ac.removeID(id)
|
||||
}
|
||||
|
||||
// Peers returns the full list of ips contained in this connection pool.
|
||||
func (ac *AddrCert) Peers() []utils.IPDesc {
|
||||
ac.mux.Lock()
|
||||
defer ac.mux.Unlock()
|
||||
|
||||
return ac.peers()
|
||||
}
|
||||
|
||||
// IPs returns the full list of ips contained in this connection pool. This can
|
||||
// be useful for gossiping a node's connections through the network.
|
||||
func (ac *AddrCert) IPs() []salticidae.NetAddr {
|
||||
ac.mux.Lock()
|
||||
defer ac.mux.Unlock()
|
||||
|
||||
return ac.ips()
|
||||
}
|
||||
|
||||
// IDs return the set of IDs that are mapping in this connection pool.
|
||||
func (ac *AddrCert) IDs() ids.ShortSet {
|
||||
ac.mux.Lock()
|
||||
defer ac.mux.Unlock()
|
||||
|
||||
return ac.ids()
|
||||
}
|
||||
|
||||
// Conns return the set of connections in this connection pool.
|
||||
func (ac *AddrCert) Conns() ([]utils.IPDesc, []ids.ShortID) {
|
||||
ac.mux.Lock()
|
||||
defer ac.mux.Unlock()
|
||||
|
||||
return ac.conns()
|
||||
}
|
||||
|
||||
// RawConns return the set of connections in this connection pool.
|
||||
func (ac *AddrCert) RawConns() ([]salticidae.NetAddr, []ids.ShortID) {
|
||||
ac.mux.Lock()
|
||||
defer ac.mux.Unlock()
|
||||
|
||||
return ac.rawConns()
|
||||
}
|
||||
|
||||
// Len returns the number of elements in the map
|
||||
func (ac *AddrCert) Len() int {
|
||||
ac.mux.Lock()
|
||||
defer ac.mux.Unlock()
|
||||
|
||||
return ac.len()
|
||||
}
|
||||
|
||||
func (ac *AddrCert) init() {
|
||||
if ac.ipToID == nil {
|
||||
ac.ipToID = make(map[uint64]ids.ShortID)
|
||||
}
|
||||
if ac.idToIP == nil {
|
||||
ac.idToIP = make(map[[20]byte]salticidae.NetAddr)
|
||||
}
|
||||
}
|
||||
|
||||
func (ac *AddrCert) add(ip salticidae.NetAddr, id ids.ShortID) {
|
||||
ac.init()
|
||||
|
||||
ac.removeIP(ip)
|
||||
ac.removeID(id)
|
||||
|
||||
ac.ipToID[addrToID(ip)] = id
|
||||
ac.idToIP[id.Key()] = ip
|
||||
}
|
||||
|
||||
func (ac *AddrCert) getIP(id ids.ShortID) (salticidae.NetAddr, bool) {
|
||||
ac.init()
|
||||
|
||||
ip, exists := ac.idToIP[id.Key()]
|
||||
return ip, exists
|
||||
}
|
||||
|
||||
func (ac *AddrCert) getID(ip salticidae.NetAddr) (ids.ShortID, bool) {
|
||||
ac.init()
|
||||
|
||||
id, exists := ac.ipToID[addrToID(ip)]
|
||||
return id, exists
|
||||
}
|
||||
|
||||
func (ac *AddrCert) remove(ip salticidae.NetAddr, id ids.ShortID) {
|
||||
ac.removeIP(ip)
|
||||
ac.removeID(id)
|
||||
}
|
||||
|
||||
func (ac *AddrCert) removeIP(ip salticidae.NetAddr) {
|
||||
ac.init()
|
||||
|
||||
ipID := addrToID(ip)
|
||||
if id, exists := ac.ipToID[ipID]; exists {
|
||||
delete(ac.ipToID, ipID)
|
||||
delete(ac.idToIP, id.Key())
|
||||
}
|
||||
}
|
||||
|
||||
func (ac *AddrCert) removeID(id ids.ShortID) {
|
||||
ac.init()
|
||||
|
||||
idKey := id.Key()
|
||||
if ip, exists := ac.idToIP[idKey]; exists {
|
||||
delete(ac.ipToID, addrToID(ip))
|
||||
delete(ac.idToIP, idKey)
|
||||
}
|
||||
}
|
||||
|
||||
func (ac *AddrCert) peers() []utils.IPDesc {
|
||||
ac.init()
|
||||
|
||||
ips := []utils.IPDesc(nil)
|
||||
for _, ip := range ac.idToIP {
|
||||
ips = append(ips, toIPDesc(ip))
|
||||
}
|
||||
return ips
|
||||
}
|
||||
|
||||
func (ac *AddrCert) ips() []salticidae.NetAddr {
|
||||
ac.init()
|
||||
|
||||
ips := []salticidae.NetAddr(nil)
|
||||
for _, ip := range ac.idToIP {
|
||||
ips = append(ips, ip)
|
||||
}
|
||||
return ips
|
||||
}
|
||||
|
||||
func (ac *AddrCert) ids() ids.ShortSet {
|
||||
ac.init()
|
||||
|
||||
ids := ids.ShortSet{}
|
||||
for _, id := range ac.ipToID {
|
||||
ids.Add(id)
|
||||
}
|
||||
return ids
|
||||
}
|
||||
|
||||
func (ac *AddrCert) conns() ([]utils.IPDesc, []ids.ShortID) {
|
||||
ac.init()
|
||||
|
||||
ipList := []utils.IPDesc(nil)
|
||||
idList := []ids.ShortID(nil)
|
||||
for id, ip := range ac.idToIP {
|
||||
ipList = append(ipList, toIPDesc(ip))
|
||||
idList = append(idList, ids.NewShortID(id))
|
||||
}
|
||||
return ipList, idList
|
||||
}
|
||||
|
||||
func (ac *AddrCert) rawConns() ([]salticidae.NetAddr, []ids.ShortID) {
|
||||
ac.init()
|
||||
|
||||
ipList := []salticidae.NetAddr(nil)
|
||||
idList := []ids.ShortID(nil)
|
||||
for id, ip := range ac.idToIP {
|
||||
ipList = append(ipList, ip)
|
||||
idList = append(idList, ids.NewShortID(id))
|
||||
}
|
||||
return ipList, idList
|
||||
}
|
||||
|
||||
func (ac *AddrCert) len() int { return len(ac.ipToID) }
|
||||
|
||||
func toIPDesc(addr salticidae.NetAddr) utils.IPDesc {
|
||||
ip, err := ToIPDesc(addr)
|
||||
HandshakeNet.log.AssertNoError(err)
|
||||
return ip
|
||||
}
|
||||
|
||||
// ToIPDesc converts an address to an IP
|
||||
func ToIPDesc(addr salticidae.NetAddr) (utils.IPDesc, error) {
|
||||
ip := salticidae.FromBigEndianU32(addr.GetIP())
|
||||
port := salticidae.FromBigEndianU16(addr.GetPort())
|
||||
return utils.ToIPDesc(fmt.Sprintf("%d.%d.%d.%d:%d", byte(ip>>24), byte(ip>>16), byte(ip>>8), byte(ip), port))
|
||||
}
|
||||
|
||||
func addrToID(addr salticidae.NetAddr) uint64 {
|
||||
return uint64(addr.GetIP()) | (uint64(addr.GetPort()) << 32)
|
||||
}
|
|
@ -16,10 +16,11 @@ type Builder struct{ Codec }
|
|||
func (m Builder) GetVersion() (Msg, error) { return m.Pack(GetVersion, nil) }
|
||||
|
||||
// Version message
|
||||
func (m Builder) Version(networkID uint32, myTime uint64, myVersion string) (Msg, error) {
|
||||
func (m Builder) Version(networkID uint32, myTime uint64, ip utils.IPDesc, myVersion string) (Msg, error) {
|
||||
return m.Pack(Version, map[Field]interface{}{
|
||||
NetworkID: networkID,
|
||||
MyTime: myTime,
|
||||
IP: ip,
|
||||
VersionStr: myVersion,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ const (
|
|||
VersionStr Field = iota // Used in handshake
|
||||
NetworkID // Used in handshake
|
||||
MyTime // Used in handshake
|
||||
IP // Used in handshake
|
||||
Peers // Used in handshake
|
||||
ChainID // Used for dispatching
|
||||
RequestID // Used for all messages
|
||||
|
@ -38,6 +39,8 @@ func (f Field) Packer() func(*wrappers.Packer, interface{}) {
|
|||
return wrappers.TryPackInt
|
||||
case MyTime:
|
||||
return wrappers.TryPackLong
|
||||
case IP:
|
||||
return wrappers.TryPackIP
|
||||
case Peers:
|
||||
return wrappers.TryPackIPList
|
||||
case ChainID: // TODO: This will be shortened to use a modified varint spec
|
||||
|
@ -72,6 +75,8 @@ func (f Field) Unpacker() func(*wrappers.Packer) interface{} {
|
|||
return wrappers.TryUnpackInt
|
||||
case MyTime:
|
||||
return wrappers.TryUnpackLong
|
||||
case IP:
|
||||
return wrappers.TryUnpackIP
|
||||
case Peers:
|
||||
return wrappers.TryUnpackIPList
|
||||
case ChainID: // TODO: This will be shortened to use a modified varint spec
|
||||
|
@ -105,6 +110,8 @@ func (f Field) String() string {
|
|||
return "NetworkID"
|
||||
case MyTime:
|
||||
return "MyTime"
|
||||
case IP:
|
||||
return "IP"
|
||||
case Peers:
|
||||
return "Peers"
|
||||
case ChainID:
|
||||
|
@ -161,7 +168,7 @@ var (
|
|||
Messages = map[salticidae.Opcode][]Field{
|
||||
// Handshake:
|
||||
GetVersion: []Field{},
|
||||
Version: []Field{NetworkID, MyTime, VersionStr},
|
||||
Version: []Field{NetworkID, MyTime, IP, VersionStr},
|
||||
GetPeerList: []Field{},
|
||||
PeerList: []Field{Peers},
|
||||
// Bootstrapping:
|
||||
|
|
|
@ -0,0 +1,280 @@
|
|||
// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
|
||||
// See the file LICENSE for licensing terms.
|
||||
|
||||
package networking
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/ava-labs/salticidae-go"
|
||||
|
||||
"github.com/ava-labs/gecko/ids"
|
||||
"github.com/ava-labs/gecko/utils"
|
||||
)
|
||||
|
||||
// Connections provides an interface for what a group of connections will
|
||||
// support.
|
||||
type Connections interface {
|
||||
Add(salticidae.PeerID, ids.ShortID, utils.IPDesc)
|
||||
|
||||
GetPeerID(ids.ShortID) (salticidae.PeerID, bool)
|
||||
GetID(salticidae.PeerID) (ids.ShortID, bool)
|
||||
|
||||
ContainsPeerID(salticidae.PeerID) bool
|
||||
ContainsID(ids.ShortID) bool
|
||||
ContainsIP(utils.IPDesc) bool
|
||||
|
||||
Remove(salticidae.PeerID, ids.ShortID)
|
||||
RemovePeerID(salticidae.PeerID)
|
||||
RemoveID(ids.ShortID)
|
||||
|
||||
PeerIDs() []salticidae.PeerID
|
||||
IDs() ids.ShortSet
|
||||
IPs() []utils.IPDesc
|
||||
Conns() ([]salticidae.PeerID, []ids.ShortID, []utils.IPDesc)
|
||||
|
||||
Len() int
|
||||
}
|
||||
|
||||
type connections struct {
|
||||
mux sync.Mutex
|
||||
// peerID -> id
|
||||
peerIDToID map[[32]byte]ids.ShortID
|
||||
// id -> peerID
|
||||
idToPeerID map[[20]byte]salticidae.PeerID
|
||||
// id -> ip
|
||||
idToIP map[[20]byte]utils.IPDesc
|
||||
}
|
||||
|
||||
// NewConnections returns a new and empty connections object
|
||||
func NewConnections() Connections {
|
||||
return &connections{
|
||||
peerIDToID: make(map[[32]byte]ids.ShortID),
|
||||
idToPeerID: make(map[[20]byte]salticidae.PeerID),
|
||||
idToIP: make(map[[20]byte]utils.IPDesc),
|
||||
}
|
||||
}
|
||||
|
||||
// Add Assumes that peer is garbage collected normally
|
||||
func (c *connections) Add(peer salticidae.PeerID, id ids.ShortID, ip utils.IPDesc) {
|
||||
c.mux.Lock()
|
||||
defer c.mux.Unlock()
|
||||
|
||||
c.add(peer, id, ip)
|
||||
}
|
||||
|
||||
// GetPeerID returns the peer mapped to the id that is provided if one exists.
|
||||
func (c *connections) GetPeerID(id ids.ShortID) (salticidae.PeerID, bool) {
|
||||
c.mux.Lock()
|
||||
defer c.mux.Unlock()
|
||||
|
||||
return c.getPeerID(id)
|
||||
}
|
||||
|
||||
// GetID returns the id mapped to the peer that is provided if one exists.
|
||||
func (c *connections) GetID(peer salticidae.PeerID) (ids.ShortID, bool) {
|
||||
c.mux.Lock()
|
||||
defer c.mux.Unlock()
|
||||
|
||||
return c.getID(peer)
|
||||
}
|
||||
|
||||
// ContainsPeerID returns true if the peer is contained in the connection pool
|
||||
func (c *connections) ContainsPeerID(peer salticidae.PeerID) bool {
|
||||
_, exists := c.GetID(peer)
|
||||
return exists
|
||||
}
|
||||
|
||||
// ContainsID returns true if the id is contained in the connection pool
|
||||
func (c *connections) ContainsID(id ids.ShortID) bool {
|
||||
_, exists := c.GetPeerID(id)
|
||||
return exists
|
||||
}
|
||||
|
||||
// ContainsIP returns true if the ip is contained in the connection pool
|
||||
func (c *connections) ContainsIP(ip utils.IPDesc) bool {
|
||||
for _, otherIP := range c.IPs() {
|
||||
if ip.Equal(otherIP) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Remove ensures that no connection will have any mapping containing [peer] or
|
||||
// [id].
|
||||
func (c *connections) Remove(peer salticidae.PeerID, id ids.ShortID) {
|
||||
c.mux.Lock()
|
||||
defer c.mux.Unlock()
|
||||
|
||||
c.remove(peer, id)
|
||||
}
|
||||
|
||||
// RemovePeerID ensures that no connection will have a mapping containing [peer]
|
||||
func (c *connections) RemovePeerID(peer salticidae.PeerID) {
|
||||
c.mux.Lock()
|
||||
defer c.mux.Unlock()
|
||||
|
||||
c.removePeerID(peer)
|
||||
}
|
||||
|
||||
// RemoveID ensures that no connection will have a mapping containing [id]
|
||||
func (c *connections) RemoveID(id ids.ShortID) {
|
||||
c.mux.Lock()
|
||||
defer c.mux.Unlock()
|
||||
|
||||
c.removeID(id)
|
||||
}
|
||||
|
||||
// PeerIDs returns the full list of peers contained in this connection pool.
|
||||
func (c *connections) PeerIDs() []salticidae.PeerID {
|
||||
c.mux.Lock()
|
||||
defer c.mux.Unlock()
|
||||
|
||||
return c.peerIDs()
|
||||
}
|
||||
|
||||
// IDs return the set of IDs that are mapping in this connection pool.
|
||||
func (c *connections) IDs() ids.ShortSet {
|
||||
c.mux.Lock()
|
||||
defer c.mux.Unlock()
|
||||
|
||||
return c.ids()
|
||||
}
|
||||
|
||||
// IPs return the set of IPs that are mapped in this connection pool.
|
||||
func (c *connections) IPs() []utils.IPDesc {
|
||||
c.mux.Lock()
|
||||
defer c.mux.Unlock()
|
||||
|
||||
return c.ips()
|
||||
}
|
||||
|
||||
// Conns return the set of connections in this connection pool.
|
||||
func (c *connections) Conns() ([]salticidae.PeerID, []ids.ShortID, []utils.IPDesc) {
|
||||
c.mux.Lock()
|
||||
defer c.mux.Unlock()
|
||||
|
||||
return c.conns()
|
||||
}
|
||||
|
||||
// Len returns the number of elements in the map
|
||||
func (c *connections) Len() int {
|
||||
c.mux.Lock()
|
||||
defer c.mux.Unlock()
|
||||
|
||||
return c.len()
|
||||
}
|
||||
|
||||
func (c *connections) add(peer salticidae.PeerID, id ids.ShortID, ip utils.IPDesc) {
|
||||
c.remove(peer, id)
|
||||
|
||||
key := id.Key()
|
||||
c.peerIDToID[toID(peer)] = id
|
||||
c.idToPeerID[key] = peer
|
||||
c.idToIP[key] = ip
|
||||
}
|
||||
|
||||
func (c *connections) getPeerID(id ids.ShortID) (salticidae.PeerID, bool) {
|
||||
peer, exists := c.idToPeerID[id.Key()]
|
||||
return peer, exists
|
||||
}
|
||||
|
||||
func (c *connections) getID(peer salticidae.PeerID) (ids.ShortID, bool) {
|
||||
id, exists := c.peerIDToID[toID(peer)]
|
||||
return id, exists
|
||||
}
|
||||
|
||||
func (c *connections) remove(peer salticidae.PeerID, id ids.ShortID) {
|
||||
c.removePeerID(peer)
|
||||
c.removeID(id)
|
||||
}
|
||||
|
||||
func (c *connections) removePeerID(peer salticidae.PeerID) {
|
||||
peerID := toID(peer)
|
||||
if id, exists := c.peerIDToID[peerID]; exists {
|
||||
idKey := id.Key()
|
||||
|
||||
delete(c.peerIDToID, peerID)
|
||||
delete(c.idToPeerID, idKey)
|
||||
delete(c.idToIP, idKey)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *connections) removeID(id ids.ShortID) {
|
||||
idKey := id.Key()
|
||||
if peer, exists := c.idToPeerID[idKey]; exists {
|
||||
delete(c.peerIDToID, toID(peer))
|
||||
delete(c.idToPeerID, idKey)
|
||||
delete(c.idToIP, idKey)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *connections) peerIDs() []salticidae.PeerID {
|
||||
peers := make([]salticidae.PeerID, 0, len(c.idToPeerID))
|
||||
for _, peer := range c.idToPeerID {
|
||||
peers = append(peers, peer)
|
||||
}
|
||||
return peers
|
||||
}
|
||||
|
||||
func (c *connections) ids() ids.ShortSet {
|
||||
ids := ids.ShortSet{}
|
||||
for _, id := range c.peerIDToID {
|
||||
ids.Add(id)
|
||||
}
|
||||
return ids
|
||||
}
|
||||
|
||||
func (c *connections) ips() []utils.IPDesc {
|
||||
ips := make([]utils.IPDesc, 0, len(c.idToIP))
|
||||
for _, ip := range c.idToIP {
|
||||
ips = append(ips, ip)
|
||||
}
|
||||
return ips
|
||||
}
|
||||
|
||||
func (c *connections) conns() ([]salticidae.PeerID, []ids.ShortID, []utils.IPDesc) {
|
||||
peers := make([]salticidae.PeerID, 0, len(c.idToPeerID))
|
||||
idList := make([]ids.ShortID, 0, len(c.idToPeerID))
|
||||
ips := make([]utils.IPDesc, 0, len(c.idToPeerID))
|
||||
for id, peer := range c.idToPeerID {
|
||||
idList = append(idList, ids.NewShortID(id))
|
||||
peers = append(peers, peer)
|
||||
ips = append(ips, c.idToIP[id])
|
||||
}
|
||||
return peers, idList, ips
|
||||
}
|
||||
|
||||
func (c *connections) len() int { return len(c.idToPeerID) }
|
||||
|
||||
func toID(peer salticidae.PeerID) [32]byte {
|
||||
ds := salticidae.NewDataStream(false)
|
||||
|
||||
peerInt := peer.AsUInt256()
|
||||
peerInt.Serialize(ds)
|
||||
|
||||
size := ds.Size()
|
||||
dsb := ds.GetDataInPlace(size)
|
||||
idBytes := dsb.Get()
|
||||
|
||||
id := [32]byte{}
|
||||
copy(id[:], idBytes)
|
||||
|
||||
ds.Free()
|
||||
return id
|
||||
}
|
||||
|
||||
func toIPDesc(addr salticidae.NetAddr) utils.IPDesc {
|
||||
ip, err := ToIPDesc(addr)
|
||||
HandshakeNet.log.AssertNoError(err)
|
||||
return ip
|
||||
}
|
||||
|
||||
// ToIPDesc converts an address to an IP
|
||||
func ToIPDesc(addr salticidae.NetAddr) (utils.IPDesc, error) {
|
||||
ip := salticidae.FromBigEndianU32(addr.GetIP())
|
||||
port := salticidae.FromBigEndianU16(addr.GetPort())
|
||||
return utils.ToIPDesc(fmt.Sprintf("%d.%d.%d.%d:%d", byte(ip>>24), byte(ip>>16), byte(ip>>8), byte(ip), port))
|
||||
}
|
|
@ -4,7 +4,7 @@
|
|||
package networking
|
||||
|
||||
// #include "salticidae/network.h"
|
||||
// bool checkPeerCertificate(msgnetwork_conn_t *, bool, void *);
|
||||
// bool connHandler(msgnetwork_conn_t *, bool, void *);
|
||||
// void unknownPeerHandler(netaddr_t *, x509_t *, void *);
|
||||
// void peerHandler(peernetwork_conn_t *, bool, void *);
|
||||
// void ping(msg_t *, msgnetwork_conn_t *, void *);
|
||||
|
@ -19,6 +19,8 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
@ -61,9 +63,23 @@ Attempt reconnections
|
|||
node isn't connected to after awhile delete the connection.
|
||||
*/
|
||||
|
||||
// Version this avalanche instance is executing.
|
||||
var (
|
||||
VersionPrefix = "avalanche/"
|
||||
VersionSeparator = "."
|
||||
MajorVersion = 0
|
||||
MinorVersion = 1
|
||||
PatchVersion = 0
|
||||
ClientVersion = fmt.Sprintf("%s%d%s%d%s%d",
|
||||
VersionPrefix,
|
||||
MajorVersion,
|
||||
VersionSeparator,
|
||||
MinorVersion,
|
||||
VersionSeparator,
|
||||
PatchVersion)
|
||||
)
|
||||
|
||||
const (
|
||||
// CurrentVersion this avalanche instance is executing.
|
||||
CurrentVersion = "avalanche/0.0.1"
|
||||
// MaxClockDifference allowed between connected nodes.
|
||||
MaxClockDifference = time.Minute
|
||||
// PeerListGossipSpacing is the amount of time to wait between pushing this
|
||||
|
@ -74,6 +90,10 @@ const (
|
|||
// PeerListStakerGossipFraction calculates the fraction of stakers that are
|
||||
// gossiped to. If set to 1, then only stakers will be gossiped to.
|
||||
PeerListStakerGossipFraction = 2
|
||||
|
||||
// ConnectTimeout is the amount of time to wait before attempt to connect to
|
||||
// an unknown peer
|
||||
ConnectTimeout = 6 * time.Second
|
||||
// GetVersionTimeout is the amount of time to wait before sending a
|
||||
// getVersion message to a partially connected peer
|
||||
GetVersionTimeout = 2 * time.Second
|
||||
|
@ -96,23 +116,35 @@ var (
|
|||
type Handshake struct {
|
||||
handshakeMetrics
|
||||
|
||||
networkID uint32
|
||||
networkID uint32 // ID of the network I'm running, used to prevent connecting to the wrong network
|
||||
|
||||
log logging.Logger
|
||||
vdrs validators.Set
|
||||
myAddr salticidae.NetAddr
|
||||
myID ids.ShortID
|
||||
net salticidae.PeerNetwork
|
||||
enableStaking bool // Should only be false for local tests
|
||||
vdrs validators.Set // set of current validators in the AVAnet
|
||||
myAddr salticidae.NetAddr // IP I communicate to peers
|
||||
myID ids.ShortID // ID that identifies myself as a staker or not
|
||||
net salticidae.PeerNetwork // C messaging network
|
||||
enableStaking bool // Should only be false for local tests
|
||||
|
||||
clock timer.Clock
|
||||
pending AddrCert // Connections that I haven't gotten version messages from
|
||||
connections AddrCert // Connections that I think are connected
|
||||
clock timer.Clock
|
||||
|
||||
versionTimeout timer.TimeoutManager
|
||||
reconnectTimeout timer.TimeoutManager
|
||||
// Connections that I have added by IP, but haven't gotten an ID from
|
||||
requestedLock sync.Mutex
|
||||
requested map[string]struct{}
|
||||
requestedTimeout timer.TimeoutManager // keys are hashes of the ip:port string
|
||||
|
||||
// Connections that I have added as a peer, but haven't gotten a version
|
||||
// message from
|
||||
pending Connections
|
||||
versionTimeout timer.TimeoutManager // keys are the peer IDs
|
||||
|
||||
// Connections that I have gotten a valid version message from
|
||||
connections Connections
|
||||
reconnectTimeout timer.TimeoutManager // keys are the peer IDs
|
||||
|
||||
// IPs of nodes I'm connected to will be repeatedly gossiped throughout the network
|
||||
peerListGossiper *timer.Repeater
|
||||
|
||||
// If any chain is blocked on connecting to peers, track these blockers here
|
||||
awaitingLock sync.Mutex
|
||||
awaiting []*networking.AwaitingConnections
|
||||
}
|
||||
|
@ -130,17 +162,37 @@ func (nm *Handshake) Initialize(
|
|||
networkID uint32,
|
||||
) {
|
||||
log.AssertTrue(nm.net == nil, "Should only register network handlers once")
|
||||
|
||||
nm.handshakeMetrics.Initialize(log, registerer)
|
||||
|
||||
nm.networkID = networkID
|
||||
|
||||
nm.log = log
|
||||
nm.vdrs = vdrs
|
||||
nm.myAddr = myAddr
|
||||
nm.myID = myID
|
||||
nm.net = peerNet
|
||||
nm.enableStaking = enableStaking
|
||||
nm.networkID = networkID
|
||||
|
||||
nm.requested = make(map[string]struct{})
|
||||
nm.requestedTimeout.Initialize(ConnectTimeout)
|
||||
go nm.log.RecoverAndPanic(nm.requestedTimeout.Dispatch)
|
||||
|
||||
nm.pending = NewConnections()
|
||||
nm.versionTimeout.Initialize(GetVersionTimeout)
|
||||
go nm.log.RecoverAndPanic(nm.versionTimeout.Dispatch)
|
||||
|
||||
nm.connections = NewConnections()
|
||||
nm.reconnectTimeout.Initialize(ReconnectTimeout)
|
||||
go nm.log.RecoverAndPanic(nm.reconnectTimeout.Dispatch)
|
||||
|
||||
nm.peerListGossiper = timer.NewRepeater(nm.gossipPeerList, PeerListGossipSpacing)
|
||||
go nm.log.RecoverAndPanic(nm.peerListGossiper.Dispatch)
|
||||
|
||||
// register c message callbacks
|
||||
net := peerNet.AsMsgNetwork()
|
||||
|
||||
net.RegConnHandler(salticidae.MsgNetworkConnCallback(C.checkPeerCertificate), nil)
|
||||
net.RegConnHandler(salticidae.MsgNetworkConnCallback(C.connHandler), nil)
|
||||
peerNet.RegPeerHandler(salticidae.PeerNetworkPeerCallback(C.peerHandler), nil)
|
||||
peerNet.RegUnknownPeerHandler(salticidae.PeerNetworkUnknownPeerCallback(C.unknownPeerHandler), nil)
|
||||
net.RegHandler(Ping, salticidae.MsgNetworkMsgCallback(C.ping), nil)
|
||||
|
@ -149,17 +201,95 @@ func (nm *Handshake) Initialize(
|
|||
net.RegHandler(Version, salticidae.MsgNetworkMsgCallback(C.version), nil)
|
||||
net.RegHandler(GetPeerList, salticidae.MsgNetworkMsgCallback(C.getPeerList), nil)
|
||||
net.RegHandler(PeerList, salticidae.MsgNetworkMsgCallback(C.peerList), nil)
|
||||
}
|
||||
|
||||
nm.handshakeMetrics.Initialize(nm.log, registerer)
|
||||
// ConnectTo add the peer as a connection and connects to them.
|
||||
func (nm *Handshake) ConnectTo(peer salticidae.PeerID, stakerID ids.ShortID, addr salticidae.NetAddr) {
|
||||
if nm.pending.ContainsPeerID(peer) || nm.connections.ContainsPeerID(peer) {
|
||||
return
|
||||
}
|
||||
|
||||
nm.versionTimeout.Initialize(GetVersionTimeout)
|
||||
go nm.log.RecoverAndPanic(nm.versionTimeout.Dispatch)
|
||||
nm.log.Info("Attempting to connect to %s", stakerID)
|
||||
|
||||
nm.reconnectTimeout.Initialize(ReconnectTimeout)
|
||||
go nm.log.RecoverAndPanic(nm.reconnectTimeout.Dispatch)
|
||||
nm.net.AddPeer(peer)
|
||||
nm.net.SetPeerAddr(peer, addr)
|
||||
nm.net.ConnPeer(peer, 600, 1)
|
||||
|
||||
nm.peerListGossiper = timer.NewRepeater(nm.gossipPeerList, PeerListGossipSpacing)
|
||||
go nm.log.RecoverAndPanic(nm.peerListGossiper.Dispatch)
|
||||
ip := toIPDesc(addr)
|
||||
nm.pending.Add(peer, stakerID, ip)
|
||||
|
||||
peerBytes := toID(peer)
|
||||
peerID := ids.NewID(peerBytes)
|
||||
|
||||
nm.reconnectTimeout.Put(peerID, func() {
|
||||
nm.pending.Remove(peer, stakerID)
|
||||
nm.connections.Remove(peer, stakerID)
|
||||
nm.net.DelPeer(peer)
|
||||
|
||||
nm.numPeers.Set(float64(nm.connections.Len()))
|
||||
})
|
||||
}
|
||||
|
||||
// Connect ...
|
||||
func (nm *Handshake) Connect(addr salticidae.NetAddr) {
|
||||
ip := toIPDesc(addr)
|
||||
ipStr := ip.String()
|
||||
if nm.pending.ContainsIP(ip) || nm.connections.ContainsIP(ip) {
|
||||
return
|
||||
}
|
||||
|
||||
if !nm.enableStaking {
|
||||
nm.log.Info("Adding peer %s", ip)
|
||||
|
||||
peer := salticidae.NewPeerIDFromNetAddr(addr, true)
|
||||
nm.ConnectTo(peer, toShortID(ip), addr)
|
||||
return
|
||||
}
|
||||
|
||||
nm.requestedLock.Lock()
|
||||
_, exists := nm.requested[ipStr]
|
||||
nm.requestedLock.Unlock()
|
||||
|
||||
if exists {
|
||||
return
|
||||
}
|
||||
|
||||
nm.log.Info("Adding peer %s", ip)
|
||||
|
||||
count := new(int)
|
||||
*count = 100
|
||||
handler := new(func())
|
||||
*handler = func() {
|
||||
nm.requestedLock.Lock()
|
||||
defer nm.requestedLock.Unlock()
|
||||
|
||||
if *count == 100 {
|
||||
nm.requested[ipStr] = struct{}{}
|
||||
}
|
||||
|
||||
if _, exists := nm.requested[ipStr]; !exists {
|
||||
return
|
||||
}
|
||||
|
||||
if *count <= 0 {
|
||||
delete(nm.requested, ipStr)
|
||||
return
|
||||
}
|
||||
*count--
|
||||
|
||||
if nm.pending.ContainsIP(ip) || nm.connections.ContainsIP(ip) {
|
||||
return
|
||||
}
|
||||
|
||||
nm.log.Info("Attempting to discover peer at %s", ipStr)
|
||||
|
||||
msgNet := nm.net.AsMsgNetwork()
|
||||
msgNet.Connect(addr)
|
||||
|
||||
ipID := ids.NewID(hashing.ComputeHash256Array([]byte(ipStr)))
|
||||
nm.requestedTimeout.Put(ipID, *handler)
|
||||
}
|
||||
(*handler)()
|
||||
}
|
||||
|
||||
// AwaitConnections ...
|
||||
|
@ -209,19 +339,19 @@ func (nm *Handshake) gossipPeerList() {
|
|||
idsToSend = append(idsToSend, nonStakers[sampler.Sample()])
|
||||
}
|
||||
|
||||
ips := []salticidae.NetAddr{}
|
||||
peers := []salticidae.PeerID{}
|
||||
for _, id := range idsToSend {
|
||||
if ip, exists := nm.connections.GetIP(id); exists {
|
||||
ips = append(ips, ip)
|
||||
if peer, exists := nm.connections.GetPeerID(id); exists {
|
||||
peers = append(peers, peer)
|
||||
}
|
||||
}
|
||||
|
||||
nm.SendPeerList(ips...)
|
||||
nm.SendPeerList(peers...)
|
||||
}
|
||||
|
||||
// Connections returns the object that tracks the nodes that are currently
|
||||
// connected to this node.
|
||||
func (nm *Handshake) Connections() Connections { return &nm.connections }
|
||||
func (nm *Handshake) Connections() Connections { return nm.connections }
|
||||
|
||||
// Shutdown the network
|
||||
func (nm *Handshake) Shutdown() {
|
||||
|
@ -230,59 +360,60 @@ func (nm *Handshake) Shutdown() {
|
|||
}
|
||||
|
||||
// SendGetVersion to the requested peer
|
||||
func (nm *Handshake) SendGetVersion(addr salticidae.NetAddr) {
|
||||
func (nm *Handshake) SendGetVersion(peer salticidae.PeerID) {
|
||||
build := Builder{}
|
||||
gv, err := build.GetVersion()
|
||||
nm.log.AssertNoError(err)
|
||||
nm.send(gv, addr)
|
||||
nm.send(gv, peer)
|
||||
|
||||
nm.numGetVersionSent.Inc()
|
||||
}
|
||||
|
||||
// SendVersion to the requested peer
|
||||
func (nm *Handshake) SendVersion(addr salticidae.NetAddr) error {
|
||||
func (nm *Handshake) SendVersion(peer salticidae.PeerID) error {
|
||||
build := Builder{}
|
||||
v, err := build.Version(nm.networkID, nm.clock.Unix(), CurrentVersion)
|
||||
v, err := build.Version(nm.networkID, nm.clock.Unix(), toIPDesc(nm.myAddr), ClientVersion)
|
||||
if err != nil {
|
||||
return fmt.Errorf("packing Version failed due to %s", err)
|
||||
}
|
||||
nm.send(v, addr)
|
||||
nm.send(v, peer)
|
||||
nm.numVersionSent.Inc()
|
||||
return nil
|
||||
}
|
||||
|
||||
// SendPeerList to the requested peer
|
||||
func (nm *Handshake) SendPeerList(addrs ...salticidae.NetAddr) error {
|
||||
if len(addrs) == 0 {
|
||||
func (nm *Handshake) SendPeerList(peers ...salticidae.PeerID) error {
|
||||
if len(peers) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
ips, ids := nm.connections.Conns()
|
||||
_, ids, ips := nm.connections.Conns()
|
||||
ipsToSend := []utils.IPDesc(nil)
|
||||
for i, id := range ids {
|
||||
if nm.vdrs.Contains(id) {
|
||||
ipsToSend = append(ipsToSend, ips[i])
|
||||
ip := ips[i]
|
||||
if !ip.IsZero() && nm.vdrs.Contains(id) {
|
||||
ipsToSend = append(ipsToSend, ip)
|
||||
}
|
||||
}
|
||||
|
||||
if len(ipsToSend) == 0 {
|
||||
nm.log.Debug("No IPs to send to %d peer(s)", len(addrs))
|
||||
nm.log.Debug("No IPs to send to %d peer(s)", len(peers))
|
||||
return nil
|
||||
}
|
||||
|
||||
nm.log.Verbo("Sending %d ips to %d peer(s)", len(ipsToSend), len(addrs))
|
||||
nm.log.Verbo("Sending %d ips to %d peer(s)", len(ipsToSend), len(peers))
|
||||
|
||||
build := Builder{}
|
||||
pl, err := build.PeerList(ipsToSend)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Packing Peerlist failed due to %w", err)
|
||||
}
|
||||
nm.send(pl, addrs...)
|
||||
nm.numPeerlistSent.Add(float64(len(addrs)))
|
||||
nm.send(pl, peers...)
|
||||
nm.numPeerlistSent.Add(float64(len(peers)))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (nm *Handshake) send(msg Msg, addrs ...salticidae.NetAddr) {
|
||||
func (nm *Handshake) send(msg Msg, peers ...salticidae.PeerID) {
|
||||
ds := msg.DataStream()
|
||||
defer ds.Free()
|
||||
ba := salticidae.NewByteArrayMovedFromDataStream(ds, false)
|
||||
|
@ -290,81 +421,112 @@ func (nm *Handshake) send(msg Msg, addrs ...salticidae.NetAddr) {
|
|||
cMsg := salticidae.NewMsgMovedFromByteArray(msg.Op(), ba, false)
|
||||
defer cMsg.Free()
|
||||
|
||||
switch len(addrs) {
|
||||
switch len(peers) {
|
||||
case 0:
|
||||
case 1:
|
||||
nm.net.SendMsg(cMsg, addrs[0])
|
||||
nm.net.SendMsg(cMsg, peers[0])
|
||||
default:
|
||||
nm.net.MulticastMsgByMove(cMsg, addrs)
|
||||
nm.net.MulticastMsgByMove(cMsg, peers)
|
||||
}
|
||||
}
|
||||
|
||||
// checkPeerCertificate of a new inbound connection
|
||||
//export checkPeerCertificate
|
||||
func checkPeerCertificate(_ *C.struct_msgnetwork_conn_t, connected C.bool, _ unsafe.Pointer) C.bool {
|
||||
return connected
|
||||
// connHandler notifies of a new inbound connection
|
||||
//export connHandler
|
||||
func connHandler(_conn *C.struct_msgnetwork_conn_t, connected C.bool, _ unsafe.Pointer) C.bool {
|
||||
if !HandshakeNet.enableStaking || !bool(connected) {
|
||||
return connected
|
||||
}
|
||||
|
||||
HandshakeNet.requestedLock.Lock()
|
||||
defer HandshakeNet.requestedLock.Unlock()
|
||||
|
||||
conn := salticidae.MsgNetworkConnFromC(salticidae.CMsgNetworkConn(_conn))
|
||||
addr := conn.GetAddr()
|
||||
ip := toIPDesc(addr)
|
||||
ipStr := ip.String()
|
||||
|
||||
ipID := ids.NewID(hashing.ComputeHash256Array([]byte(ipStr)))
|
||||
HandshakeNet.requestedTimeout.Remove(ipID)
|
||||
|
||||
if _, exists := HandshakeNet.requested[ipStr]; !exists {
|
||||
HandshakeNet.log.Debug("connHandler called with %s", ip)
|
||||
return true
|
||||
}
|
||||
delete(HandshakeNet.requested, ipStr)
|
||||
|
||||
cert := conn.GetPeerCert()
|
||||
peer := salticidae.NewPeerIDFromX509(cert, true)
|
||||
|
||||
HandshakeNet.ConnectTo(peer, getCert(cert), addr)
|
||||
return true
|
||||
}
|
||||
|
||||
func (nm *Handshake) connectedToPeer(conn *C.struct_peernetwork_conn_t, addr salticidae.NetAddr) {
|
||||
ip := toIPDesc(addr)
|
||||
func (nm *Handshake) connectedToPeer(conn *C.struct_peernetwork_conn_t, peer salticidae.PeerID) {
|
||||
peerBytes := toID(peer)
|
||||
peerID := ids.NewID(peerBytes)
|
||||
|
||||
// If we're enforcing staking, use a peer's certificate to uniquely identify them
|
||||
// Otherwise, use a hash of their ip to identify them
|
||||
cert := ids.ShortID{}
|
||||
ipCert := toShortID(ip)
|
||||
if nm.enableStaking {
|
||||
cert = getPeerCert(conn)
|
||||
} else {
|
||||
cert = ipCert
|
||||
key := [20]byte{}
|
||||
copy(key[:], peerID.Bytes())
|
||||
cert = ids.NewShortID(key)
|
||||
}
|
||||
|
||||
nm.log.Debug("Connected to %s", ip)
|
||||
nm.log.Debug("Connected to %s", cert)
|
||||
|
||||
longCert := cert.LongID()
|
||||
nm.reconnectTimeout.Remove(longCert)
|
||||
nm.reconnectTimeout.Remove(ipCert.LongID())
|
||||
|
||||
nm.pending.Add(addr, cert)
|
||||
nm.reconnectTimeout.Remove(peerID)
|
||||
|
||||
handler := new(func())
|
||||
*handler = func() {
|
||||
if nm.pending.ContainsIP(addr) {
|
||||
nm.SendGetVersion(addr)
|
||||
nm.versionTimeout.Put(longCert, *handler)
|
||||
if nm.pending.ContainsPeerID(peer) {
|
||||
nm.SendGetVersion(peer)
|
||||
nm.versionTimeout.Put(peerID, *handler)
|
||||
}
|
||||
}
|
||||
(*handler)()
|
||||
}
|
||||
|
||||
func (nm *Handshake) disconnectedFromPeer(addr salticidae.NetAddr) {
|
||||
func (nm *Handshake) disconnectedFromPeer(peer salticidae.PeerID) {
|
||||
cert := ids.ShortID{}
|
||||
if pendingCert, exists := nm.pending.GetID(addr); exists {
|
||||
if pendingCert, exists := nm.pending.GetID(peer); exists {
|
||||
cert = pendingCert
|
||||
} else if connectedCert, exists := nm.connections.GetID(addr); exists {
|
||||
nm.log.Info("Disconnected from pending peer %s", cert)
|
||||
} else if connectedCert, exists := nm.connections.GetID(peer); exists {
|
||||
cert = connectedCert
|
||||
nm.log.Info("Disconnected from peer %s", cert)
|
||||
} else {
|
||||
return
|
||||
}
|
||||
|
||||
nm.log.Info("Disconnected from %s", toIPDesc(addr))
|
||||
peerBytes := toID(peer)
|
||||
peerID := ids.NewID(peerBytes)
|
||||
|
||||
nm.versionTimeout.Remove(peerID)
|
||||
nm.connections.Remove(peer, cert)
|
||||
nm.numPeers.Set(float64(nm.connections.Len()))
|
||||
|
||||
longCert := cert.LongID()
|
||||
if nm.vdrs.Contains(cert) {
|
||||
nm.reconnectTimeout.Put(longCert, func() {
|
||||
nm.net.DelPeer(addr)
|
||||
nm.reconnectTimeout.Put(peerID, func() {
|
||||
nm.pending.Remove(peer, cert)
|
||||
nm.connections.Remove(peer, cert)
|
||||
nm.net.DelPeer(peer)
|
||||
|
||||
nm.numPeers.Set(float64(nm.connections.Len()))
|
||||
})
|
||||
nm.pending.Add(peer, cert, utils.IPDesc{})
|
||||
} else {
|
||||
nm.net.DelPeer(addr)
|
||||
nm.pending.Remove(peer, cert)
|
||||
nm.net.DelPeer(peer)
|
||||
}
|
||||
nm.versionTimeout.Remove(longCert)
|
||||
|
||||
if !nm.enableStaking {
|
||||
nm.vdrs.Remove(cert)
|
||||
}
|
||||
|
||||
nm.pending.RemoveIP(addr)
|
||||
nm.connections.RemoveIP(addr)
|
||||
nm.numPeers.Set(float64(nm.connections.Len()))
|
||||
|
||||
nm.awaitingLock.Lock()
|
||||
defer nm.awaitingLock.Unlock()
|
||||
for _, awaiting := range HandshakeNet.awaiting {
|
||||
|
@ -372,57 +534,123 @@ func (nm *Handshake) disconnectedFromPeer(addr salticidae.NetAddr) {
|
|||
}
|
||||
}
|
||||
|
||||
// checkCompatibility Check to make sure that the peer and I speak the same language.
|
||||
func (nm *Handshake) checkCompatibility(peerVersion string) bool {
|
||||
if !strings.HasPrefix(peerVersion, VersionPrefix) {
|
||||
nm.log.Warn("Peer attempted to connect with an invalid version prefix")
|
||||
return false
|
||||
}
|
||||
peerVersion = peerVersion[len(VersionPrefix):]
|
||||
splitPeerVersion := strings.SplitN(peerVersion, VersionSeparator, 3)
|
||||
if len(splitPeerVersion) != 3 {
|
||||
nm.log.Warn("Peer attempted to connect with an invalid number of subversions")
|
||||
return false
|
||||
}
|
||||
|
||||
major, err := strconv.Atoi(splitPeerVersion[0])
|
||||
if err != nil {
|
||||
nm.log.Warn("Peer attempted to connect with an invalid major version")
|
||||
return false
|
||||
}
|
||||
minor, err := strconv.Atoi(splitPeerVersion[1])
|
||||
if err != nil {
|
||||
nm.log.Warn("Peer attempted to connect with an invalid minor version")
|
||||
return false
|
||||
}
|
||||
patch, err := strconv.Atoi(splitPeerVersion[2])
|
||||
if err != nil {
|
||||
nm.log.Warn("Peer attempted to connect with an invalid patch version")
|
||||
return false
|
||||
}
|
||||
|
||||
switch {
|
||||
case major < MajorVersion:
|
||||
// peers major version is too low
|
||||
return false
|
||||
case major > MajorVersion:
|
||||
nm.log.Warn("Peer attempted to connect with a higher major version, this client may need to be updated")
|
||||
return false
|
||||
}
|
||||
|
||||
switch {
|
||||
case minor < MinorVersion:
|
||||
// peers minor version is too low
|
||||
return false
|
||||
case minor > MinorVersion:
|
||||
nm.log.Warn("Peer attempted to connect with a higher minor version, this client may need to be updated")
|
||||
return false
|
||||
}
|
||||
|
||||
if patch > PatchVersion {
|
||||
nm.log.Warn("Peer is connecting with a higher patch version, this client may need to be updated")
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// peerHandler notifies a change to the set of connected peers
|
||||
// connected is true if a new peer is connected
|
||||
// connected is false if a formerly connected peer has disconnected
|
||||
//export peerHandler
|
||||
func peerHandler(_conn *C.struct_peernetwork_conn_t, connected C.bool, _ unsafe.Pointer) {
|
||||
HandshakeNet.log.Debug("peerHandler called")
|
||||
|
||||
pConn := salticidae.PeerNetworkConnFromC(salticidae.CPeerNetworkConn(_conn))
|
||||
addr := pConn.GetPeerAddr(true)
|
||||
peer := pConn.GetPeerID(true)
|
||||
|
||||
if connected {
|
||||
HandshakeNet.connectedToPeer(_conn, addr)
|
||||
HandshakeNet.connectedToPeer(_conn, peer)
|
||||
} else {
|
||||
HandshakeNet.disconnectedFromPeer(addr)
|
||||
HandshakeNet.disconnectedFromPeer(peer)
|
||||
}
|
||||
}
|
||||
|
||||
// unknownPeerHandler notifies of an unknown peer connection attempt
|
||||
//export unknownPeerHandler
|
||||
func unknownPeerHandler(_addr *C.netaddr_t, _cert *C.x509_t, _ unsafe.Pointer) {
|
||||
HandshakeNet.log.Debug("unknownPeerHandler called")
|
||||
|
||||
addr := salticidae.NetAddrFromC(salticidae.CNetAddr(_addr)).Copy(true)
|
||||
ip := toIPDesc(addr)
|
||||
|
||||
HandshakeNet.log.Info("Adding peer %s", ip)
|
||||
|
||||
cert := ids.ShortID{}
|
||||
var peer salticidae.PeerID
|
||||
var id ids.ShortID
|
||||
if HandshakeNet.enableStaking {
|
||||
cert = getCert(salticidae.X509FromC(salticidae.CX509(_cert)))
|
||||
cert := salticidae.X509FromC(salticidae.CX509(_cert))
|
||||
peer = salticidae.NewPeerIDFromX509(cert, true)
|
||||
id = getCert(cert)
|
||||
} else {
|
||||
cert = toShortID(ip)
|
||||
peer = salticidae.NewPeerIDFromNetAddr(addr, true)
|
||||
id = toShortID(ip)
|
||||
}
|
||||
|
||||
HandshakeNet.reconnectTimeout.Put(cert.LongID(), func() {
|
||||
HandshakeNet.net.DelPeer(addr)
|
||||
peerBytes := toID(peer)
|
||||
peerID := ids.NewID(peerBytes)
|
||||
|
||||
HandshakeNet.reconnectTimeout.Put(peerID, func() {
|
||||
HandshakeNet.pending.Remove(peer, id)
|
||||
HandshakeNet.connections.Remove(peer, id)
|
||||
HandshakeNet.net.DelPeer(peer)
|
||||
|
||||
HandshakeNet.numPeers.Set(float64(HandshakeNet.connections.Len()))
|
||||
})
|
||||
HandshakeNet.net.AddPeer(addr)
|
||||
HandshakeNet.pending.Add(peer, id, utils.IPDesc{})
|
||||
HandshakeNet.net.AddPeer(peer)
|
||||
}
|
||||
|
||||
// ping handles the recept of a ping message
|
||||
//export ping
|
||||
func ping(_ *C.struct_msg_t, _conn *C.struct_msgnetwork_conn_t, _ unsafe.Pointer) {
|
||||
conn := salticidae.PeerNetworkConnFromC(salticidae.CPeerNetworkConn(_conn))
|
||||
addr := conn.GetPeerAddr(false)
|
||||
defer addr.Free()
|
||||
if addr.IsNull() {
|
||||
HandshakeNet.log.Warn("Ping sent from unknown peer")
|
||||
return
|
||||
}
|
||||
peer := conn.GetPeerID(false)
|
||||
defer peer.Free()
|
||||
|
||||
build := Builder{}
|
||||
pong, err := build.Pong()
|
||||
HandshakeNet.log.AssertNoError(err)
|
||||
|
||||
HandshakeNet.send(pong, addr)
|
||||
HandshakeNet.send(pong, peer)
|
||||
}
|
||||
|
||||
// pong handles the recept of a pong message
|
||||
|
@ -435,15 +663,10 @@ func getVersion(_msg *C.struct_msg_t, _conn *C.struct_msgnetwork_conn_t, _ unsaf
|
|||
HandshakeNet.numGetVersionReceived.Inc()
|
||||
|
||||
conn := salticidae.PeerNetworkConnFromC(salticidae.CPeerNetworkConn(_conn))
|
||||
addr := conn.GetPeerAddr(false)
|
||||
defer addr.Free()
|
||||
peer := conn.GetPeerID(false)
|
||||
defer peer.Free()
|
||||
|
||||
if addr.IsNull() {
|
||||
HandshakeNet.log.Warn("GetVersion sent from unknown peer")
|
||||
return
|
||||
}
|
||||
|
||||
HandshakeNet.SendVersion(addr)
|
||||
HandshakeNet.SendVersion(peer)
|
||||
}
|
||||
|
||||
// version handles the recept of a version message
|
||||
|
@ -453,35 +676,33 @@ func version(_msg *C.struct_msg_t, _conn *C.struct_msgnetwork_conn_t, _ unsafe.P
|
|||
|
||||
msg := salticidae.MsgFromC(salticidae.CMsg(_msg))
|
||||
conn := salticidae.PeerNetworkConnFromC(salticidae.CPeerNetworkConn(_conn))
|
||||
addr := conn.GetPeerAddr(true)
|
||||
if addr.IsNull() {
|
||||
HandshakeNet.log.Warn("Version sent from unknown peer")
|
||||
peer := conn.GetPeerID(true)
|
||||
|
||||
peerBytes := toID(peer)
|
||||
peerID := ids.NewID(peerBytes)
|
||||
|
||||
HandshakeNet.versionTimeout.Remove(peerID)
|
||||
|
||||
id, exists := HandshakeNet.pending.GetID(peer)
|
||||
if !exists {
|
||||
HandshakeNet.log.Warn("Dropping Version message because the peer isn't pending")
|
||||
return
|
||||
}
|
||||
|
||||
cert := ids.ShortID{}
|
||||
if HandshakeNet.enableStaking {
|
||||
cert = getMsgCert(_conn)
|
||||
} else {
|
||||
ip := toIPDesc(addr)
|
||||
cert = toShortID(ip)
|
||||
}
|
||||
|
||||
defer HandshakeNet.pending.Remove(addr, cert)
|
||||
HandshakeNet.pending.Remove(peer, id)
|
||||
|
||||
build := Builder{}
|
||||
pMsg, err := build.Parse(Version, msg.GetPayloadByMove())
|
||||
if err != nil {
|
||||
HandshakeNet.log.Warn("Failed to parse Version message")
|
||||
|
||||
HandshakeNet.net.DelPeer(addr)
|
||||
HandshakeNet.net.DelPeer(peer)
|
||||
return
|
||||
}
|
||||
|
||||
if networkID := pMsg.Get(NetworkID).(uint32); networkID != HandshakeNet.networkID {
|
||||
HandshakeNet.log.Warn("Peer's network ID doesn't match our networkID: Peer's = %d ; Ours = %d", networkID, HandshakeNet.networkID)
|
||||
|
||||
HandshakeNet.net.DelPeer(addr)
|
||||
HandshakeNet.net.DelPeer(peer)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -489,36 +710,35 @@ func version(_msg *C.struct_msg_t, _conn *C.struct_msgnetwork_conn_t, _ unsafe.P
|
|||
if peerTime := float64(pMsg.Get(MyTime).(uint64)); math.Abs(peerTime-myTime) > MaxClockDifference.Seconds() {
|
||||
HandshakeNet.log.Warn("Peer's clock is too far out of sync with mine. His = %d, Mine = %d (seconds)", uint64(peerTime), uint64(myTime))
|
||||
|
||||
HandshakeNet.net.DelPeer(addr)
|
||||
HandshakeNet.net.DelPeer(peer)
|
||||
return
|
||||
}
|
||||
|
||||
if peerVersion := pMsg.Get(VersionStr).(string); !checkCompatibility(CurrentVersion, peerVersion) {
|
||||
HandshakeNet.log.Warn("Bad version")
|
||||
if peerVersion := pMsg.Get(VersionStr).(string); !HandshakeNet.checkCompatibility(peerVersion) {
|
||||
HandshakeNet.log.Debug("Dropping connection due to an incompatible version from peer")
|
||||
|
||||
HandshakeNet.net.DelPeer(addr)
|
||||
HandshakeNet.net.DelPeer(peer)
|
||||
return
|
||||
}
|
||||
|
||||
HandshakeNet.log.Debug("Finishing handshake with %s", toIPDesc(addr))
|
||||
ip := pMsg.Get(IP).(utils.IPDesc)
|
||||
|
||||
HandshakeNet.SendPeerList(addr)
|
||||
HandshakeNet.connections.Add(addr, cert)
|
||||
HandshakeNet.log.Debug("Finishing handshake with %s", ip)
|
||||
|
||||
HandshakeNet.versionTimeout.Remove(cert.LongID())
|
||||
HandshakeNet.SendPeerList(peer)
|
||||
HandshakeNet.connections.Add(peer, id, ip)
|
||||
HandshakeNet.numPeers.Set(float64(HandshakeNet.connections.Len()))
|
||||
|
||||
if !HandshakeNet.enableStaking {
|
||||
HandshakeNet.vdrs.Add(validators.NewValidator(cert, 1))
|
||||
HandshakeNet.vdrs.Add(validators.NewValidator(id, 1))
|
||||
}
|
||||
|
||||
HandshakeNet.numPeers.Set(float64(HandshakeNet.connections.Len()))
|
||||
|
||||
HandshakeNet.awaitingLock.Lock()
|
||||
defer HandshakeNet.awaitingLock.Unlock()
|
||||
|
||||
for i := 0; i < len(HandshakeNet.awaiting); i++ {
|
||||
awaiting := HandshakeNet.awaiting[i]
|
||||
awaiting.Add(cert)
|
||||
awaiting.Add(id)
|
||||
if !awaiting.Ready() {
|
||||
continue
|
||||
}
|
||||
|
@ -539,13 +759,10 @@ func getPeerList(_ *C.struct_msg_t, _conn *C.struct_msgnetwork_conn_t, _ unsafe.
|
|||
HandshakeNet.numGetPeerlistReceived.Inc()
|
||||
|
||||
conn := salticidae.PeerNetworkConnFromC(salticidae.CPeerNetworkConn(_conn))
|
||||
addr := conn.GetPeerAddr(false)
|
||||
defer addr.Free()
|
||||
if addr.IsNull() {
|
||||
HandshakeNet.log.Warn("GetPeerList sent from unknown peer")
|
||||
return
|
||||
}
|
||||
HandshakeNet.SendPeerList(addr)
|
||||
peer := conn.GetPeerID(false)
|
||||
defer peer.Free()
|
||||
|
||||
HandshakeNet.SendPeerList(peer)
|
||||
}
|
||||
|
||||
// peerList handles the recept of a peerList message
|
||||
|
@ -565,27 +782,15 @@ func peerList(_msg *C.struct_msg_t, _conn *C.struct_msgnetwork_conn_t, _ unsafe.
|
|||
ips := pMsg.Get(Peers).([]utils.IPDesc)
|
||||
cErr := salticidae.NewError()
|
||||
for _, ip := range ips {
|
||||
HandshakeNet.log.Verbo("Trying to adding peer %s", ip)
|
||||
addr := salticidae.NewNetAddrFromIPPortString(ip.String(), true, &cErr)
|
||||
if cErr.GetCode() == 0 && !HandshakeNet.myAddr.IsEq(addr) { // Make sure not to connect to myself
|
||||
ip := toIPDesc(addr)
|
||||
ipCert := toShortID(ip)
|
||||
|
||||
if !HandshakeNet.pending.ContainsIP(addr) && !HandshakeNet.connections.ContainsIP(addr) {
|
||||
HandshakeNet.log.Debug("Adding peer %s", ip)
|
||||
|
||||
HandshakeNet.reconnectTimeout.Put(ipCert.LongID(), func() {
|
||||
HandshakeNet.net.DelPeer(addr)
|
||||
})
|
||||
HandshakeNet.net.AddPeer(addr)
|
||||
}
|
||||
if cErr.GetCode() != 0 || HandshakeNet.myAddr.IsEq(addr) {
|
||||
// Make sure not to connect to myself
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getMsgCert(_conn *C.struct_msgnetwork_conn_t) ids.ShortID {
|
||||
conn := salticidae.MsgNetworkConnFromC(salticidae.CMsgNetworkConn(_conn))
|
||||
return getCert(conn.GetPeerCert())
|
||||
HandshakeNet.Connect(addr)
|
||||
}
|
||||
}
|
||||
|
||||
func getPeerCert(_conn *C.struct_peernetwork_conn_t) ids.ShortID {
|
||||
|
@ -595,29 +800,16 @@ func getPeerCert(_conn *C.struct_peernetwork_conn_t) ids.ShortID {
|
|||
|
||||
func getCert(cert salticidae.X509) ids.ShortID {
|
||||
der := cert.GetDer(false)
|
||||
defer der.Free()
|
||||
|
||||
certDS := salticidae.NewDataStreamMovedFromByteArray(der, false)
|
||||
defer certDS.Free()
|
||||
|
||||
certBytes := certDS.GetDataInPlace(certDS.Size()).Get()
|
||||
certID, err := ids.ToShortID(hashing.PubkeyBytesToAddress(certBytes))
|
||||
|
||||
certDS.Free()
|
||||
der.Free()
|
||||
HandshakeNet.log.AssertNoError(err)
|
||||
return certID
|
||||
}
|
||||
|
||||
// checkCompatibility Check to make sure that the peer and I speak the same language.
|
||||
func checkCompatibility(myVersion string, peerVersion string) bool {
|
||||
// At the moment, we are all compatible.
|
||||
return true
|
||||
}
|
||||
|
||||
func toAddr(ip utils.IPDesc, autoFree bool) salticidae.NetAddr {
|
||||
err := salticidae.NewError()
|
||||
addr := salticidae.NewNetAddrFromIPPortString(ip.String(), autoFree, &err)
|
||||
HandshakeNet.log.AssertTrue(err.GetCode() == 0, "IP Failed parsing")
|
||||
return addr
|
||||
}
|
||||
func toShortID(ip utils.IPDesc) ids.ShortID {
|
||||
return ids.NewShortID(hashing.ComputeHash160Array([]byte(ip.String())))
|
||||
}
|
||||
|
|
|
@ -89,12 +89,12 @@ func (s *Voting) Shutdown() { s.executor.Stop() }
|
|||
|
||||
// Accept is called after every consensus decision
|
||||
func (s *Voting) Accept(chainID, containerID ids.ID, container []byte) error {
|
||||
addrs := []salticidae.NetAddr(nil)
|
||||
peers := []salticidae.PeerID(nil)
|
||||
|
||||
allAddrs, allIDs := s.conns.RawConns()
|
||||
allPeers, allIDs, _ := s.conns.Conns()
|
||||
for i, id := range allIDs {
|
||||
if !s.vdrs.Contains(id) {
|
||||
addrs = append(addrs, allAddrs[i])
|
||||
peers = append(peers, allPeers[i])
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -109,25 +109,25 @@ func (s *Voting) Accept(chainID, containerID ids.ID, container []byte) error {
|
|||
"\nChain: %s"+
|
||||
"\nContainer ID: %s"+
|
||||
"\nContainer:\n%s",
|
||||
len(addrs),
|
||||
len(peers),
|
||||
chainID,
|
||||
containerID,
|
||||
formatting.DumpBytes{Bytes: container},
|
||||
)
|
||||
s.send(msg, addrs...)
|
||||
s.numPutSent.Add(float64(len(addrs)))
|
||||
s.send(msg, peers...)
|
||||
s.numPutSent.Add(float64(len(peers)))
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetAcceptedFrontier implements the Sender interface.
|
||||
func (s *Voting) GetAcceptedFrontier(validatorIDs ids.ShortSet, chainID ids.ID, requestID uint32) {
|
||||
addrs := []salticidae.NetAddr(nil)
|
||||
peers := []salticidae.PeerID(nil)
|
||||
validatorIDList := validatorIDs.List()
|
||||
for _, validatorID := range validatorIDList {
|
||||
vID := validatorID
|
||||
if addr, exists := s.conns.GetIP(vID); exists {
|
||||
addrs = append(addrs, addr)
|
||||
s.log.Verbo("Sending a GetAcceptedFrontier to %s", toIPDesc(addr))
|
||||
if peer, exists := s.conns.GetPeerID(vID); exists {
|
||||
peers = append(peers, peer)
|
||||
s.log.Verbo("Sending a GetAcceptedFrontier to %s", vID)
|
||||
} else {
|
||||
s.log.Debug("Attempted to send a GetAcceptedFrontier message to a disconnected validator: %s", vID)
|
||||
s.executor.Add(func() { s.router.GetAcceptedFrontierFailed(vID, chainID, requestID) })
|
||||
|
@ -142,17 +142,17 @@ func (s *Voting) GetAcceptedFrontier(validatorIDs ids.ShortSet, chainID ids.ID,
|
|||
"\nNumber of Validators: %d"+
|
||||
"\nChain: %s"+
|
||||
"\nRequest ID: %d",
|
||||
len(addrs),
|
||||
len(peers),
|
||||
chainID,
|
||||
requestID,
|
||||
)
|
||||
s.send(msg, addrs...)
|
||||
s.numGetAcceptedFrontierSent.Add(float64(len(addrs)))
|
||||
s.send(msg, peers...)
|
||||
s.numGetAcceptedFrontierSent.Add(float64(len(peers)))
|
||||
}
|
||||
|
||||
// AcceptedFrontier implements the Sender interface.
|
||||
func (s *Voting) AcceptedFrontier(validatorID ids.ShortID, chainID ids.ID, requestID uint32, containerIDs ids.Set) {
|
||||
addr, exists := s.conns.GetIP(validatorID)
|
||||
peer, exists := s.conns.GetPeerID(validatorID)
|
||||
if !exists {
|
||||
s.log.Debug("Attempted to send an AcceptedFrontier message to a disconnected validator: %s", validatorID)
|
||||
return // Validator is not connected
|
||||
|
@ -167,29 +167,27 @@ func (s *Voting) AcceptedFrontier(validatorID ids.ShortID, chainID ids.ID, reque
|
|||
|
||||
s.log.Verbo("Sending an AcceptedFrontier message."+
|
||||
"\nValidator: %s"+
|
||||
"\nDestination: %s"+
|
||||
"\nChain: %s"+
|
||||
"\nRequest ID: %d"+
|
||||
"\nContainer IDs: %s",
|
||||
validatorID,
|
||||
toIPDesc(addr),
|
||||
chainID,
|
||||
requestID,
|
||||
containerIDs,
|
||||
)
|
||||
s.send(msg, addr)
|
||||
s.send(msg, peer)
|
||||
s.numAcceptedFrontierSent.Inc()
|
||||
}
|
||||
|
||||
// GetAccepted implements the Sender interface.
|
||||
func (s *Voting) GetAccepted(validatorIDs ids.ShortSet, chainID ids.ID, requestID uint32, containerIDs ids.Set) {
|
||||
addrs := []salticidae.NetAddr(nil)
|
||||
peers := []salticidae.PeerID(nil)
|
||||
validatorIDList := validatorIDs.List()
|
||||
for _, validatorID := range validatorIDList {
|
||||
vID := validatorID
|
||||
if addr, exists := s.conns.GetIP(validatorID); exists {
|
||||
addrs = append(addrs, addr)
|
||||
s.log.Verbo("Sending a GetAccepted to %s", toIPDesc(addr))
|
||||
if peer, exists := s.conns.GetPeerID(validatorID); exists {
|
||||
peers = append(peers, peer)
|
||||
s.log.Verbo("Sending a GetAccepted to %s", vID)
|
||||
} else {
|
||||
s.log.Debug("Attempted to send a GetAccepted message to a disconnected validator: %s", vID)
|
||||
s.executor.Add(func() { s.router.GetAcceptedFailed(vID, chainID, requestID) })
|
||||
|
@ -199,8 +197,8 @@ func (s *Voting) GetAccepted(validatorIDs ids.ShortSet, chainID ids.ID, requestI
|
|||
build := Builder{}
|
||||
msg, err := build.GetAccepted(chainID, requestID, containerIDs)
|
||||
if err != nil {
|
||||
for _, addr := range addrs {
|
||||
if validatorID, exists := s.conns.GetID(addr); exists {
|
||||
for _, peer := range peers {
|
||||
if validatorID, exists := s.conns.GetID(peer); exists {
|
||||
s.executor.Add(func() { s.router.GetAcceptedFailed(validatorID, chainID, requestID) })
|
||||
}
|
||||
}
|
||||
|
@ -213,18 +211,18 @@ func (s *Voting) GetAccepted(validatorIDs ids.ShortSet, chainID ids.ID, requestI
|
|||
"\nChain: %s"+
|
||||
"\nRequest ID: %d"+
|
||||
"\nContainer IDs:%s",
|
||||
len(addrs),
|
||||
len(peers),
|
||||
chainID,
|
||||
requestID,
|
||||
containerIDs,
|
||||
)
|
||||
s.send(msg, addrs...)
|
||||
s.numGetAcceptedSent.Add(float64(len(addrs)))
|
||||
s.send(msg, peers...)
|
||||
s.numGetAcceptedSent.Add(float64(len(peers)))
|
||||
}
|
||||
|
||||
// Accepted implements the Sender interface.
|
||||
func (s *Voting) Accepted(validatorID ids.ShortID, chainID ids.ID, requestID uint32, containerIDs ids.Set) {
|
||||
addr, exists := s.conns.GetIP(validatorID)
|
||||
peer, exists := s.conns.GetPeerID(validatorID)
|
||||
if !exists {
|
||||
s.log.Debug("Attempted to send an Accepted message to a disconnected validator: %s", validatorID)
|
||||
return // Validator is not connected
|
||||
|
@ -239,23 +237,21 @@ func (s *Voting) Accepted(validatorID ids.ShortID, chainID ids.ID, requestID uin
|
|||
|
||||
s.log.Verbo("Sending an Accepted message."+
|
||||
"\nValidator: %s"+
|
||||
"\nDestination: %s"+
|
||||
"\nChain: %s"+
|
||||
"\nRequest ID: %d"+
|
||||
"\nContainer IDs: %s",
|
||||
validatorID,
|
||||
toIPDesc(addr),
|
||||
chainID,
|
||||
requestID,
|
||||
containerIDs,
|
||||
)
|
||||
s.send(msg, addr)
|
||||
s.send(msg, peer)
|
||||
s.numAcceptedSent.Inc()
|
||||
}
|
||||
|
||||
// Get implements the Sender interface.
|
||||
func (s *Voting) Get(validatorID ids.ShortID, chainID ids.ID, requestID uint32, containerID ids.ID) {
|
||||
addr, exists := s.conns.GetIP(validatorID)
|
||||
peer, exists := s.conns.GetPeerID(validatorID)
|
||||
if !exists {
|
||||
s.log.Debug("Attempted to send a Get message to a disconnected validator: %s", validatorID)
|
||||
s.executor.Add(func() { s.router.GetFailed(validatorID, chainID, requestID, containerID) })
|
||||
|
@ -268,23 +264,21 @@ func (s *Voting) Get(validatorID ids.ShortID, chainID ids.ID, requestID uint32,
|
|||
|
||||
s.log.Verbo("Sending a Get message."+
|
||||
"\nValidator: %s"+
|
||||
"\nDestination: %s"+
|
||||
"\nChain: %s"+
|
||||
"\nRequest ID: %d"+
|
||||
"\nContainer ID: %s",
|
||||
validatorID,
|
||||
toIPDesc(addr),
|
||||
chainID,
|
||||
requestID,
|
||||
containerID,
|
||||
)
|
||||
s.send(msg, addr)
|
||||
s.send(msg, peer)
|
||||
s.numGetSent.Inc()
|
||||
}
|
||||
|
||||
// Put implements the Sender interface.
|
||||
func (s *Voting) Put(validatorID ids.ShortID, chainID ids.ID, requestID uint32, containerID ids.ID, container []byte) {
|
||||
addr, exists := s.conns.GetIP(validatorID)
|
||||
peer, exists := s.conns.GetPeerID(validatorID)
|
||||
if !exists {
|
||||
s.log.Debug("Attempted to send a Container message to a disconnected validator: %s", validatorID)
|
||||
return // Validator is not connected
|
||||
|
@ -299,31 +293,29 @@ func (s *Voting) Put(validatorID ids.ShortID, chainID ids.ID, requestID uint32,
|
|||
|
||||
s.log.Verbo("Sending a Container message."+
|
||||
"\nValidator: %s"+
|
||||
"\nDestination: %s"+
|
||||
"\nChain: %s"+
|
||||
"\nRequest ID: %d"+
|
||||
"\nContainer ID: %s"+
|
||||
"\nContainer:\n%s",
|
||||
validatorID,
|
||||
toIPDesc(addr),
|
||||
chainID,
|
||||
requestID,
|
||||
containerID,
|
||||
formatting.DumpBytes{Bytes: container},
|
||||
)
|
||||
s.send(msg, addr)
|
||||
s.send(msg, peer)
|
||||
s.numPutSent.Inc()
|
||||
}
|
||||
|
||||
// PushQuery implements the Sender interface.
|
||||
func (s *Voting) PushQuery(validatorIDs ids.ShortSet, chainID ids.ID, requestID uint32, containerID ids.ID, container []byte) {
|
||||
addrs := []salticidae.NetAddr(nil)
|
||||
peers := []salticidae.PeerID(nil)
|
||||
validatorIDList := validatorIDs.List()
|
||||
for _, validatorID := range validatorIDList {
|
||||
vID := validatorID
|
||||
if addr, exists := s.conns.GetIP(vID); exists {
|
||||
addrs = append(addrs, addr)
|
||||
s.log.Verbo("Sending a PushQuery to %s", toIPDesc(addr))
|
||||
if peer, exists := s.conns.GetPeerID(vID); exists {
|
||||
peers = append(peers, peer)
|
||||
s.log.Verbo("Sending a PushQuery to %s", vID)
|
||||
} else {
|
||||
s.log.Debug("Attempted to send a PushQuery message to a disconnected validator: %s", vID)
|
||||
s.executor.Add(func() { s.router.QueryFailed(vID, chainID, requestID) })
|
||||
|
@ -333,8 +325,8 @@ func (s *Voting) PushQuery(validatorIDs ids.ShortSet, chainID ids.ID, requestID
|
|||
build := Builder{}
|
||||
msg, err := build.PushQuery(chainID, requestID, containerID, container)
|
||||
if err != nil {
|
||||
for _, addr := range addrs {
|
||||
if validatorID, exists := s.conns.GetID(addr); exists {
|
||||
for _, peer := range peers {
|
||||
if validatorID, exists := s.conns.GetID(peer); exists {
|
||||
s.executor.Add(func() { s.router.QueryFailed(validatorID, chainID, requestID) })
|
||||
}
|
||||
}
|
||||
|
@ -348,25 +340,25 @@ func (s *Voting) PushQuery(validatorIDs ids.ShortSet, chainID ids.ID, requestID
|
|||
"\nRequest ID: %d"+
|
||||
"\nContainer ID: %s"+
|
||||
"\nContainer:\n%s",
|
||||
len(addrs),
|
||||
len(peers),
|
||||
chainID,
|
||||
requestID,
|
||||
containerID,
|
||||
formatting.DumpBytes{Bytes: container},
|
||||
)
|
||||
s.send(msg, addrs...)
|
||||
s.numPushQuerySent.Add(float64(len(addrs)))
|
||||
s.send(msg, peers...)
|
||||
s.numPushQuerySent.Add(float64(len(peers)))
|
||||
}
|
||||
|
||||
// PullQuery implements the Sender interface.
|
||||
func (s *Voting) PullQuery(validatorIDs ids.ShortSet, chainID ids.ID, requestID uint32, containerID ids.ID) {
|
||||
addrs := []salticidae.NetAddr(nil)
|
||||
peers := []salticidae.PeerID(nil)
|
||||
validatorIDList := validatorIDs.List()
|
||||
for _, validatorID := range validatorIDList {
|
||||
vID := validatorID
|
||||
if addr, exists := s.conns.GetIP(vID); exists {
|
||||
addrs = append(addrs, addr)
|
||||
s.log.Verbo("Sending a PullQuery to %s", toIPDesc(addr))
|
||||
if peer, exists := s.conns.GetPeerID(vID); exists {
|
||||
peers = append(peers, peer)
|
||||
s.log.Verbo("Sending a PullQuery to %s", vID)
|
||||
} else {
|
||||
s.log.Warn("Attempted to send a PullQuery message to a disconnected validator: %s", vID)
|
||||
s.executor.Add(func() { s.router.QueryFailed(vID, chainID, requestID) })
|
||||
|
@ -382,18 +374,18 @@ func (s *Voting) PullQuery(validatorIDs ids.ShortSet, chainID ids.ID, requestID
|
|||
"\nChain: %s"+
|
||||
"\nRequest ID: %d"+
|
||||
"\nContainer ID: %s",
|
||||
len(addrs),
|
||||
len(peers),
|
||||
chainID,
|
||||
requestID,
|
||||
containerID,
|
||||
)
|
||||
s.send(msg, addrs...)
|
||||
s.numPullQuerySent.Add(float64(len(addrs)))
|
||||
s.send(msg, peers...)
|
||||
s.numPullQuerySent.Add(float64(len(peers)))
|
||||
}
|
||||
|
||||
// Chits implements the Sender interface.
|
||||
func (s *Voting) Chits(validatorID ids.ShortID, chainID ids.ID, requestID uint32, votes ids.Set) {
|
||||
addr, exists := s.conns.GetIP(validatorID)
|
||||
peer, exists := s.conns.GetPeerID(validatorID)
|
||||
if !exists {
|
||||
s.log.Debug("Attempted to send a Chits message to a disconnected validator: %s", validatorID)
|
||||
return // Validator is not connected
|
||||
|
@ -408,21 +400,19 @@ func (s *Voting) Chits(validatorID ids.ShortID, chainID ids.ID, requestID uint32
|
|||
|
||||
s.log.Verbo("Sending a Chits message."+
|
||||
"\nValidator: %s"+
|
||||
"\nDestination: %s"+
|
||||
"\nChain: %s"+
|
||||
"\nRequest ID: %d"+
|
||||
"\nNumber of Chits: %d",
|
||||
validatorID,
|
||||
toIPDesc(addr),
|
||||
chainID,
|
||||
requestID,
|
||||
votes.Len(),
|
||||
)
|
||||
s.send(msg, addr)
|
||||
s.send(msg, peer)
|
||||
s.numChitsSent.Inc()
|
||||
}
|
||||
|
||||
func (s *Voting) send(msg Msg, addrs ...salticidae.NetAddr) {
|
||||
func (s *Voting) send(msg Msg, peers ...salticidae.PeerID) {
|
||||
ds := msg.DataStream()
|
||||
defer ds.Free()
|
||||
ba := salticidae.NewByteArrayMovedFromDataStream(ds, false)
|
||||
|
@ -430,12 +420,12 @@ func (s *Voting) send(msg Msg, addrs ...salticidae.NetAddr) {
|
|||
cMsg := salticidae.NewMsgMovedFromByteArray(msg.Op(), ba, false)
|
||||
defer cMsg.Free()
|
||||
|
||||
switch len(addrs) {
|
||||
switch len(peers) {
|
||||
case 0:
|
||||
case 1:
|
||||
s.net.SendMsg(cMsg, addrs[0])
|
||||
s.net.SendMsg(cMsg, peers[0])
|
||||
default:
|
||||
s.net.MulticastMsgByMove(cMsg, addrs)
|
||||
s.net.MulticastMsgByMove(cMsg, peers)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -620,18 +610,16 @@ func chits(_msg *C.struct_msg_t, _conn *C.struct_msgnetwork_conn_t, _ unsafe.Poi
|
|||
|
||||
func (s *Voting) sanitize(_msg *C.struct_msg_t, _conn *C.struct_msgnetwork_conn_t, op salticidae.Opcode) (ids.ShortID, ids.ID, uint32, Msg, error) {
|
||||
conn := salticidae.PeerNetworkConnFromC(salticidae.CPeerNetworkConn((*C.peernetwork_conn_t)(_conn)))
|
||||
addr := conn.GetPeerAddr(false)
|
||||
defer addr.Free()
|
||||
if addr.IsNull() {
|
||||
return ids.ShortID{}, ids.ID{}, 0, nil, errConnectionDropped
|
||||
}
|
||||
s.log.Verbo("Receiving message from %s", toIPDesc(addr))
|
||||
peer := conn.GetPeerID(false)
|
||||
defer peer.Free()
|
||||
|
||||
validatorID, exists := s.conns.GetID(addr)
|
||||
validatorID, exists := s.conns.GetID(peer)
|
||||
if !exists {
|
||||
return ids.ShortID{}, ids.ID{}, 0, nil, fmt.Errorf("message received from an un-registered source: %s", toIPDesc(addr))
|
||||
return ids.ShortID{}, ids.ID{}, 0, nil, fmt.Errorf("message received from an un-registered peer")
|
||||
}
|
||||
|
||||
s.log.Verbo("Receiving message from %s", validatorID)
|
||||
|
||||
msg := salticidae.MsgFromC(salticidae.CMsg(_msg))
|
||||
codec := Codec{}
|
||||
pMsg, err := codec.Parse(op, msg.GetPayloadByMove())
|
||||
|
|
17
node/node.go
17
node/node.go
|
@ -5,7 +5,7 @@ package node
|
|||
|
||||
// #include "salticidae/network.h"
|
||||
// void onTerm(int sig, void *);
|
||||
// void errorHandler(SalticidaeCError *, bool, void *);
|
||||
// void errorHandler(SalticidaeCError *, bool, int32_t, void *);
|
||||
import "C"
|
||||
|
||||
import (
|
||||
|
@ -130,14 +130,14 @@ func onTerm(C.int, unsafe.Pointer) {
|
|||
}
|
||||
|
||||
//export errorHandler
|
||||
func errorHandler(_err *C.struct_SalticidaeCError, fatal C.bool, _ unsafe.Pointer) {
|
||||
func errorHandler(_err *C.struct_SalticidaeCError, fatal C.bool, asyncID C.int32_t, _ unsafe.Pointer) {
|
||||
err := (*salticidae.Error)(unsafe.Pointer(_err))
|
||||
if fatal {
|
||||
MainNode.Log.Fatal("Error during async call: %s", salticidae.StrError(err.GetCode()))
|
||||
MainNode.EC.Stop()
|
||||
return
|
||||
}
|
||||
MainNode.Log.Error("Error during async call: %s", salticidae.StrError(err.GetCode()))
|
||||
MainNode.Log.Debug("Error during async with ID %d call: %s", asyncID, salticidae.StrError(err.GetCode()))
|
||||
}
|
||||
|
||||
func (n *Node) initNetlib() error {
|
||||
|
@ -152,6 +152,8 @@ func (n *Node) initNetlib() error {
|
|||
|
||||
// Create peer network config, may have tls enabled
|
||||
peerConfig := salticidae.NewPeerNetworkConfig()
|
||||
peerConfig.ConnTimeout(60)
|
||||
|
||||
msgConfig := peerConfig.AsMsgNetworkConfig()
|
||||
msgConfig.MaxMsgSize(maxMessageSize)
|
||||
|
||||
|
@ -254,7 +256,7 @@ func (n *Node) StartConsensusServer() error {
|
|||
// Listen for P2P messages
|
||||
n.PeerNet.Listen(serverIP, &err)
|
||||
if code := err.GetCode(); code != 0 {
|
||||
return fmt.Errorf("failed to start consensus server: %s", salticidae.StrError(code))
|
||||
return fmt.Errorf("failed to listen on consensus server at %s: %s", n.Config.StakingIP, salticidae.StrError(code))
|
||||
}
|
||||
|
||||
// Start a server to handle throughput tests if configuration says to. Disabled by default.
|
||||
|
@ -268,18 +270,19 @@ func (n *Node) StartConsensusServer() error {
|
|||
|
||||
n.ClientNet.Listen(clientIP, &err)
|
||||
if code := err.GetCode(); code != 0 {
|
||||
return fmt.Errorf("failed to listen on xput server: %s", salticidae.StrError(code))
|
||||
return fmt.Errorf("failed to listen on xput server at 127.0.0.1:%d: %s", n.Config.ThroughputPort, salticidae.StrError(code))
|
||||
}
|
||||
}
|
||||
|
||||
// Add bootstrap nodes to the peer network
|
||||
for _, peer := range n.Config.BootstrapPeers {
|
||||
if !peer.IP.Equal(n.Config.StakingIP) {
|
||||
bootstrapIP := salticidae.NewNetAddrFromIPPortString(peer.IP.String(), true, &err)
|
||||
bootstrapAddr := salticidae.NewNetAddrFromIPPortString(peer.IP.String(), true, &err)
|
||||
if code := err.GetCode(); code != 0 {
|
||||
return fmt.Errorf("failed to create bootstrap ip addr: %s", salticidae.StrError(code))
|
||||
}
|
||||
n.PeerNet.AddPeer(bootstrapIP)
|
||||
|
||||
n.ValidatorAPI.Connect(bootstrapAddr)
|
||||
} else {
|
||||
n.Log.Error("can't add self as a bootstrapper")
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ borealis_bootstrap:
|
|||
staking_tls_enabled: true
|
||||
staking_tls_key_file: "/home/ubuntu/keys/staker.key"
|
||||
staking_tls_cert_file: "/home/ubuntu/keys/staker.crt"
|
||||
plugin_dir: "/home/ubuntu/go/src/github.com/ava-labs/gecko/build/plugins"
|
||||
log_dir: "/home/ubuntu/.gecko"
|
||||
log_level: debug
|
||||
snow_sample_size: 3
|
||||
|
@ -73,6 +74,7 @@ borealis_node:
|
|||
staking_tls_enabled: true
|
||||
staking_tls_key_file: "/home/ubuntu/keys/staker.key"
|
||||
staking_tls_cert_file: "/home/ubuntu/keys/staker.crt"
|
||||
plugin_dir: "/home/ubuntu/go/src/github.com/ava-labs/gecko/build/plugins"
|
||||
log_dir: "/home/ubuntu/.gecko"
|
||||
log_level: debug
|
||||
snow_sample_size: 3
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
|
||||
---
|
||||
- name: Update the network
|
||||
connection: ssh
|
||||
gather_facts: false
|
||||
hosts: all
|
||||
tasks:
|
||||
- name: Kill Node
|
||||
command: killall ava
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
---
|
||||
- name: Update the network
|
||||
connection: ssh
|
||||
gather_facts: false
|
||||
hosts: all
|
||||
tasks:
|
||||
- name: Ping node
|
||||
shell: "ls"
|
||||
environment:
|
||||
PATH: /sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin:/snap/bin
|
|
@ -7,8 +7,8 @@
|
|||
vars:
|
||||
ava_binary: ~/go/src/github.com/ava-labs/gecko/build/ava
|
||||
repo_folder: ~/go/src/github.com/ava-labs/gecko
|
||||
repo_name: ava-labs/gecko
|
||||
repo_branch: cascade
|
||||
repo_name: ava-labs/gecko-internal
|
||||
repo_branch: retry-connections
|
||||
tasks:
|
||||
- name: Kill Node
|
||||
command: killall ava
|
||||
|
@ -33,6 +33,6 @@
|
|||
path: "{{ log_dir }}"
|
||||
state: absent
|
||||
- name: Start node
|
||||
shell: "nohup {{ ava_binary }} --network-id={{ network_id }} --api-admin-enabled={{ api_admin_enabled }} --api-keystore-enabled={{ api_keystore_enabled }} --api-metrics-enabled={{ api_metrics_enabled }} --ava-tx-fee={{ ava_tx_fee }} --assertions-enabled={{ assertions_enabled }} --signature-verification-enabled={{ signature_verification_enabled }} --db-enabled={{ db_enabled }} --db-dir={{ db_dir }} --http-port={{ http_port }} --http-tls-enabled={{ http_tls_enabled }} --http-tls-key-file={{ http_tls_key_file }} --http-tls-cert-file={{ http_tls_cert_file }} --bootstrap-ips={{ bootstrap_ips }} --bootstrap-ids={{ bootstrap_ids }} --public-ip={{ ansible_host }} --staking-port={{ staking_port }} --staking-tls-enabled={{ staking_tls_enabled }} --staking-tls-key-file={{ staking_tls_key_file }} --staking-tls-cert-file={{ staking_tls_cert_file }} --log-dir={{ log_dir }} --log-level={{ log_level }} --snow-sample-size={{ snow_sample_size }} --snow-quorum-size={{ snow_quorum_size }} --snow-virtuous-commit-threshold={{ snow_virtuous_commit_threshold }} --snow-rogue-commit-threshold={{ snow_rogue_commit_threshold }} --snow-avalanche-num-parents={{ snow_avalanche_num_parents }} --snow-avalanche-batch-size={{ snow_avalanche_batch_size }} --api-ipcs-enabled={{ api_ipcs_enabled }} --xput-server-enabled={{ xput_server_enabled }} --xput-server-port={{ xput_server_port }} >/dev/null 2>&1 &"
|
||||
shell: "nohup {{ ava_binary }} --network-id={{ network_id }} --api-admin-enabled={{ api_admin_enabled }} --api-keystore-enabled={{ api_keystore_enabled }} --api-metrics-enabled={{ api_metrics_enabled }} --ava-tx-fee={{ ava_tx_fee }} --assertions-enabled={{ assertions_enabled }} --signature-verification-enabled={{ signature_verification_enabled }} --db-enabled={{ db_enabled }} --db-dir={{ db_dir }} --http-port={{ http_port }} --http-tls-enabled={{ http_tls_enabled }} --http-tls-key-file={{ http_tls_key_file }} --http-tls-cert-file={{ http_tls_cert_file }} --bootstrap-ips={{ bootstrap_ips }} --bootstrap-ids={{ bootstrap_ids }} --public-ip={{ ansible_host }} --staking-port={{ staking_port }} --staking-tls-enabled={{ staking_tls_enabled }} --staking-tls-key-file={{ staking_tls_key_file }} --staking-tls-cert-file={{ staking_tls_cert_file }} --plugin-dir={{ plugin_dir }} --log-dir={{ log_dir }} --log-level={{ log_level }} --snow-sample-size={{ snow_sample_size }} --snow-quorum-size={{ snow_quorum_size }} --snow-virtuous-commit-threshold={{ snow_virtuous_commit_threshold }} --snow-rogue-commit-threshold={{ snow_rogue_commit_threshold }} --snow-avalanche-num-parents={{ snow_avalanche_num_parents }} --snow-avalanche-batch-size={{ snow_avalanche_batch_size }} --api-ipcs-enabled={{ api_ipcs_enabled }} --xput-server-enabled={{ xput_server_enabled }} --xput-server-port={{ xput_server_port }} >/dev/null 2>&1 &"
|
||||
environment:
|
||||
PATH: /sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin:/snap/bin
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
vars:
|
||||
ava_binary: ~/go/src/github.com/ava-labs/gecko/build/ava
|
||||
repo_folder: ~/go/src/github.com/ava-labs/gecko
|
||||
repo_name: ava-labs/gecko
|
||||
repo_branch: cascade
|
||||
repo_name: ava-labs/gecko-internal
|
||||
repo_branch: retry-connections
|
||||
tasks:
|
||||
- name: Kill Node
|
||||
command: killall ava
|
||||
|
@ -25,6 +25,6 @@
|
|||
environment:
|
||||
PATH: /sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin:/snap/bin
|
||||
- name: Start node
|
||||
shell: "nohup {{ ava_binary }} --network-id={{ network_id }} --api-admin-enabled={{ api_admin_enabled }} --api-keystore-enabled={{ api_keystore_enabled }} --api-metrics-enabled={{ api_metrics_enabled }} --ava-tx-fee={{ ava_tx_fee }} --assertions-enabled={{ assertions_enabled }} --signature-verification-enabled={{ signature_verification_enabled }} --db-enabled={{ db_enabled }} --db-dir={{ db_dir }} --http-port={{ http_port }} --http-tls-enabled={{ http_tls_enabled }} --http-tls-key-file={{ http_tls_key_file }} --http-tls-cert-file={{ http_tls_cert_file }} --bootstrap-ips={{ bootstrap_ips }} --bootstrap-ids={{ bootstrap_ids }} --public-ip={{ ansible_host }} --staking-port={{ staking_port }} --staking-tls-enabled={{ staking_tls_enabled }} --staking-tls-key-file={{ staking_tls_key_file }} --staking-tls-cert-file={{ staking_tls_cert_file }} --log-dir={{ log_dir }} --log-level={{ log_level }} --snow-sample-size={{ snow_sample_size }} --snow-quorum-size={{ snow_quorum_size }} --snow-virtuous-commit-threshold={{ snow_virtuous_commit_threshold }} --snow-rogue-commit-threshold={{ snow_rogue_commit_threshold }} --snow-avalanche-num-parents={{ snow_avalanche_num_parents }} --snow-avalanche-batch-size={{ snow_avalanche_batch_size }} --api-ipcs-enabled={{ api_ipcs_enabled }} --xput-server-enabled={{ xput_server_enabled }} --xput-server-port={{ xput_server_port }} >/dev/null 2>&1 &"
|
||||
shell: "nohup {{ ava_binary }} --network-id={{ network_id }} --api-admin-enabled={{ api_admin_enabled }} --api-keystore-enabled={{ api_keystore_enabled }} --api-metrics-enabled={{ api_metrics_enabled }} --ava-tx-fee={{ ava_tx_fee }} --assertions-enabled={{ assertions_enabled }} --signature-verification-enabled={{ signature_verification_enabled }} --db-enabled={{ db_enabled }} --db-dir={{ db_dir }} --http-port={{ http_port }} --http-tls-enabled={{ http_tls_enabled }} --http-tls-key-file={{ http_tls_key_file }} --http-tls-cert-file={{ http_tls_cert_file }} --bootstrap-ips={{ bootstrap_ips }} --bootstrap-ids={{ bootstrap_ids }} --public-ip={{ ansible_host }} --staking-port={{ staking_port }} --staking-tls-enabled={{ staking_tls_enabled }} --staking-tls-key-file={{ staking_tls_key_file }} --staking-tls-cert-file={{ staking_tls_cert_file }} --plugin-dir={{ plugin_dir }} --log-dir={{ log_dir }} --log-level={{ log_level }} --snow-sample-size={{ snow_sample_size }} --snow-quorum-size={{ snow_quorum_size }} --snow-virtuous-commit-threshold={{ snow_virtuous_commit_threshold }} --snow-rogue-commit-threshold={{ snow_rogue_commit_threshold }} --snow-avalanche-num-parents={{ snow_avalanche_num_parents }} --snow-avalanche-batch-size={{ snow_avalanche_batch_size }} --api-ipcs-enabled={{ api_ipcs_enabled }} --xput-server-enabled={{ xput_server_enabled }} --xput-server-port={{ xput_server_port }} >/dev/null 2>&1 &"
|
||||
environment:
|
||||
PATH: /sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin:/snap/bin
|
||||
|
|
|
@ -6,14 +6,14 @@ Start a number of AVA nodes on Amazon EC2
|
|||
import boto3
|
||||
|
||||
|
||||
bootstapNode = "Borealis-Bootstrap"
|
||||
fullNode = "Borealis-Node"
|
||||
bootstapNode = "Cascade-Bootstrap"
|
||||
fullNode = "Cascade-Node"
|
||||
|
||||
|
||||
def runInstances(ec2, num: int, name: str):
|
||||
if num > 0:
|
||||
ec2.run_instances(
|
||||
ImageId="ami-0badd1c10cb7673e9",
|
||||
ImageId="ami-0c088c21fbcdb8a48",
|
||||
InstanceType="c5.large",
|
||||
MaxCount=num,
|
||||
MinCount=num,
|
||||
|
@ -29,11 +29,9 @@ def runInstances(ec2, num: int, name: str):
|
|||
def main():
|
||||
import argparse
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
description=__doc__,
|
||||
)
|
||||
parser.add_argument('numBootstraps', type=int)
|
||||
parser.add_argument('numNodes', type=int)
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("numBootstraps", type=int)
|
||||
parser.add_argument("numNodes", type=int)
|
||||
args = parser.parse_args()
|
||||
|
||||
ec2 = boto3.client("ec2")
|
||||
|
|
|
@ -17,6 +17,9 @@ if [[ -d "$CORETH_PATH/.git" ]]; then
|
|||
else
|
||||
go get -t -v -d "$CORETH_PKG/..."
|
||||
fi
|
||||
cd "$CORETH_PATH"
|
||||
git -c advice.detachedHead=false checkout v0.1.0
|
||||
cd -
|
||||
|
||||
GECKO_PKG=github.com/ava-labs/gecko
|
||||
GECKO_PATH="$GOPATH/src/$GECKO_PKG"
|
||||
|
@ -31,3 +34,8 @@ fi
|
|||
go build -o "$PREFIX/ava" "$GECKO_PATH/main/"*.go
|
||||
go build -o "$PREFIX/xputtest" "$GECKO_PATH/xputtest/"*.go
|
||||
go build -o "$PLUGIN_PREFIX/evm" "$CORETH_PATH/plugin/"*.go
|
||||
if [[ -f "$PREFIX/ava" && -f "$PREFIX/xputtest" && -f "$PLUGIN_PREFIX/evm" ]]; then
|
||||
echo "Build Successful"
|
||||
else
|
||||
echo "Build failure"
|
||||
fi
|
|
@ -9,5 +9,5 @@ SALTICIDAE_GO_HOME="$GOPATH/src/github.com/ava-labs/salticidae-go/"
|
|||
if [[ -f "$SALTICIDAE_GO_HOME/salticidae/libsalticidae.a" ]]; then
|
||||
source "$SALTICIDAE_GO_HOME/scripts/env.sh"
|
||||
else
|
||||
source /dev/stdin <<<"$(curl -sS https://raw.githubusercontent.com/ava-labs/salticidae-go/master/setup.sh)"
|
||||
source /dev/stdin <<<"$(curl -sS https://raw.githubusercontent.com/ava-labs/salticidae-go/v0.1.0/setup.sh)"
|
||||
fi
|
||||
|
|
|
@ -10,20 +10,21 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
errMsg = "__________ .___\n" +
|
||||
"\\______ \\____________ __| _/__.__.\n" +
|
||||
" | | _/\\_ __ \\__ \\ / __ < | |\n" +
|
||||
" | | \\ | | \\// __ \\_/ /_/ |\\___ |\n" +
|
||||
" |______ / |__| (____ /\\____ |/ ____|\n" +
|
||||
" \\/ \\/ \\/\\/\n" +
|
||||
errMsg = "" +
|
||||
`__________ .___` + "\n" +
|
||||
`\______ \____________ __| _/__.__.` + "\n" +
|
||||
` | | _/\_ __ \__ \ / __ < | |` + "\n" +
|
||||
` | | \ | | \// __ \_/ /_/ |\___ |` + "\n" +
|
||||
` |______ / |__| (____ /\____ |/ ____|` + "\n" +
|
||||
` \/ \/ \/\/` + "\n" +
|
||||
"\n" +
|
||||
"🏆 🏆 🏆 🏆 🏆 🏆\n" +
|
||||
" ________ ________ ________________\n" +
|
||||
" / _____/ \\_____ \\ / _ \\__ ___/\n" +
|
||||
"/ \\ ___ / | \\ / /_\\ \\| |\n" +
|
||||
"\\ \\_\\ \\/ | \\/ | \\ |\n" +
|
||||
" \\______ /\\_______ /\\____|__ /____|\n" +
|
||||
" \\/ \\/ \\/\n"
|
||||
`🏆 🏆 🏆 🏆 🏆 🏆` + "\n" +
|
||||
` ________ ________ ________________` + "\n" +
|
||||
` / _____/ \_____ \ / _ \__ ___/` + "\n" +
|
||||
`/ \ ___ / | \ / /_\ \| |` + "\n" +
|
||||
`\ \_\ \/ | \/ | \ |` + "\n" +
|
||||
` \______ /\_______ /\____|__ /____|` + "\n" +
|
||||
` \/ \/ \/` + "\n"
|
||||
)
|
||||
|
||||
// Parameters required for snowball consensus
|
||||
|
|
|
@ -177,9 +177,7 @@ func (b *bootstrapper) storeVertex(vtx avalanche.Vertex) {
|
|||
}
|
||||
}
|
||||
|
||||
for _, parent := range vtx.Parents() {
|
||||
vts = append(vts, parent)
|
||||
}
|
||||
vts = append(vts, vtx.Parents()...)
|
||||
case choices.Accepted:
|
||||
b.BootstrapConfig.Context.Log.Verbo("Bootstrapping confirmed %s", vtxID)
|
||||
case choices.Rejected:
|
||||
|
@ -207,6 +205,7 @@ func (b *bootstrapper) finish() {
|
|||
func (b *bootstrapper) executeAll(jobs *queue.Jobs, numBlocked prometheus.Gauge) {
|
||||
for job, err := jobs.Pop(); err == nil; job, err = jobs.Pop() {
|
||||
numBlocked.Dec()
|
||||
b.BootstrapConfig.Context.Log.Debug("Executing: %s", job.ID())
|
||||
if err := jobs.Execute(job); err != nil {
|
||||
b.BootstrapConfig.Context.Log.Warn("Error executing: %s", err)
|
||||
}
|
||||
|
|
|
@ -82,6 +82,10 @@ func (s *Serializer) ParseVertex(b []byte) (avacon.Vertex, error) {
|
|||
|
||||
// BuildVertex implements the avalanche.State interface
|
||||
func (s *Serializer) BuildVertex(parentSet ids.Set, txs []snowstorm.Tx) (avacon.Vertex, error) {
|
||||
if len(txs) == 0 {
|
||||
return nil, errNoTxs
|
||||
}
|
||||
|
||||
parentIDs := parentSet.List()
|
||||
ids.SortIDs(parentIDs)
|
||||
sortTxs(txs)
|
||||
|
|
|
@ -24,6 +24,7 @@ var (
|
|||
errExtraSpace = errors.New("trailing buffer space")
|
||||
errInvalidParents = errors.New("vertex contains non-sorted or duplicated parentIDs")
|
||||
errInvalidTxs = errors.New("vertex contains non-sorted or duplicated transactions")
|
||||
errNoTxs = errors.New("vertex contains no transactions")
|
||||
)
|
||||
|
||||
type vertex struct {
|
||||
|
@ -45,6 +46,8 @@ func (vtx *vertex) Verify() error {
|
|||
switch {
|
||||
case !ids.IsSortedAndUniqueIDs(vtx.parentIDs):
|
||||
return errInvalidParents
|
||||
case len(vtx.txs) == 0:
|
||||
return errNoTxs
|
||||
case !isSortedAndUniqueTxs(vtx.txs):
|
||||
return errInvalidTxs
|
||||
default:
|
||||
|
@ -55,7 +58,7 @@ func (vtx *vertex) Verify() error {
|
|||
/*
|
||||
* Vertex:
|
||||
* Codec | 04 Bytes
|
||||
* Chain | 32 Bytes
|
||||
* Chain | 32 Bytes
|
||||
* Height | 08 Bytes
|
||||
* NumParents | 04 Bytes
|
||||
* Repeated (NumParents):
|
||||
|
|
|
@ -316,8 +316,37 @@ func (t *Transitive) batch(txs []snowstorm.Tx, force, empty bool) {
|
|||
}
|
||||
}
|
||||
|
||||
if len(batch) > 0 || (empty && !issued) {
|
||||
if len(batch) > 0 {
|
||||
t.issueBatch(batch)
|
||||
} else if empty && !issued {
|
||||
t.issueRepoll()
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Transitive) issueRepoll() {
|
||||
preferredIDs := t.Consensus.Preferences().List()
|
||||
numPreferredIDs := len(preferredIDs)
|
||||
if numPreferredIDs == 0 {
|
||||
t.Config.Context.Log.Error("Re-query attempt was dropped due to no pending vertices")
|
||||
return
|
||||
}
|
||||
|
||||
sampler := random.Uniform{N: len(preferredIDs)}
|
||||
vtxID := preferredIDs[sampler.Sample()]
|
||||
|
||||
p := t.Consensus.Parameters()
|
||||
vdrs := t.Config.Validators.Sample(p.K) // Validators to sample
|
||||
|
||||
vdrSet := ids.ShortSet{} // Validators to sample repr. as a set
|
||||
for _, vdr := range vdrs {
|
||||
vdrSet.Add(vdr.ID())
|
||||
}
|
||||
|
||||
t.RequestID++
|
||||
if numVdrs := len(vdrs); numVdrs == p.K && t.polls.Add(t.RequestID, vdrSet.Len()) {
|
||||
t.Config.Sender.PullQuery(vdrSet, t.RequestID, vtxID)
|
||||
} else if numVdrs < p.K {
|
||||
t.Config.Context.Log.Error("Re-query for %s was dropped due to an insufficient number of validators", vtxID)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -698,23 +698,12 @@ func TestEngineScheduleRepoll(t *testing.T) {
|
|||
|
||||
sender.PushQueryF = nil
|
||||
|
||||
st.buildVertex = func(_ ids.Set, txs []snowstorm.Tx) (avalanche.Vertex, error) {
|
||||
consumers := []snowstorm.Tx{}
|
||||
for _, tx := range txs {
|
||||
consumers = append(consumers, tx)
|
||||
}
|
||||
return &Vtx{
|
||||
parents: []avalanche.Vertex{gVtx, mVtx},
|
||||
id: GenerateID(),
|
||||
txs: consumers,
|
||||
status: choices.Processing,
|
||||
bytes: []byte{1},
|
||||
}, nil
|
||||
}
|
||||
|
||||
repolled := new(bool)
|
||||
sender.PushQueryF = func(_ ids.ShortSet, _ uint32, _ ids.ID, _ []byte) {
|
||||
sender.PullQueryF = func(_ ids.ShortSet, _ uint32, vtxID ids.ID) {
|
||||
*repolled = true
|
||||
if !vtxID.Equals(vtx.ID()) {
|
||||
t.Fatalf("Wrong vertex queried")
|
||||
}
|
||||
}
|
||||
|
||||
te.QueryFailed(vdr.ID(), *requestID)
|
||||
|
@ -979,31 +968,14 @@ func TestEngineIssueRepoll(t *testing.T) {
|
|||
te.Initialize(config)
|
||||
te.finishBootstrapping()
|
||||
|
||||
newVtxID := new(ids.ID)
|
||||
|
||||
st.buildVertex = func(s ids.Set, txs []snowstorm.Tx) (avalanche.Vertex, error) {
|
||||
if len(txs) != 0 {
|
||||
t.Fatalf("Wrong vertex issued")
|
||||
}
|
||||
if s.Len() != 2 || !s.Contains(gVtx.ID()) || !s.Contains(mVtx.ID()) {
|
||||
t.Fatalf("Wrong vertex issued")
|
||||
}
|
||||
|
||||
vtx := &Vtx{
|
||||
parents: []avalanche.Vertex{gVtx, mVtx},
|
||||
id: GenerateID(),
|
||||
status: choices.Processing,
|
||||
bytes: []byte{1},
|
||||
}
|
||||
*newVtxID = vtx.ID()
|
||||
return vtx, nil
|
||||
}
|
||||
|
||||
sender.PushQueryF = func(vdrs ids.ShortSet, _ uint32, vtxID ids.ID, vtx []byte) {
|
||||
sender.PullQueryF = func(vdrs ids.ShortSet, _ uint32, vtxID ids.ID) {
|
||||
vdrSet := ids.ShortSet{}
|
||||
vdrSet.Add(vdr.ID())
|
||||
if !vdrs.Equals(vdrSet) || !vtxID.Equals(*newVtxID) {
|
||||
t.Fatalf("Wrong query message")
|
||||
if !vdrs.Equals(vdrSet) {
|
||||
t.Fatalf("Wrong query recipients")
|
||||
}
|
||||
if !vtxID.Equals(gVtx.ID()) && !vtxID.Equals(mVtx.ID()) {
|
||||
t.Fatalf("Unknown re-query")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -79,12 +79,23 @@ func (v *voter) bubbleVotes(votes ids.UniqueBag) ids.UniqueBag {
|
|||
vtx := vts[0]
|
||||
vts = vts[1:]
|
||||
|
||||
if status := vtx.Status(); status.Fetched() && !v.t.Consensus.VertexIssued(vtx) {
|
||||
vts = append(vts, vtx.Parents()...)
|
||||
} else if !status.Decided() && v.t.Consensus.VertexIssued(vtx) {
|
||||
status := vtx.Status()
|
||||
if !status.Fetched() {
|
||||
v.t.Config.Context.Log.Verbo("Dropping %d vote(s) for %s because the vertex is unknown", set.Len(), vtx.ID())
|
||||
continue
|
||||
}
|
||||
|
||||
if status.Decided() {
|
||||
v.t.Config.Context.Log.Verbo("Dropping %d vote(s) for %s because the vertex is decided", set.Len(), vtx.ID())
|
||||
continue
|
||||
}
|
||||
|
||||
if v.t.Consensus.VertexIssued(vtx) {
|
||||
v.t.Config.Context.Log.Verbo("Applying %d vote(s) for %s", set.Len(), vtx.ID())
|
||||
bubbledVotes.UnionSet(vtx.ID(), set)
|
||||
} else {
|
||||
v.t.Config.Context.Log.Debug("Dropping %d vote(s) for %s because the vertex is invalid", set.Len(), vtx.ID())
|
||||
v.t.Config.Context.Log.Verbo("Bubbling %d vote(s) for %s because the vertex isn't issued", set.Len(), vtx.ID())
|
||||
vts = append(vts, vtx.Parents()...)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
48
utils/ip.go
48
utils/ip.go
|
@ -10,6 +10,28 @@ import (
|
|||
"strconv"
|
||||
)
|
||||
|
||||
// This was taken from: https://stackoverflow.com/a/50825191/3478466
|
||||
var privateIPBlocks []*net.IPNet
|
||||
|
||||
func init() {
|
||||
for _, cidr := range []string{
|
||||
"127.0.0.0/8", // IPv4 loopback
|
||||
"10.0.0.0/8", // RFC1918
|
||||
"172.16.0.0/12", // RFC1918
|
||||
"192.168.0.0/16", // RFC1918
|
||||
"169.254.0.0/16", // RFC3927 link-local
|
||||
"::1/128", // IPv6 loopback
|
||||
"fe80::/10", // IPv6 link-local
|
||||
"fc00::/7", // IPv6 unique local addr
|
||||
} {
|
||||
_, block, err := net.ParseCIDR(cidr)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("parse error on %q: %v", cidr, err))
|
||||
}
|
||||
privateIPBlocks = append(privateIPBlocks, block)
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
errBadIP = errors.New("bad ip format")
|
||||
)
|
||||
|
@ -35,6 +57,32 @@ func (ipDesc IPDesc) String() string {
|
|||
return net.JoinHostPort(ipDesc.IP.String(), fmt.Sprintf("%d", ipDesc.Port))
|
||||
}
|
||||
|
||||
// IsPrivate attempts to decide if the ip address in this descriptor is a local
|
||||
// ip address.
|
||||
// This function was taken from: https://stackoverflow.com/a/50825191/3478466
|
||||
func (ipDesc IPDesc) IsPrivate() bool {
|
||||
ip := ipDesc.IP
|
||||
if ip.IsLoopback() || ip.IsLinkLocalUnicast() || ip.IsLinkLocalMulticast() {
|
||||
return true
|
||||
}
|
||||
|
||||
for _, block := range privateIPBlocks {
|
||||
if block.Contains(ip) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// IsZero returns if the IP or port is zeroed out
|
||||
func (ipDesc IPDesc) IsZero() bool {
|
||||
ip := ipDesc.IP
|
||||
return ipDesc.Port == 0 ||
|
||||
len(ip) == 0 ||
|
||||
ip.Equal(net.IPv4zero) ||
|
||||
ip.Equal(net.IPv6zero)
|
||||
}
|
||||
|
||||
// ToIPDesc ...
|
||||
func ToIPDesc(str string) (IPDesc, error) {
|
||||
host, portStr, err := net.SplitHostPort(str)
|
||||
|
|
|
@ -43,7 +43,7 @@ func (f *factory) Make() (Logger, error) {
|
|||
// MakeChain ...
|
||||
func (f *factory) MakeChain(chainID ids.ID, subdir string) (Logger, error) {
|
||||
config := f.config
|
||||
config.MsgPrefix = "SN " + chainID.String()
|
||||
config.MsgPrefix = "chain " + chainID.String()
|
||||
config.Directory = path.Join(config.Directory, "chain", chainID.String(), subdir)
|
||||
|
||||
log, err := New(config)
|
||||
|
|
|
@ -91,8 +91,10 @@ func (cr *codecRegistry) RegisterType(val interface{}) error {
|
|||
cr.typeToFxIndex[valType] = cr.index
|
||||
return cr.codec.RegisterType(val)
|
||||
}
|
||||
func (cr *codecRegistry) Marshal(val interface{}) ([]byte, error) { return cr.codec.Marshal(val) }
|
||||
func (cr *codecRegistry) Unmarshal(b []byte, val interface{}) error { return cr.codec.Unmarshal(b, val) }
|
||||
func (cr *codecRegistry) Marshal(val interface{}) ([]byte, error) { return cr.codec.Marshal(val) }
|
||||
func (cr *codecRegistry) Unmarshal(b []byte, val interface{}) error {
|
||||
return cr.codec.Unmarshal(b, val)
|
||||
}
|
||||
|
||||
/*
|
||||
******************************************************************************
|
||||
|
@ -392,7 +394,9 @@ func (vm *VM) initAliases(genesisBytes []byte) error {
|
|||
|
||||
txID := tx.ID()
|
||||
|
||||
vm.Alias(txID, genesisTx.Alias)
|
||||
if err = vm.Alias(txID, genesisTx.Alias); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -461,7 +465,10 @@ func (vm *VM) parseTx(b []byte) (*UniqueTx, error) {
|
|||
if err := vm.state.SetTx(tx.ID(), tx.Tx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tx.setStatus(choices.Processing)
|
||||
|
||||
if err := tx.setStatus(choices.Processing); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return tx, nil
|
||||
|
|
|
@ -943,3 +943,51 @@ func TestIssueProperty(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMFormat(t *testing.T) {
|
||||
_, _, vm := GenesisVM(t)
|
||||
defer ctx.Lock.Unlock()
|
||||
defer vm.Shutdown()
|
||||
|
||||
tests := []struct {
|
||||
in string
|
||||
expected string
|
||||
}{
|
||||
{"", "3D7sudhzUKTYFkYj4Zoe7GgSKhuyP9bYwXunHwhZsmQe1z9Mp-45PJLL"},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.in, func(t *testing.T) {
|
||||
if res := vm.Format([]byte(tt.in)); tt.expected != res {
|
||||
t.Errorf("Expected %q, got %q", tt.expected, res)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMFormatAliased(t *testing.T) {
|
||||
_, _, vm := GenesisVM(t)
|
||||
defer ctx.Lock.Unlock()
|
||||
defer vm.Shutdown()
|
||||
|
||||
origAliases := ctx.BCLookup
|
||||
defer func() { ctx.BCLookup = origAliases }()
|
||||
|
||||
tmpAliases := &ids.Aliaser{}
|
||||
tmpAliases.Initialize()
|
||||
tmpAliases.Alias(ctx.ChainID, "X")
|
||||
ctx.BCLookup = tmpAliases
|
||||
|
||||
tests := []struct {
|
||||
in string
|
||||
expected string
|
||||
}{
|
||||
{"", "X-45PJLL"},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.in, func(t *testing.T) {
|
||||
if res := vm.Format([]byte(tt.in)); tt.expected != res {
|
||||
t.Errorf("Expected %q, got %q", tt.expected, res)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -341,8 +341,5 @@ func (c codec) unmarshal(p *wrappers.Packer, field reflect.Value) error {
|
|||
|
||||
// Returns true iff [field] should be serialized
|
||||
func shouldSerialize(field reflect.StructField) bool {
|
||||
if field.Tag.Get("serialize") == "true" {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
return field.Tag.Get("serialize") == "true"
|
||||
}
|
||||
|
|
|
@ -95,10 +95,7 @@ func (svm *SnowmanVM) Shutdown() {
|
|||
// DBInitialized returns true iff [svm]'s database has values in it already
|
||||
func (svm *SnowmanVM) DBInitialized() bool {
|
||||
status := svm.State.GetStatus(svm.DB, dbInitializedID)
|
||||
if status == choices.Accepted {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
return status == choices.Accepted
|
||||
}
|
||||
|
||||
// SetDBInitialized marks the database as initialized
|
||||
|
|
|
@ -131,6 +131,8 @@ func (m *manager) addStaticAPIEndpoints(vmID ids.ID) {
|
|||
// register the static endpoints
|
||||
for extension, service := range staticVM.CreateStaticHandlers() {
|
||||
m.log.Verbo("adding static API endpoint: %s", defaultEndpoint+extension)
|
||||
m.apiServer.AddRoute(service, lock, defaultEndpoint, extension, m.log)
|
||||
if err := m.apiServer.AddRoute(service, lock, defaultEndpoint, extension, m.log); err != nil {
|
||||
m.log.Warn("failed to add static API endpoint %s: %v", fmt.Sprintf("%s%s", defaultEndpoint, extension), err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1227,6 +1227,10 @@ func (service *Service) chainExists(blockID ids.ID, chainID ids.ID) (bool, error
|
|||
db := block.onAccept()
|
||||
|
||||
chains, err := service.vm.getChains(db)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
for _, chain := range chains {
|
||||
if chain.ID().Equals(chainID) {
|
||||
return true, nil
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
)
|
||||
|
||||
func TestAddDefaultSubnetValidator(t *testing.T) {
|
||||
expectedJSONString := `{"startTime":"0","endtime":"0","id":null,"destination":null,"delegationFeeRate":"0","payerNonce":"0"}`
|
||||
expectedJSONString := `{"startTime":"0","endTime":"0","id":null,"destination":null,"delegationFeeRate":"0","payerNonce":"0"}`
|
||||
args := AddDefaultSubnetValidatorArgs{}
|
||||
bytes, err := json.Marshal(&args)
|
||||
if err != nil {
|
||||
|
|
|
@ -44,7 +44,7 @@ type APIAccount struct {
|
|||
// is sent when this staker is done staking.
|
||||
type APIValidator struct {
|
||||
StartTime json.Uint64 `json:"startTime"`
|
||||
EndTime json.Uint64 `json:"endtime"`
|
||||
EndTime json.Uint64 `json:"endTime"`
|
||||
Weight *json.Uint64 `json:"weight,omitempty"`
|
||||
StakeAmount *json.Uint64 `json:"stakeAmount,omitempty"`
|
||||
ID ids.ShortID `json:"id"`
|
||||
|
|
Loading…
Reference in New Issue