mirror of https://github.com/poanetwork/gecko.git
1-way handshake on a staking network
This commit is contained in:
parent
c6b92425ef
commit
aa60e61c5c
|
@ -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.")
|
||||
|
|
|
@ -157,11 +157,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)
|
||||
}
|
||||
|
|
|
@ -115,6 +115,8 @@ type Handshake struct {
|
|||
|
||||
awaitingLock sync.Mutex
|
||||
awaiting []*networking.AwaitingConnections
|
||||
|
||||
requestedConnections map[string]struct{}
|
||||
}
|
||||
|
||||
// Initialize to the c networking library. This should only be done once during
|
||||
|
@ -141,6 +143,8 @@ func (nm *Handshake) Initialize(
|
|||
nm.pending = NewConnections()
|
||||
nm.connections = NewConnections()
|
||||
|
||||
nm.requestedConnections = make(map[string]struct{})
|
||||
|
||||
net := peerNet.AsMsgNetwork()
|
||||
|
||||
net.RegConnHandler(salticidae.MsgNetworkConnCallback(C.connHandler), nil)
|
||||
|
@ -165,6 +169,23 @@ func (nm *Handshake) Initialize(
|
|||
go nm.log.RecoverAndPanic(nm.peerListGossiper.Dispatch)
|
||||
}
|
||||
|
||||
// Connect ...
|
||||
func (nm *Handshake) Connect(addr salticidae.NetAddr) {
|
||||
if !nm.enableStaking {
|
||||
peer := salticidae.NewPeerIDFromNetAddr(addr, false)
|
||||
nm.net.AddPeer(peer)
|
||||
nm.net.SetPeerAddr(peer, addr)
|
||||
nm.net.ConnPeer(peer, 600, 1)
|
||||
peer.Free()
|
||||
} else {
|
||||
ip := toIPDesc(addr)
|
||||
nm.requestedConnections[ip.String()] = struct{}{}
|
||||
|
||||
msgNet := nm.net.AsMsgNetwork()
|
||||
msgNet.Connect(addr)
|
||||
}
|
||||
}
|
||||
|
||||
// AwaitConnections ...
|
||||
func (nm *Handshake) AwaitConnections(awaiting *networking.AwaitingConnections) {
|
||||
nm.awaitingLock.Lock()
|
||||
|
@ -264,7 +285,7 @@ func (nm *Handshake) SendPeerList(peers ...salticidae.PeerID) error {
|
|||
ipsToSend := []utils.IPDesc(nil)
|
||||
for i, id := range ids {
|
||||
ip := ips[i]
|
||||
if !ip.IsPrivate() && nm.vdrs.Contains(id) {
|
||||
if !ip.IsZero() && nm.vdrs.Contains(id) {
|
||||
ipsToSend = append(ipsToSend, ip)
|
||||
}
|
||||
}
|
||||
|
@ -305,28 +326,51 @@ func (nm *Handshake) send(msg Msg, peers ...salticidae.PeerID) {
|
|||
|
||||
// connHandler notifies of a new inbound connection
|
||||
//export connHandler
|
||||
func connHandler(_ *C.struct_msgnetwork_conn_t, connected C.bool, _ unsafe.Pointer) C.bool {
|
||||
HandshakeNet.log.Error("connHandler called")
|
||||
return connected
|
||||
func connHandler(_conn *C.struct_msgnetwork_conn_t, connected C.bool, _ unsafe.Pointer) C.bool {
|
||||
if !HandshakeNet.enableStaking || !bool(connected) {
|
||||
return connected
|
||||
}
|
||||
|
||||
conn := salticidae.MsgNetworkConnFromC(salticidae.CMsgNetworkConn(_conn))
|
||||
addr := conn.GetAddr()
|
||||
ip := toIPDesc(addr)
|
||||
|
||||
ipStr := ip.String()
|
||||
if _, exists := HandshakeNet.requestedConnections[ipStr]; !exists {
|
||||
HandshakeNet.log.Debug("connHandler called with %s", ip)
|
||||
return true
|
||||
}
|
||||
delete(HandshakeNet.requestedConnections, ipStr)
|
||||
|
||||
cert := conn.GetPeerCert()
|
||||
peer := salticidae.NewPeerIDFromX509(cert, false)
|
||||
|
||||
HandshakeNet.net.AddPeer(peer)
|
||||
HandshakeNet.net.SetPeerAddr(peer, addr)
|
||||
HandshakeNet.net.ConnPeer(peer, 600, 1)
|
||||
|
||||
peer.Free()
|
||||
return true
|
||||
}
|
||||
|
||||
func (nm *Handshake) connectedToPeer(conn *C.struct_peernetwork_conn_t, peer salticidae.PeerID, 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.reconnectTimeout.Remove(peerID)
|
||||
|
||||
nm.pending.Add(peer, cert, utils.IPDesc{})
|
||||
|
||||
|
@ -334,13 +378,13 @@ func (nm *Handshake) connectedToPeer(conn *C.struct_peernetwork_conn_t, peer sal
|
|||
*handler = func() {
|
||||
if nm.pending.ContainsPeerID(peer) {
|
||||
nm.SendGetVersion(peer)
|
||||
nm.versionTimeout.Put(longCert, *handler)
|
||||
nm.versionTimeout.Put(peerID, *handler)
|
||||
}
|
||||
}
|
||||
(*handler)()
|
||||
}
|
||||
|
||||
func (nm *Handshake) disconnectedFromPeer(peer salticidae.PeerID, addr salticidae.NetAddr) {
|
||||
func (nm *Handshake) disconnectedFromPeer(peer salticidae.PeerID) {
|
||||
cert := ids.ShortID{}
|
||||
if pendingCert, exists := nm.pending.GetID(peer); exists {
|
||||
cert = pendingCert
|
||||
|
@ -350,17 +394,19 @@ func (nm *Handshake) disconnectedFromPeer(peer salticidae.PeerID, addr salticida
|
|||
return
|
||||
}
|
||||
|
||||
nm.log.Info("Disconnected from %s", toIPDesc(addr))
|
||||
nm.log.Info("Disconnected from %s", cert)
|
||||
|
||||
peerBytes := toID(peer)
|
||||
peerID := ids.NewID(peerBytes)
|
||||
|
||||
longCert := cert.LongID()
|
||||
if nm.vdrs.Contains(cert) {
|
||||
nm.reconnectTimeout.Put(longCert, func() {
|
||||
nm.reconnectTimeout.Put(peerID, func() {
|
||||
nm.net.DelPeer(peer)
|
||||
})
|
||||
} else {
|
||||
nm.net.DelPeer(peer)
|
||||
}
|
||||
nm.versionTimeout.Remove(longCert)
|
||||
nm.versionTimeout.Remove(peerID)
|
||||
|
||||
if !nm.enableStaking {
|
||||
nm.vdrs.Remove(cert)
|
||||
|
@ -382,23 +428,22 @@ func (nm *Handshake) disconnectedFromPeer(peer salticidae.PeerID, addr salticida
|
|||
// 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.Error("peerHandler called")
|
||||
HandshakeNet.log.Debug("peerHandler called")
|
||||
|
||||
pConn := salticidae.PeerNetworkConnFromC(salticidae.CPeerNetworkConn(_conn))
|
||||
addr := pConn.GetPeerAddr(true)
|
||||
peer := pConn.GetPeerID(true)
|
||||
|
||||
if connected {
|
||||
HandshakeNet.connectedToPeer(_conn, peer, addr)
|
||||
HandshakeNet.connectedToPeer(_conn, peer)
|
||||
} else {
|
||||
HandshakeNet.disconnectedFromPeer(peer, 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.Error("unknownPeerHandler called")
|
||||
HandshakeNet.log.Debug("unknownPeerHandler called")
|
||||
|
||||
addr := salticidae.NetAddrFromC(salticidae.CNetAddr(_addr)).Copy(true)
|
||||
ip := toIPDesc(addr)
|
||||
|
@ -406,17 +451,17 @@ func unknownPeerHandler(_addr *C.netaddr_t, _cert *C.x509_t, _ unsafe.Pointer) {
|
|||
HandshakeNet.log.Info("Adding peer %s", ip)
|
||||
|
||||
var peer salticidae.PeerID
|
||||
id := ids.ShortID{}
|
||||
if HandshakeNet.enableStaking {
|
||||
cert := salticidae.X509FromC(salticidae.CX509(_cert))
|
||||
id = getCert(cert)
|
||||
peer = salticidae.NewPeerIDFromX509(cert, true)
|
||||
} else {
|
||||
id = toShortID(ip)
|
||||
peer = salticidae.NewPeerIDFromNetAddr(addr, true)
|
||||
}
|
||||
|
||||
HandshakeNet.reconnectTimeout.Put(id.LongID(), func() {
|
||||
peerBytes := toID(peer)
|
||||
peerID := ids.NewID(peerBytes)
|
||||
|
||||
HandshakeNet.reconnectTimeout.Put(peerID, func() {
|
||||
HandshakeNet.net.DelPeer(peer)
|
||||
})
|
||||
HandshakeNet.net.AddPeer(peer)
|
||||
|
@ -506,7 +551,10 @@ func version(_msg *C.struct_msg_t, _conn *C.struct_msgnetwork_conn_t, _ unsafe.P
|
|||
HandshakeNet.SendPeerList(peer)
|
||||
HandshakeNet.connections.Add(peer, id, ip)
|
||||
|
||||
HandshakeNet.versionTimeout.Remove(id.LongID())
|
||||
peerBytes := toID(peer)
|
||||
peerID := ids.NewID(peerBytes)
|
||||
|
||||
HandshakeNet.versionTimeout.Remove(peerID)
|
||||
|
||||
if !HandshakeNet.enableStaking {
|
||||
HandshakeNet.vdrs.Add(validators.NewValidator(id, 1))
|
||||
|
@ -560,19 +608,16 @@ func peerList(_msg *C.struct_msg_t, _conn *C.struct_msgnetwork_conn_t, _ unsafe.
|
|||
return
|
||||
}
|
||||
|
||||
msgNet := HandshakeNet.net.AsMsgNetwork()
|
||||
|
||||
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)
|
||||
if !HandshakeNet.pending.ContainsIP(ip) && !HandshakeNet.connections.ContainsIP(ip) {
|
||||
HandshakeNet.log.Debug("Adding peer %s", ip)
|
||||
|
||||
msgNet.Connect(addr)
|
||||
HandshakeNet.Connect(addr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -272,16 +272,15 @@ func (n *Node) StartConsensusServer() error {
|
|||
}
|
||||
}
|
||||
|
||||
msgNet := n.PeerNet.AsMsgNetwork()
|
||||
|
||||
// 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))
|
||||
}
|
||||
msgNet.Connect(bootstrapIP)
|
||||
|
||||
n.ValidatorAPI.Connect(bootstrapAddr)
|
||||
} else {
|
||||
n.Log.Error("can't add self as a bootstrapper")
|
||||
}
|
||||
|
|
10
utils/ip.go
10
utils/ip.go
|
@ -71,8 +71,14 @@ func (ipDesc IPDesc) IsPrivate() bool {
|
|||
return true
|
||||
}
|
||||
}
|
||||
// added so that default ips will be marked as private
|
||||
return len(ip) == 0 ||
|
||||
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)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue