github.com/franono/tendermint@v0.32.2-0.20200527150959-749313264ce9/blockchain/v2/io.go (about)

     1  package v2
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/franono/tendermint/p2p"
     7  	"github.com/franono/tendermint/state"
     8  	"github.com/franono/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, skipWAL bool) bool
    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.State, skipWAL bool)
    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, skipWAL bool) bool {
   101  	conR, ok := sio.sw.Reactor("CONSENSUS").(consensusReactor)
   102  	if ok {
   103  		conR.SwitchToConsensus(state, skipWAL)
   104  	}
   105  	return ok
   106  }
   107  
   108  func (sio *switchIO) broadcastStatusRequest(base int64, height int64) {
   109  	if height == 0 && base > 0 {
   110  		base = 0
   111  	}
   112  	msgBytes := cdc.MustMarshalBinaryBare(&bcStatusRequestMessage{
   113  		Base:   base,
   114  		Height: height,
   115  	})
   116  	// XXX: maybe we should use an io specific peer list here
   117  	sio.sw.Broadcast(BlockchainChannel, msgBytes)
   118  }