Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions internal/chain/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,13 @@ func (e *engineImpl) VerifyShardState(
if len(headerShardStateBytes) == 0 {
return nil
}
// Only scheduled epoch-ending blocks may carry shard state.
// A non-last block with non-empty shard-state bytes would be accepted by
// SuperCommitteeForNextEpoch (which returns shard.State{} for non-last blocks),
// causing the chain to persist an empty next-epoch committee and halt consensus.
if bc.Config().IsShardStateValidation(header.Epoch()) && !shard.Schedule.IsLastBlock(header.Number().Uint64()) {
return errors.New("[VerifyShardState] non-epoch-ending block must not carry shard state")
}
shardState, err := bc.SuperCommitteeForNextEpoch(beacon, header, true)
if err != nil {
return err
Expand Down
11 changes: 11 additions & 0 deletions internal/params/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,7 @@ var (
EIP3860Epoch: EpochTBD,
PragueEpoch: EpochTBD,
EIP8024Epoch: EpochTBD,
ShardStateValidationEpoch: EpochTBD,
}

// AllProtocolChanges ...
Expand Down Expand Up @@ -453,6 +454,7 @@ var (
big.NewInt(0), // TimestampValidationEpoch
big.NewInt(0), // PragueEpoch
big.NewInt(0), // EIP8024Epoch
EpochTBD, // ShardStateValidationEpoch
}

// TestChainConfig ...
Expand Down Expand Up @@ -515,6 +517,7 @@ var (
big.NewInt(0), // TimestampValidationEpoch
big.NewInt(0), // PragueEpoch
big.NewInt(0), // EIP8024Epoch
EpochTBD, // ShardStateValidationEpoch
}

// TestRules ...
Expand Down Expand Up @@ -726,6 +729,9 @@ type ChainConfig struct {
PragueEpoch *big.Int `json:"prague-epoch,omitempty"`
// EIP8024Epoch is the first epoch to support EIP-8024 (DUPN, SWAPN, EXCHANGE opcodes)
EIP8024Epoch *big.Int `json:"eip8024-epoch,omitempty"`
// ShardStateValidationEpoch is the first epoch to enforce that only scheduled
// epoch-ending blocks may carry shard state bytes in their header
ShardStateValidationEpoch *big.Int `json:"shard-state-validation-epoch,omitempty"`
}

// String implements the fmt.Stringer interface.
Expand Down Expand Up @@ -1012,6 +1018,11 @@ func (c *ChainConfig) IsEIP8024(epoch *big.Int) bool {
return isForked(c.EIP8024Epoch, epoch)
}

// IsShardStateValidation returns true when non-epoch-ending blocks are rejected if they carry shard state bytes
func (c *ChainConfig) IsShardStateValidation(epoch *big.Int) bool {
return isForked(c.ShardStateValidationEpoch, epoch)
}

// IsChainIdFix returns whether epoch is either equal to the ChainId Fix fork epoch or greater.
func (c *ChainConfig) IsChainIdFix(epoch *big.Int) bool {
return isForked(c.ChainIdFixEpoch, epoch)
Expand Down