github.com/vipernet-xyz/tm@v0.34.24/blockchain/v2/io.go (about)

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