github.com/number571/tendermint@v0.34.11-gost/internal/blockchain/v2/io.go (about) 1 package v2 2 3 import ( 4 "errors" 5 6 "github.com/number571/tendermint/internal/p2p" 7 bcproto "github.com/number571/tendermint/proto/tendermint/blockchain" 8 "github.com/number571/tendermint/state" 9 "github.com/number571/tendermint/types" 10 "github.com/gogo/protobuf/proto" 11 ) 12 13 var ( 14 errPeerQueueFull = errors.New("peer queue full") 15 ) 16 17 type iIO interface { 18 sendBlockRequest(peer p2p.Peer, height int64) error 19 sendBlockToPeer(block *types.Block, peer p2p.Peer) error 20 sendBlockNotFound(height int64, peer p2p.Peer) error 21 sendStatusResponse(base, height int64, peer p2p.Peer) error 22 23 sendStatusRequest(peer p2p.Peer) error 24 broadcastStatusRequest() error 25 26 trySwitchToConsensus(state state.State, skipWAL bool) bool 27 } 28 29 type switchIO struct { 30 sw *p2p.Switch 31 } 32 33 func newSwitchIo(sw *p2p.Switch) *switchIO { 34 return &switchIO{ 35 sw: sw, 36 } 37 } 38 39 const ( 40 // BlockchainChannel is a channel for blocks and status updates (`BlockStore` height) 41 BlockchainChannel = byte(0x40) 42 ) 43 44 type consensusReactor interface { 45 // for when we switch from blockchain reactor and fast sync to 46 // the consensus machine 47 SwitchToConsensus(state state.State, skipWAL bool) 48 } 49 50 func (sio *switchIO) sendBlockRequest(peer p2p.Peer, height int64) error { 51 msgProto := &bcproto.Message{ 52 Sum: &bcproto.Message_BlockRequest{ 53 BlockRequest: &bcproto.BlockRequest{ 54 Height: height, 55 }, 56 }, 57 } 58 59 msgBytes, err := proto.Marshal(msgProto) 60 if err != nil { 61 return err 62 } 63 64 queued := peer.TrySend(BlockchainChannel, msgBytes) 65 if !queued { 66 return errPeerQueueFull 67 } 68 return nil 69 } 70 71 func (sio *switchIO) sendStatusResponse(base int64, height int64, peer p2p.Peer) error { 72 msgProto := &bcproto.Message{ 73 Sum: &bcproto.Message_StatusResponse{ 74 StatusResponse: &bcproto.StatusResponse{ 75 Height: height, 76 Base: base, 77 }, 78 }, 79 } 80 81 msgBytes, err := proto.Marshal(msgProto) 82 if err != nil { 83 return err 84 } 85 86 if queued := peer.TrySend(BlockchainChannel, msgBytes); !queued { 87 return errPeerQueueFull 88 } 89 90 return nil 91 } 92 93 func (sio *switchIO) sendBlockToPeer(block *types.Block, peer p2p.Peer) error { 94 if block == nil { 95 panic("trying to send nil block") 96 } 97 98 bpb, err := block.ToProto() 99 if err != nil { 100 return err 101 } 102 103 msgProto := &bcproto.Message{ 104 Sum: &bcproto.Message_BlockResponse{ 105 BlockResponse: &bcproto.BlockResponse{ 106 Block: bpb, 107 }, 108 }, 109 } 110 111 msgBytes, err := proto.Marshal(msgProto) 112 if err != nil { 113 return err 114 } 115 116 if queued := peer.TrySend(BlockchainChannel, msgBytes); !queued { 117 return errPeerQueueFull 118 } 119 120 return nil 121 } 122 123 func (sio *switchIO) sendBlockNotFound(height int64, peer p2p.Peer) error { 124 msgProto := &bcproto.Message{ 125 Sum: &bcproto.Message_NoBlockResponse{ 126 NoBlockResponse: &bcproto.NoBlockResponse{ 127 Height: height, 128 }, 129 }, 130 } 131 132 msgBytes, err := proto.Marshal(msgProto) 133 if err != nil { 134 return err 135 } 136 137 if queued := peer.TrySend(BlockchainChannel, msgBytes); !queued { 138 return errPeerQueueFull 139 } 140 141 return nil 142 } 143 144 func (sio *switchIO) trySwitchToConsensus(state state.State, skipWAL bool) bool { 145 conR, ok := sio.sw.Reactor("CONSENSUS").(consensusReactor) 146 if ok { 147 conR.SwitchToConsensus(state, skipWAL) 148 } 149 return ok 150 } 151 152 func (sio *switchIO) sendStatusRequest(peer p2p.Peer) error { 153 msgProto := &bcproto.Message{ 154 Sum: &bcproto.Message_StatusRequest{ 155 StatusRequest: &bcproto.StatusRequest{}, 156 }, 157 } 158 159 msgBytes, err := proto.Marshal(msgProto) 160 if err != nil { 161 return err 162 } 163 164 if queued := peer.TrySend(BlockchainChannel, msgBytes); !queued { 165 return errPeerQueueFull 166 } 167 168 return nil 169 } 170 171 func (sio *switchIO) broadcastStatusRequest() error { 172 msgProto := &bcproto.Message{ 173 Sum: &bcproto.Message_StatusRequest{ 174 StatusRequest: &bcproto.StatusRequest{}, 175 }, 176 } 177 178 msgBytes, err := proto.Marshal(msgProto) 179 if err != nil { 180 return err 181 } 182 183 // XXX: maybe we should use an io specific peer list here 184 sio.sw.Broadcast(BlockchainChannel, msgBytes) 185 186 return nil 187 }