2021-05-17 19:25:59 +00:00
|
|
|
package sync
|
|
|
|
|
|
|
|
import (
|
|
|
|
"github.com/libp2p/go-libp2p-core/network"
|
2021-09-03 16:00:56 +00:00
|
|
|
"github.com/pkg/errors"
|
2021-05-17 19:25:59 +00:00
|
|
|
"github.com/prysmaticlabs/prysm/beacon-chain/blockchain"
|
2021-09-03 16:00:56 +00:00
|
|
|
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
2021-05-17 19:25:59 +00:00
|
|
|
"github.com/prysmaticlabs/prysm/beacon-chain/p2p"
|
|
|
|
)
|
|
|
|
|
2021-09-03 16:00:56 +00:00
|
|
|
// Specifies the fixed size context length.
|
|
|
|
const forkDigestLength = 4
|
|
|
|
|
2021-05-17 19:25:59 +00:00
|
|
|
// writes peer's current context for the expected payload to the stream.
|
2021-09-03 16:00:56 +00:00
|
|
|
func writeContextToStream(objCtx []byte, stream network.Stream, chain blockchain.ChainInfoFetcher) error {
|
|
|
|
// The rpc context for our v2 methods is the fork-digest of
|
|
|
|
// the relevant payload. We write the associated fork-digest(context)
|
|
|
|
// into the stream for the payload.
|
2021-05-17 19:25:59 +00:00
|
|
|
rpcCtx, err := rpcContext(stream, chain)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
// Exit early if there is an empty context.
|
|
|
|
if len(rpcCtx) == 0 {
|
|
|
|
return nil
|
|
|
|
}
|
2021-09-03 16:00:56 +00:00
|
|
|
// Always choose the object's context when writing to the stream.
|
|
|
|
if objCtx != nil {
|
|
|
|
rpcCtx = objCtx
|
|
|
|
}
|
2021-05-17 19:25:59 +00:00
|
|
|
_, err = stream.Write(rpcCtx)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// reads any attached context-bytes to the payload.
|
|
|
|
func readContextFromStream(stream network.Stream, chain blockchain.ChainInfoFetcher) ([]byte, error) {
|
|
|
|
rpcCtx, err := rpcContext(stream, chain)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
if len(rpcCtx) == 0 {
|
|
|
|
return []byte{}, nil
|
|
|
|
}
|
|
|
|
// Read context (fork-digest) from stream
|
2021-09-03 16:00:56 +00:00
|
|
|
b := make([]byte, forkDigestLength)
|
2021-05-17 19:25:59 +00:00
|
|
|
if _, err := stream.Read(b); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return b, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// retrieve expected context depending on rpc topic schema version.
|
|
|
|
func rpcContext(stream network.Stream, chain blockchain.ChainInfoFetcher) ([]byte, error) {
|
|
|
|
_, _, version, err := p2p.TopicDeconstructor(string(stream.Protocol()))
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
switch version {
|
|
|
|
case p2p.SchemaVersionV1:
|
|
|
|
// Return empty context for a v1 method.
|
|
|
|
return []byte{}, nil
|
2021-09-03 16:00:56 +00:00
|
|
|
case p2p.SchemaVersionV2:
|
|
|
|
currFork := chain.CurrentFork()
|
|
|
|
genRoot := chain.GenesisValidatorRoot()
|
|
|
|
digest, err := helpers.ComputeForkDigest(currFork.CurrentVersion, genRoot[:])
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return digest[:], nil
|
2021-05-17 19:25:59 +00:00
|
|
|
default:
|
|
|
|
return nil, errors.New("invalid version of %s registered for topic: %s")
|
|
|
|
}
|
|
|
|
}
|