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