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