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  }