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  }