Skip to content
This repository has been archived by the owner on Dec 4, 2024. It is now read-only.

Commit

Permalink
extra data fork poc
Browse files Browse the repository at this point in the history
  • Loading branch information
igorcrevar committed May 30, 2023
1 parent debb89e commit edb3052
Show file tree
Hide file tree
Showing 25 changed files with 403 additions and 161 deletions.
10 changes: 9 additions & 1 deletion chain/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ const (
EIP150 = "EIP150"
EIP158 = "EIP158"
EIP155 = "EIP155"
NoviSad = "novisad"
Nikaragva = "nikaragva"
)

// Forks is map which contains all forks and their starting blocks from genesis
Expand All @@ -112,6 +114,8 @@ func (f *Forks) At(block uint64) ForksInTime {
EIP150: f.IsActive(EIP150, block),
EIP158: f.IsActive(EIP158, block),
EIP155: f.IsActive(EIP155, block),
NoviSad: f.IsActive(NoviSad, block),
Nikaragva: f.IsActive(Nikaragva, block),
}
}

Expand Down Expand Up @@ -141,7 +145,9 @@ type ForksInTime struct {
London,
EIP150,
EIP158,
EIP155 bool
EIP155,
NoviSad,
Nikaragva bool
}

// AllForksEnabled should contain all supported forks by current edge version
Expand All @@ -156,6 +162,8 @@ var AllForksEnabled = &Forks{
Petersburg: NewFork(0),
Istanbul: NewFork(0),
London: NewFork(0),
NoviSad: NewFork(10),
Nikaragva: NewFork(20),
}

// CheckMissingFork checks if there is a fork received as a genesis parameter that is not supported
Expand Down
2 changes: 1 addition & 1 deletion consensus/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ type Consensus interface {
GetBridgeProvider() BridgeDataProvider

// FilterExtra filters extra data in header that is not a part of block hash
FilterExtra(extra []byte) ([]byte, error)
FilterExtra(*types.Header) ([]byte, error)

// Initialize initializes the consensus (e.g. setup data)
Initialize() error
Expand Down
4 changes: 2 additions & 2 deletions consensus/dev/dev.go
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,6 @@ func (d *Dev) GetBridgeProvider() consensus.BridgeDataProvider {
return nil
}

func (d *Dev) FilterExtra(extra []byte) ([]byte, error) {
return extra, nil
func (d *Dev) FilterExtra(header *types.Header) ([]byte, error) {
return header.ExtraData, nil
}
4 changes: 2 additions & 2 deletions consensus/dummy/dummy.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ func (d *Dummy) GetBridgeProvider() consensus.BridgeDataProvider {
return nil
}

func (d *Dummy) FilterExtra(extra []byte) ([]byte, error) {
return extra, nil
func (d *Dummy) FilterExtra(header *types.Header) ([]byte, error) {
return header.ExtraData, nil
}

func (d *Dummy) run() {
Expand Down
4 changes: 2 additions & 2 deletions consensus/ibft/ibft.go
Original file line number Diff line number Diff line change
Expand Up @@ -552,8 +552,8 @@ func (i *backendIBFT) GetBridgeProvider() consensus.BridgeDataProvider {
}

// FilterExtra is the implementation of Consensus interface
func (i *backendIBFT) FilterExtra(extra []byte) ([]byte, error) {
return extra, nil
func (i *backendIBFT) FilterExtra(header *types.Header) ([]byte, error) {
return header.ExtraData, nil
}

// updateCurrentModules updates Signer, Hooks, and Validators
Expand Down
6 changes: 3 additions & 3 deletions consensus/polybft/checkpoint_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ func (c *checkpointManager) submitCheckpoint(latestHeader *types.Header, isEndOf
return fmt.Errorf("block %d was not found", initialBlockNumber)
}

parentExtra, err = GetIbftExtra(parentHeader.ExtraData)
parentExtra, err = GetIbftExtra(parentHeader.ExtraData, parentHeader.Number)
if err != nil {
return err
}
Expand All @@ -155,7 +155,7 @@ func (c *checkpointManager) submitCheckpoint(latestHeader *types.Header, isEndOf
return fmt.Errorf("block %d was not found", blockNumber)
}

currentExtra, err = GetIbftExtra(currentHeader.ExtraData)
currentExtra, err = GetIbftExtra(currentHeader.ExtraData, currentHeader.Number)
if err != nil {
return err
}
Expand All @@ -182,7 +182,7 @@ func (c *checkpointManager) submitCheckpoint(latestHeader *types.Header, isEndOf
// (in case there were pending checkpoint blocks)
if currentExtra == nil {
// we need to send checkpoint for the latest block
currentExtra, err = GetIbftExtra(latestHeader.ExtraData)
currentExtra, err = GetIbftExtra(latestHeader.ExtraData, latestHeader.Number)
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion consensus/polybft/consensus_metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func updateBlockMetrics(currentBlock *types.Block, parentHeader *types.Header) e
// update the number of transactions in the block metric
metrics.SetGauge([]string{consensusMetricsPrefix, "num_txs"}, float32(len(currentBlock.Transactions)))

extra, err := GetIbftExtra(currentBlock.Header.ExtraData)
extra, err := GetIbftExtra(currentBlock.Header.ExtraData, currentBlock.Number())
if err != nil {
return err
}
Expand Down
8 changes: 4 additions & 4 deletions consensus/polybft/consensus_runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -520,7 +520,7 @@ func (c *consensusRuntime) calculateCommitEpochInput(
return nil
}

blockExtra, err := GetIbftExtra(currentBlock.ExtraData)
blockExtra, err := GetIbftExtra(currentBlock.ExtraData, currentBlock.Number)
if err != nil {
return nil, nil, err
}
Expand Down Expand Up @@ -694,7 +694,7 @@ func (c *consensusRuntime) IsValidProposalHash(proposal *proto.Proposal, hash []
return false
}

extra, err := GetIbftExtra(block.Header.ExtraData)
extra, err := GetIbftExtra(block.Header.ExtraData, block.Number())
if err != nil {
c.logger.Error("failed to retrieve extra", "block number", block.Number(), "error", err)

Expand Down Expand Up @@ -842,7 +842,7 @@ func (c *consensusRuntime) BuildPrePrepareMessage(
return nil
}

extra, err := GetIbftExtra(block.Header.ExtraData)
extra, err := GetIbftExtra(block.Header.ExtraData, block.Number())
if err != nil {
c.logger.Error("failed to retrieve extra for block %d: %w", block.Number(), err)

Expand Down Expand Up @@ -974,7 +974,7 @@ func (c *consensusRuntime) getFirstBlockOfEpoch(epochNumber uint64, latestHeader

blockHeader := latestHeader

blockExtra, err := GetIbftExtra(latestHeader.ExtraData)
blockExtra, err := GetIbftExtra(latestHeader.ExtraData, latestHeader.Number)
if err != nil {
return 0, err
}
Expand Down
145 changes: 37 additions & 108 deletions consensus/polybft/extra.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,122 +26,52 @@ var PolyBFTMixDigest = types.StringToHash("adce6e5230abe012342a44e4e9b6d05997d6f

// Extra defines the structure of the extra field for Istanbul
type Extra struct {
Validators *validator.ValidatorSetDelta
Parent *Signature
Committed *Signature
Checkpoint *CheckpointData
Validators *validator.ValidatorSetDelta
Parent *Signature
Committed *Signature
Checkpoint *CheckpointData
Dummy1 string // NoviSad fork
Dummy2 string // Nikaragva fork
BlockNumber uint64 // field used by forking manager
}

// MarshalRLPTo defines the marshal function wrapper for Extra
func (i *Extra) MarshalRLPTo(dst []byte) []byte {
func (e *Extra) MarshalRLPTo(dst []byte) []byte {
ar := &fastrlp.Arena{}

return append(make([]byte, ExtraVanity), i.MarshalRLPWith(ar).MarshalTo(dst)...)
return append(make([]byte, ExtraVanity), e.MarshalRLPWith(ar).MarshalTo(dst)...)
}

// MarshalRLPWith defines the marshal function implementation for Extra
func (i *Extra) MarshalRLPWith(ar *fastrlp.Arena) *fastrlp.Value {
vv := ar.NewArray()

// Validators
if i.Validators == nil {
vv.Set(ar.NewNullArray())
} else {
vv.Set(i.Validators.MarshalRLPWith(ar))
}

// Parent Signatures
if i.Parent == nil {
vv.Set(ar.NewNullArray())
} else {
vv.Set(i.Parent.MarshalRLPWith(ar))
}

// Committed Signatures
if i.Committed == nil {
vv.Set(ar.NewNullArray())
} else {
vv.Set(i.Committed.MarshalRLPWith(ar))
}

// Checkpoint
if i.Checkpoint == nil {
vv.Set(ar.NewNullArray())
} else {
vv.Set(i.Checkpoint.MarshalRLPWith(ar))
}

return vv
func (e *Extra) MarshalRLPWith(ar *fastrlp.Arena) *fastrlp.Value {
return GetExtraHandler(e.BlockNumber).MarshalRLPWith(e, ar)
}

// UnmarshalRLP defines the unmarshal function wrapper for Extra
func (i *Extra) UnmarshalRLP(input []byte) error {
return fastrlp.UnmarshalRLP(input[ExtraVanity:], i)
func (e *Extra) UnmarshalRLP(input []byte) error {
return fastrlp.UnmarshalRLP(input[ExtraVanity:], e)
}

// UnmarshalRLPWith defines the unmarshal implementation for Extra
func (i *Extra) UnmarshalRLPWith(v *fastrlp.Value) error {
const expectedElements = 4

elems, err := v.GetElems()
if err != nil {
return err
}

if num := len(elems); num != expectedElements {
return fmt.Errorf("incorrect elements count to decode Extra, expected %d but found %d", expectedElements, num)
}

// Validators
if elems[0].Elems() > 0 {
i.Validators = &validator.ValidatorSetDelta{}
if err := i.Validators.UnmarshalRLPWith(elems[0]); err != nil {
return err
}
}

// Parent Signatures
if elems[1].Elems() > 0 {
i.Parent = &Signature{}
if err := i.Parent.UnmarshalRLPWith(elems[1]); err != nil {
return err
}
}

// Committed Signatures
if elems[2].Elems() > 0 {
i.Committed = &Signature{}
if err := i.Committed.UnmarshalRLPWith(elems[2]); err != nil {
return err
}
}

// Checkpoint
if elems[3].Elems() > 0 {
i.Checkpoint = &CheckpointData{}
if err := i.Checkpoint.UnmarshalRLPWith(elems[3]); err != nil {
return err
}
}

return nil
func (e *Extra) UnmarshalRLPWith(v *fastrlp.Value) error {
return GetExtraHandler(e.BlockNumber).UnmarshalRLPWith(e, v)
}

// ValidateFinalizedData contains extra data validations for finalized headers
func (i *Extra) ValidateFinalizedData(header *types.Header, parent *types.Header, parents []*types.Header,
func (e *Extra) ValidateFinalizedData(header *types.Header, parent *types.Header, parents []*types.Header,
chainID uint64, consensusBackend polybftBackend, domain []byte, logger hclog.Logger) error {
// validate committed signatures
blockNumber := header.Number
if i.Committed == nil {
if e.Committed == nil {
return fmt.Errorf("failed to verify signatures for block %d, because signatures are not present", blockNumber)
}

if i.Checkpoint == nil {
if e.Checkpoint == nil {
return fmt.Errorf("failed to verify signatures for block %d, because checkpoint data are not present", blockNumber)
}

// validate current block signatures
checkpointHash, err := i.Checkpoint.Hash(chainID, header.Number, header.Hash)
checkpointHash, err := e.Checkpoint.Hash(chainID, header.Number, header.Hash)
if err != nil {
return fmt.Errorf("failed to calculate proposal hash: %w", err)
}
Expand All @@ -151,34 +81,34 @@ func (i *Extra) ValidateFinalizedData(header *types.Header, parent *types.Header
return fmt.Errorf("failed to validate header for block %d. could not retrieve block validators:%w", blockNumber, err)
}

if err := i.Committed.Verify(validators, checkpointHash, domain, logger); err != nil {
if err := e.Committed.Verify(validators, checkpointHash, domain, logger); err != nil {
return fmt.Errorf("failed to verify signatures for block %d (proposal hash %s): %w",
blockNumber, checkpointHash, err)
}

parentExtra, err := GetIbftExtra(parent.ExtraData)
parentExtra, err := GetIbftExtra(parent.ExtraData, parent.Number)
if err != nil {
return fmt.Errorf("failed to verify signatures for block %d: %w", blockNumber, err)
}

// validate parent signatures
if err := i.ValidateParentSignatures(blockNumber, consensusBackend, parents,
if err := e.ValidateParentSignatures(blockNumber, consensusBackend, parents,
parent, parentExtra, chainID, domain, logger); err != nil {
return err
}

return i.Checkpoint.ValidateBasic(parentExtra.Checkpoint)
return e.Checkpoint.ValidateBasic(parentExtra.Checkpoint)
}

// ValidateParentSignatures validates signatures for parent block
func (i *Extra) ValidateParentSignatures(blockNumber uint64, consensusBackend polybftBackend, parents []*types.Header,
func (e *Extra) ValidateParentSignatures(blockNumber uint64, consensusBackend polybftBackend, parents []*types.Header,
parent *types.Header, parentExtra *Extra, chainID uint64, domain []byte, logger hclog.Logger) error {
// skip block 1 because genesis does not have committed signatures
if blockNumber <= 1 {
return nil
}

if i.Parent == nil {
if e.Parent == nil {
return fmt.Errorf("failed to verify signatures for parent of block %d because signatures are not present",
blockNumber)
}
Expand All @@ -197,14 +127,18 @@ func (i *Extra) ValidateParentSignatures(blockNumber uint64, consensusBackend po
return fmt.Errorf("failed to calculate parent proposal hash: %w", err)
}

if err := i.Parent.Verify(parentValidators, parentCheckpointHash, domain, logger); err != nil {
if err := e.Parent.Verify(parentValidators, parentCheckpointHash, domain, logger); err != nil {
return fmt.Errorf("failed to verify signatures for parent of block %d (proposal hash: %s): %w",
blockNumber, parentCheckpointHash, err)
}

return nil
}

func (e *Extra) ValidateAdditional(header *types.Header) error {
return GetExtraHandler(e.BlockNumber).ValidateAdditional(e, header)
}

// Signature represents aggregated signatures of signers accompanied with a bitmap
// (in order to be able to determine identities of each signer)
type Signature struct {
Expand Down Expand Up @@ -464,29 +398,24 @@ func (c *CheckpointData) Validate(parentCheckpoint *CheckpointData,

// GetIbftExtraClean returns unmarshaled extra field from the passed in header,
// but without signatures for the given header (it only includes signatures for the parent block)
func GetIbftExtraClean(extraRaw []byte) ([]byte, error) {
extra, err := GetIbftExtra(extraRaw)
func GetIbftExtraClean(extraRaw []byte, blockNumber uint64) ([]byte, error) {
extra, err := GetIbftExtra(extraRaw, blockNumber)
if err != nil {
return nil, err
}

ibftExtra := &Extra{
Parent: extra.Parent,
Validators: extra.Validators,
Checkpoint: extra.Checkpoint,
Committed: &Signature{},
}

return ibftExtra.MarshalRLPTo(nil), nil
return GetExtraAddHandler(blockNumber).GetIbftExtraClean(extra).MarshalRLPTo(nil), nil
}

// GetIbftExtra returns the istanbul extra data field from the passed in header
func GetIbftExtra(extraRaw []byte) (*Extra, error) {
func GetIbftExtra(extraRaw []byte, blockNumber uint64) (*Extra, error) {
if len(extraRaw) < ExtraVanity {
return nil, fmt.Errorf("wrong extra size: %d", len(extraRaw))
}

extra := &Extra{}
extra := &Extra{
BlockNumber: blockNumber,
}

if err := extra.UnmarshalRLP(extraRaw); err != nil {
return nil, err
Expand Down
Loading

0 comments on commit edb3052

Please sign in to comment.