-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Handle incoming chunks on the P2P layer
- Add hooks for the new topic "beacon_block_chunk" - Add protos for the new messages - Handle the sync package logic of signature validation - Create native types for the chunks to be handled in the sync package Still TODO: - Handle chunks for pending blocks. - Handle nodes with incoming chunks, avoid verifying signature twice - Decode the block and send it to the blockchain package
- Loading branch information
Showing
18 changed files
with
1,124 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
load("@prysm//tools/go:def.bzl", "go_library") | ||
|
||
go_library( | ||
name = "go_default_library", | ||
srcs = ["signature.go"], | ||
importpath = "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/chunks", | ||
visibility = ["//visibility:public"], | ||
deps = [ | ||
"//beacon-chain/core/signing:go_default_library", | ||
"//beacon-chain/state:go_default_library", | ||
"//config/params:go_default_library", | ||
"//consensus-types/interfaces:go_default_library", | ||
"//consensus-types/primitives:go_default_library", | ||
"//network/forks:go_default_library", | ||
"//time/slots:go_default_library", | ||
], | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package chunks | ||
|
||
import ( | ||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/signing" | ||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state" | ||
"github.com/prysmaticlabs/prysm/v5/config/params" | ||
"github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" | ||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives" | ||
"github.com/prysmaticlabs/prysm/v5/network/forks" | ||
"github.com/prysmaticlabs/prysm/v5/time/slots" | ||
) | ||
|
||
// VerifyChunkSignature verifies the proposer signature of a beacon block chunk. | ||
func VerifyChunkSignature(beaconState state.ReadOnlyBeaconState, | ||
proposerIndex primitives.ValidatorIndex, | ||
sig []byte, | ||
rootFunc func() ([32]byte, error)) error { | ||
currentEpoch := slots.ToEpoch(beaconState.Slot()) | ||
domain, err := signing.Domain(beaconState.Fork(), currentEpoch, params.BeaconConfig().DomainBeaconProposer, beaconState.GenesisValidatorsRoot()) | ||
if err != nil { | ||
return err | ||
} | ||
proposer, err := beaconState.ValidatorAtIndex(proposerIndex) | ||
if err != nil { | ||
return err | ||
} | ||
proposerPubKey := proposer.PublicKey | ||
return signing.VerifyBlockSigningRoot(proposerPubKey, sig, domain, rootFunc) | ||
} | ||
|
||
// VerifyChunkSignatureUsingCurrentFork verifies the proposer signature of a beacon block chunk. This differs | ||
// from the above method by not using fork data from the state and instead retrieving it | ||
// via the respective epoch. | ||
func VerifyChunkSignatureUsingCurrentFork(beaconState state.ReadOnlyBeaconState, chunk interfaces.ReadOnlyBeaconBlockChunk) error { | ||
currentEpoch := slots.ToEpoch(chunk.Slot()) | ||
fork, err := forks.Fork(currentEpoch) | ||
if err != nil { | ||
return err | ||
} | ||
domain, err := signing.Domain(fork, currentEpoch, params.BeaconConfig().DomainBeaconProposer, beaconState.GenesisValidatorsRoot()) | ||
if err != nil { | ||
return err | ||
} | ||
proposer, err := beaconState.ValidatorAtIndex(chunk.ProposerIndex()) | ||
if err != nil { | ||
return err | ||
} | ||
proposerPubKey := proposer.PublicKey | ||
sig := chunk.Signature() | ||
return signing.VerifyBlockSigningRoot(proposerPubKey, sig[:], domain, func() ([32]byte, error) { | ||
return chunk.HeaderRoot(), nil | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
package sync | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
pubsub "github.com/libp2p/go-libp2p-pubsub" | ||
"github.com/libp2p/go-libp2p/core/peer" | ||
"github.com/pkg/errors" | ||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/blockchain" | ||
core_chunks "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/chunks" | ||
"github.com/prysmaticlabs/prysm/v5/consensus-types/chunks" | ||
"github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces" | ||
"github.com/prysmaticlabs/prysm/v5/monitoring/tracing" | ||
"github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace" | ||
"github.com/prysmaticlabs/prysm/v5/time/slots" | ||
"github.com/sirupsen/logrus" | ||
"google.golang.org/protobuf/proto" | ||
) | ||
|
||
func (s *Service) beaconBlockChunkSubscriber(ctx context.Context, msg proto.Message) error { | ||
chunk, err := chunks.NewBlockChunk(msg) | ||
if err != nil { | ||
return err | ||
} | ||
if chunk.IsNil() { | ||
return chunks.ErrNilObject | ||
} | ||
// TODO: verify if we have the full block, decode and send it to the blockchain package. | ||
return nil | ||
} | ||
|
||
func (s *Service) validateBeaconBlockChunkPubSub(ctx context.Context, pid peer.ID, msg *pubsub.Message) (pubsub.ValidationResult, error) { | ||
if pid == s.cfg.p2p.PeerID() { | ||
return pubsub.ValidationAccept, nil | ||
} | ||
if s.cfg.initialSync.Syncing() { | ||
return pubsub.ValidationIgnore, nil | ||
} | ||
ctx, span := trace.StartSpan(ctx, "sync.validateBeaconBlockChunkPubSub") | ||
defer span.End() | ||
|
||
m, err := s.decodePubsubMessage(msg) | ||
if err != nil { | ||
tracing.AnnotateError(span, err) | ||
return pubsub.ValidationReject, errors.Wrap(err, "Could not decode message") | ||
} | ||
|
||
// It's fine to use the same lock for both block and chunk validation | ||
s.validateBlockLock.Lock() | ||
defer s.validateBlockLock.Unlock() | ||
|
||
chunk, ok := m.(interfaces.ReadOnlyBeaconBlockChunk) | ||
if !ok { | ||
return pubsub.ValidationReject, errors.New("msg is not ReadOnlyBeaconBlockChunk") | ||
} | ||
|
||
if chunk.IsNil() { | ||
return pubsub.ValidationReject, errors.New("chunk is nil") | ||
} | ||
|
||
// Check if parent is a bad block and then reject the chunk. | ||
if s.hasBadBlock(chunk.ParentRoot()) { | ||
err := fmt.Errorf("received chunk that has an invalid parent %#x", chunk.ParentRoot()) | ||
log.WithError(err).Debug("Received block with an invalid parent") | ||
return pubsub.ValidationReject, err | ||
} | ||
|
||
// Be lenient in handling early blocks. Instead of discarding blocks arriving later than | ||
// MAXIMUM_GOSSIP_CLOCK_DISPARITY in future, we tolerate blocks arriving at max two slots | ||
// earlier (SECONDS_PER_SLOT * 2 seconds). Queue such blocks and process them at the right slot. | ||
genesisTime := uint64(s.cfg.clock.GenesisTime().Unix()) | ||
if err := slots.VerifyTime(genesisTime, chunk.Slot(), earlyBlockProcessingTolerance); err != nil { | ||
log.WithError(err).Debug("Ignored chunk: could not verify slot time") | ||
return pubsub.ValidationIgnore, nil | ||
} | ||
|
||
cp := s.cfg.chain.FinalizedCheckpt() | ||
startSlot, err := slots.EpochStart(cp.Epoch) | ||
if err != nil { | ||
log.WithError(err).Debug("Ignored block: could not calculate epoch start slot") | ||
return pubsub.ValidationIgnore, nil | ||
} | ||
if startSlot >= chunk.Slot() { | ||
err := fmt.Errorf("finalized slot %d greater or equal to block slot %d", startSlot, chunk.Slot()) | ||
log.Debug(err) | ||
return pubsub.ValidationIgnore, err | ||
} | ||
|
||
if !s.cfg.chain.HasBlock(ctx, chunk.ParentRoot()) { | ||
// TODO: implement pending chunk storage | ||
return pubsub.ValidationIgnore, err | ||
} | ||
|
||
err = s.validateBeaconBlockChunk(ctx, chunk) | ||
if err != nil { | ||
log.WithError(err).Debug("Could not validate beacon block chunk") | ||
return pubsub.ValidationReject, err | ||
} | ||
|
||
logFields := logrus.Fields{ | ||
"chunkSlot": chunk.Slot(), | ||
"proposerIndex": chunk.ProposerIndex(), | ||
"parentRoot": chunk.ParentRoot(), | ||
} | ||
log.WithFields(logFields).Debug("Received block chunk") | ||
return pubsub.ValidationAccept, nil | ||
} | ||
|
||
func (s *Service) validateBeaconBlockChunk(ctx context.Context, chunk interfaces.ReadOnlyBeaconBlockChunk) error { | ||
if !s.cfg.chain.InForkchoice(chunk.ParentRoot()) { | ||
return blockchain.ErrNotDescendantOfFinalized | ||
} | ||
|
||
parentState, err := s.cfg.stateGen.StateByRoot(ctx, chunk.ParentRoot()) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
if err := core_chunks.VerifyChunkSignatureUsingCurrentFork(parentState, chunk); err != nil { | ||
return err | ||
} | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
### Added | ||
|
||
- Use random linear network coding for block propagation |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
load("@prysm//tools/go:def.bzl", "go_library") | ||
|
||
go_library( | ||
name = "go_default_library", | ||
srcs = [ | ||
"beacon_block_chunk.go", | ||
"error.go", | ||
], | ||
importpath = "github.com/prysmaticlabs/prysm/v5/consensus-types/chunks", | ||
visibility = ["//visibility:public"], | ||
deps = [ | ||
"//config/params:go_default_library", | ||
"//consensus-types/interfaces:go_default_library", | ||
"//consensus-types/primitives:go_default_library", | ||
"//proto/prysm/v1alpha1:go_default_library", | ||
"//runtime/version:go_default_library", | ||
"//time/slots:go_default_library", | ||
], | ||
) |
Oops, something went wrong.