github.com/aergoio/aergo@v1.3.1/p2p/v030/v032handshake.go (about) 1 /* 2 * @file 3 * @copyright defined in aergo/LICENSE.txt 4 */ 5 6 package v030 7 8 import ( 9 "bytes" 10 "context" 11 "fmt" 12 "github.com/aergoio/aergo-lib/log" 13 "github.com/aergoio/aergo/internal/enc" 14 "github.com/aergoio/aergo/p2p/p2pcommon" 15 "github.com/aergoio/aergo/p2p/p2putil" 16 "github.com/aergoio/aergo/types" 17 "io" 18 ) 19 20 // V032Handshaker exchange status data over protocol version .0.3.1 21 // it 22 type V032Handshaker struct { 23 V030Handshaker 24 localGenesisHash []byte 25 } 26 27 var _ p2pcommon.VersionedHandshaker = (*V032Handshaker)(nil) 28 29 func (h *V032Handshaker) GetMsgRW() p2pcommon.MsgReadWriter { 30 return h.msgRW 31 } 32 33 func NewV032VersionedHS(pm p2pcommon.PeerManager, actor p2pcommon.ActorService, log *log.Logger, chainID *types.ChainID, peerID types.PeerID, rwc io.ReadWriteCloser, genesis []byte) *V032Handshaker { 34 h := &V032Handshaker{V030Handshaker{pm: pm, actor: actor, logger: log, chainID: chainID, peerID: peerID}, 35 genesis} 36 h.msgRW = NewV030MsgPipe(rwc) 37 return h 38 } 39 40 func (h *V032Handshaker) checkRemoteStatus(remotePeerStatus *types.Status) error { 41 // v0.3.2 just added genesis hash 42 if err := h.V030Handshaker.checkRemoteStatus(remotePeerStatus); err != nil { 43 return err 44 } 45 // do additional check for genesises are identical 46 genHash := h.localGenesisHash 47 if !bytes.Equal(genHash, remotePeerStatus.Genesis) { 48 h.sendGoAway("different genesis block") 49 return fmt.Errorf("different genesis block local: %v , remote %v", enc.ToString(genHash), enc.ToString(remotePeerStatus.Genesis)) 50 } 51 52 return nil 53 } 54 55 56 func (h *V032Handshaker) DoForOutbound(ctx context.Context) (*types.Status, error) { 57 // TODO need to check auth at first... 58 h.logger.Debug().Str(p2putil.LogPeerID, p2putil.ShortForm(h.peerID)).Msg("Starting versioned handshake for outbound peer connection") 59 60 // outbound: send, receive and check 61 localStatus, err := createStatus(h.pm, h.actor, h.chainID, h.localGenesisHash) 62 if err != nil { 63 h.logger.Warn().Err(err).Msg("Failed to create status message.") 64 h.sendGoAway("internal error") 65 return nil, err 66 } 67 err = h.sendLocalStatus(ctx, localStatus) 68 if err != nil { 69 return nil, err 70 } 71 72 remotePeerStatus, err := h.receiveRemoteStatus(ctx) 73 if err != nil { 74 return nil, err 75 } 76 77 if err = h.checkRemoteStatus(remotePeerStatus); err != nil { 78 return nil, err 79 } else { 80 return remotePeerStatus, nil 81 } 82 83 } 84 85 func (h *V032Handshaker) DoForInbound(ctx context.Context) (*types.Status, error) { 86 // TODO need to check auth at first... 87 h.logger.Debug().Str(p2putil.LogPeerID, p2putil.ShortForm(h.peerID)).Msg("Starting versioned handshake for inbound peer connection") 88 89 // inbound: receive, check and send 90 remotePeerStatus, err := h.receiveRemoteStatus(ctx) 91 if err != nil { 92 return nil, err 93 } 94 if err = h.checkRemoteStatus(remotePeerStatus); err != nil { 95 return nil, err 96 } 97 98 // send my status message as response 99 localStatus, err := createStatus(h.pm, h.actor, h.chainID, h.localGenesisHash) 100 if err != nil { 101 h.logger.Warn().Err(err).Msg("Failed to create status message.") 102 h.sendGoAway("internal error") 103 return nil, err 104 } 105 err = h.sendLocalStatus(ctx, localStatus) 106 if err != nil { 107 return nil, err 108 } 109 return remotePeerStatus, nil 110 }