github.com/prysmaticlabs/prysm@v1.4.4/beacon-chain/sync/rpc_chunked_response.go (about)

     1  package sync
     2  
     3  import (
     4  	"errors"
     5  
     6  	libp2pcore "github.com/libp2p/go-libp2p-core"
     7  	"github.com/prysmaticlabs/prysm/beacon-chain/blockchain"
     8  	"github.com/prysmaticlabs/prysm/beacon-chain/p2p"
     9  	"github.com/prysmaticlabs/prysm/beacon-chain/p2p/encoder"
    10  	eth "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
    11  	"github.com/prysmaticlabs/prysm/proto/eth/v1alpha1/wrapper"
    12  	"github.com/prysmaticlabs/prysm/proto/interfaces"
    13  )
    14  
    15  // chunkWriter writes the given message as a chunked response to the given network
    16  // stream.
    17  // response_chunk  ::= <result> | <context-bytes> | <encoding-dependent-header> | <encoded-payload>
    18  func (s *Service) chunkWriter(stream libp2pcore.Stream, msg interface{}) error {
    19  	SetStreamWriteDeadline(stream, defaultWriteDuration)
    20  	return WriteChunk(stream, s.cfg.Chain, s.cfg.P2P.Encoding(), msg)
    21  }
    22  
    23  // WriteChunk object to stream.
    24  // response_chunk  ::= <result> | <context-bytes> | <encoding-dependent-header> | <encoded-payload>
    25  func WriteChunk(stream libp2pcore.Stream, chain blockchain.ChainInfoFetcher, encoding encoder.NetworkEncoding, msg interface{}) error {
    26  	if _, err := stream.Write([]byte{responseCodeSuccess}); err != nil {
    27  		return err
    28  	}
    29  	if err := writeContextToStream(stream, chain); err != nil {
    30  		return err
    31  	}
    32  	_, err := encoding.EncodeWithMaxLength(stream, msg)
    33  	return err
    34  }
    35  
    36  // ReadChunkedBlock handles each response chunk that is sent by the
    37  // peer and converts it into a beacon block.
    38  func ReadChunkedBlock(stream libp2pcore.Stream, chain blockchain.ChainInfoFetcher, p2p p2p.P2P, isFirstChunk bool) (interfaces.SignedBeaconBlock, error) {
    39  	// Handle deadlines differently for first chunk
    40  	if isFirstChunk {
    41  		return readFirstChunkedBlock(stream, chain, p2p)
    42  	}
    43  	blk := &eth.SignedBeaconBlock{}
    44  	if err := readResponseChunk(stream, chain, p2p, blk); err != nil {
    45  		return nil, err
    46  	}
    47  	return wrapper.WrappedPhase0SignedBeaconBlock(blk), nil
    48  }
    49  
    50  // readFirstChunkedBlock reads the first chunked block and applies the appropriate deadlines to
    51  // it.
    52  func readFirstChunkedBlock(stream libp2pcore.Stream, chain blockchain.ChainInfoFetcher, p2p p2p.P2P) (interfaces.SignedBeaconBlock, error) {
    53  	blk := &eth.SignedBeaconBlock{}
    54  	code, errMsg, err := ReadStatusCode(stream, p2p.Encoding())
    55  	if err != nil {
    56  		return nil, err
    57  	}
    58  	if code != 0 {
    59  		return nil, errors.New(errMsg)
    60  	}
    61  	// No-op for now with the rpc context.
    62  	_, err = readContextFromStream(stream, chain)
    63  	if err != nil {
    64  		return nil, err
    65  	}
    66  	err = p2p.Encoding().DecodeWithMaxLength(stream, blk)
    67  	return wrapper.WrappedPhase0SignedBeaconBlock(blk), err
    68  }
    69  
    70  // readResponseChunk reads the response from the stream and decodes it into the
    71  // provided message type.
    72  func readResponseChunk(stream libp2pcore.Stream, chain blockchain.ChainInfoFetcher, p2p p2p.P2P, to interface{}) error {
    73  	SetStreamReadDeadline(stream, respTimeout)
    74  	code, errMsg, err := readStatusCodeNoDeadline(stream, p2p.Encoding())
    75  	if err != nil {
    76  		return err
    77  	}
    78  	if code != 0 {
    79  		return errors.New(errMsg)
    80  	}
    81  	// No-op for now with the rpc context.
    82  	_, err = readContextFromStream(stream, chain)
    83  	if err != nil {
    84  		return err
    85  	}
    86  	return p2p.Encoding().DecodeWithMaxLength(stream, to)
    87  }