github.com/pure-x-eth/consensus_tm@v0.0.0-20230502163723-e3c2ff987250/blockchain/v2/io.go (about) 1 package v2 2 3 import ( 4 "fmt" 5 6 "github.com/pure-x-eth/consensus_tm/p2p" 7 bcproto "github.com/pure-x-eth/consensus_tm/proto/tendermint/blockchain" 8 "github.com/pure-x-eth/consensus_tm/state" 9 "github.com/pure-x-eth/consensus_tm/types" 10 ) 11 12 type iIO interface { 13 sendBlockRequest(peerID p2p.ID, height int64) error 14 sendBlockToPeer(block *types.Block, peerID p2p.ID) error 15 sendBlockNotFound(height int64, peerID p2p.ID) error 16 sendStatusResponse(base, height int64, peerID p2p.ID) error 17 18 broadcastStatusRequest() 19 20 trySwitchToConsensus(state state.State, skipWAL bool) bool 21 } 22 23 type switchIO struct { 24 sw *p2p.Switch 25 } 26 27 func newSwitchIo(sw *p2p.Switch) *switchIO { 28 return &switchIO{ 29 sw: sw, 30 } 31 } 32 33 const ( 34 // BlockchainChannel is a channel for blocks and status updates (`BlockStore` height) 35 BlockchainChannel = byte(0x40) 36 ) 37 38 type consensusReactor interface { 39 // for when we switch from blockchain reactor and fast sync to 40 // the consensus machine 41 SwitchToConsensus(state state.State, skipWAL bool) 42 } 43 44 func (sio *switchIO) sendBlockRequest(peerID p2p.ID, height int64) error { 45 peer := sio.sw.Peers().Get(peerID) 46 if peer == nil { 47 return fmt.Errorf("peer not found") 48 } 49 if queued := p2p.TrySendEnvelopeShim(peer, p2p.Envelope{ //nolint: staticcheck 50 ChannelID: BlockchainChannel, 51 Message: &bcproto.BlockRequest{Height: height}, 52 }, sio.sw.Logger); !queued { 53 return fmt.Errorf("send queue full") 54 } 55 return nil 56 } 57 58 func (sio *switchIO) sendStatusResponse(base int64, height int64, peerID p2p.ID) error { 59 peer := sio.sw.Peers().Get(peerID) 60 if peer == nil { 61 return fmt.Errorf("peer not found") 62 } 63 64 if queued := p2p.TrySendEnvelopeShim(peer, p2p.Envelope{ //nolint: staticcheck 65 ChannelID: BlockchainChannel, 66 Message: &bcproto.StatusRequest{}, 67 }, sio.sw.Logger); !queued { 68 return fmt.Errorf("peer queue full") 69 } 70 71 return nil 72 } 73 74 func (sio *switchIO) sendBlockToPeer(block *types.Block, peerID p2p.ID) error { 75 peer := sio.sw.Peers().Get(peerID) 76 if peer == nil { 77 return fmt.Errorf("peer not found") 78 } 79 if block == nil { 80 panic("trying to send nil block") 81 } 82 83 bpb, err := block.ToProto() 84 if err != nil { 85 return err 86 } 87 88 if queued := p2p.TrySendEnvelopeShim(peer, p2p.Envelope{ //nolint: staticcheck 89 ChannelID: BlockchainChannel, 90 Message: &bcproto.BlockResponse{Block: bpb}, 91 }, sio.sw.Logger); !queued { 92 return fmt.Errorf("peer queue full") 93 } 94 95 return nil 96 } 97 98 func (sio *switchIO) sendBlockNotFound(height int64, peerID p2p.ID) error { 99 peer := sio.sw.Peers().Get(peerID) 100 if peer == nil { 101 return fmt.Errorf("peer not found") 102 } 103 if queued := p2p.TrySendEnvelopeShim(peer, p2p.Envelope{ //nolint: staticcheck 104 ChannelID: BlockchainChannel, 105 Message: &bcproto.NoBlockResponse{Height: height}, 106 }, sio.sw.Logger); !queued { 107 return fmt.Errorf("peer queue full") 108 } 109 110 return nil 111 } 112 113 func (sio *switchIO) trySwitchToConsensus(state state.State, skipWAL bool) bool { 114 conR, ok := sio.sw.Reactor("CONSENSUS").(consensusReactor) 115 if ok { 116 conR.SwitchToConsensus(state, skipWAL) 117 } 118 return ok 119 } 120 121 func (sio *switchIO) broadcastStatusRequest() { 122 // XXX: maybe we should use an io specific peer list here 123 sio.sw.BroadcastEnvelope(p2p.Envelope{ 124 ChannelID: BlockchainChannel, 125 Message: &bcproto.StatusRequest{}, 126 }) 127 }