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

Hardforking example #1567

Draft
wants to merge 1 commit into
base: develop
Choose a base branch
from
Draft
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
10 changes: 9 additions & 1 deletion chain/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ const (
EIP150 = "EIP150"
EIP158 = "EIP158"
EIP155 = "EIP155"
MyFirstFork = "myfirstfork"
MySecondFork = "mysecondfork"
)

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

Expand Down Expand Up @@ -143,7 +147,9 @@ type ForksInTime struct {
London,
EIP150,
EIP158,
EIP155 bool
EIP155,
MyFirstFork,
MySecondFork bool
}

// AllForksEnabled should contain all supported forks by current edge version
Expand All @@ -157,4 +163,6 @@ var AllForksEnabled = &Forks{
Petersburg: NewFork(0),
Istanbul: NewFork(0),
London: NewFork(0),
MyFirstFork: NewFork(10),
MySecondFork: NewFork(20),
}
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 @@ -800,7 +800,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 @@ -932,7 +932,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 // MyFirstFork fork
Dummy2 string // MySecondFork 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 GetExtraHandler(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