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 := ð.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 := ð.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 }