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  }