Skip to content

Commit

Permalink
Merge branch 'master' into rf-action
Browse files Browse the repository at this point in the history
  • Loading branch information
envestcc authored Sep 30, 2024
2 parents 351a8a1 + 3c2aa0d commit df51d33
Show file tree
Hide file tree
Showing 15 changed files with 173 additions and 67 deletions.
2 changes: 2 additions & 0 deletions action/action.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ type (
amountForCost interface{ Amount() *big.Int }

gasLimitForCost interface{ GasLimitForCost() }

validateSidecar interface{ ValidateSidecar() error }
)

// Sign signs the action using sender's private key
Expand Down
4 changes: 4 additions & 0 deletions action/blob_data.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,10 @@ func (tx *BlobTxData) SanityCheck() error {
if price := tx.blobFeeCap; price != nil && price.Sign() < 0 {
return errors.Wrap(ErrNegativeValue, "negative blob fee cap")
}
return nil
}

func (tx *BlobTxData) ValidateSidecar() error {
var (
size = len(tx.blobHashes)
sidecar = tx.sidecar
Expand Down
26 changes: 15 additions & 11 deletions action/blob_data_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,44 +76,48 @@ func TestBlobTxData(t *testing.T) {
decodeBlob := MustNoErrorV(fromProtoBlobTxData(&recv))
r.Equal(blobData, decodeBlob)
})
t.Run("Sanity", func(t *testing.T) {
t.Run("SanityCheck/ValidateSidecar", func(t *testing.T) {
r.NoError(blobData.SanityCheck())
blobData.blobFeeCap = uint256.NewInt(1)
blobData.blobFeeCap.Lsh(blobData.blobFeeCap, 255)
r.ErrorIs(blobData.SanityCheck(), ErrNegativeValue)
r.NoError(blobData.ValidateSidecar())
// check blob hashes size
h := blobData.blobHashes
blobData.blobHashes = blobData.blobHashes[:0]
r.ErrorContains(blobData.SanityCheck(), "blobless blob transaction")
r.ErrorContains(blobData.ValidateSidecar(), "blobless blob transaction")
blobData.blobHashes = h
// check Blobs, Commitments, Proofs size
sidecar := blobData.sidecar
sidecar.Blobs = append(sidecar.Blobs, kzg4844.Blob{})
r.ErrorContains(blobData.SanityCheck(), "number of blobs and hashes mismatch")
r.ErrorContains(blobData.ValidateSidecar(), "number of blobs and hashes mismatch")
sidecar.Blobs = sidecar.Blobs[:1]
sidecar.Commitments = append(sidecar.Commitments, kzg4844.Commitment{})
r.ErrorContains(blobData.SanityCheck(), "number of blobs and commitments mismatch")
r.ErrorContains(blobData.ValidateSidecar(), "number of blobs and commitments mismatch")
sidecar.Commitments = sidecar.Commitments[:1]
sidecar.Proofs = append(sidecar.Proofs, kzg4844.Proof{})
r.ErrorContains(blobData.SanityCheck(), "number of blobs and proofs mismatch")
r.ErrorContains(blobData.ValidateSidecar(), "number of blobs and proofs mismatch")
sidecar.Proofs = sidecar.Proofs[:1]
r.NoError(blobData.SanityCheck())
r.NoError(blobData.ValidateSidecar())
// verify commitments hash
b := sidecar.Commitments[0][3]
sidecar.Commitments[0][3] = b + 1
r.ErrorContains(blobData.SanityCheck(), "blob 0: computed hash 01fca1582898b9c172b690c0ea344713bb28199208d3553b5ed56f33e0f34034 mismatches transaction one")
r.ErrorContains(blobData.ValidateSidecar(), "blob 0: computed hash 01fca1582898b9c172b690c0ea344713bb28199208d3553b5ed56f33e0f34034 mismatches transaction one")
sidecar.Commitments[0][3] = b
// verify blobs via KZG
b = sidecar.Blobs[0][31]
sidecar.Blobs[0][31] = b + 1
r.ErrorContains(blobData.SanityCheck(), "invalid blob 0: can't verify opening proof")
r.ErrorContains(blobData.ValidateSidecar(), "invalid blob 0: can't verify opening proof")
sidecar.Blobs[0][31] = b
b = sidecar.Proofs[0][42]
sidecar.Proofs[0][42] = b + 1
r.ErrorContains(blobData.SanityCheck(), "invalid blob 0: invalid compressed coordinate: square root doesn't exist")
r.ErrorContains(blobData.ValidateSidecar(), "invalid blob 0: invalid compressed coordinate: square root doesn't exist")
sidecar.Proofs[0][42] = b
b = sidecar.Proofs[0][47]
sidecar.Proofs[0][47] = b + 1
r.ErrorContains(blobData.SanityCheck(), "invalid blob 0: invalid point: subgroup check failed")
r.ErrorContains(blobData.ValidateSidecar(), "invalid blob 0: invalid point: subgroup check failed")
sidecar.Proofs[0][47] = b
r.NoError(blobData.SanityCheck())
r.NoError(blobData.ValidateSidecar())
})
}

Expand Down
8 changes: 8 additions & 0 deletions action/envelope.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ type (
SetGas(uint64)
SetChainID(uint32)
SanityCheck() error
ValidateSidecar() error
}

// TxData is the interface required to execute a transaction by EVM
Expand Down Expand Up @@ -442,3 +443,10 @@ func (elp *envelope) SanityCheck() error {
}
return elp.common.SanityCheck()
}

func (elp *envelope) ValidateSidecar() error {
if vsc, ok := elp.common.(validateSidecar); ok {
return vsc.ValidateSidecar()
}
return nil
}
2 changes: 2 additions & 0 deletions action/protocol/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ type (
BaseFee *big.Int
// ExcessBlobGas is the excess blob gas of the block
ExcessBlobGas uint64
// SkipSidecarValidation dictates to validate sidecar (for blob tx) or not
SkipSidecarValidation bool
}

// ActionCtx provides action auxiliary information.
Expand Down
3 changes: 3 additions & 0 deletions action/protocol/execution/protocol.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,9 @@ func (p *Protocol) Validate(ctx context.Context, elp action.Envelope, _ protocol
if dataSize > sizeLimit {
return action.ErrOversizedData
}
if len(elp.BlobHashes()) > 0 && elp.To() == nil {
return errors.New("cannot create contract in blob tx")
}
return nil
}

Expand Down
6 changes: 6 additions & 0 deletions action/protocol/generic_validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,12 @@ func (v *GenericValidator) Validate(ctx context.Context, selp *action.SealedEnve
if selp.BlobGasFeeCap().Cmp(basefee) < 0 {
return errors.Wrapf(action.ErrUnderpriced, "blob fee cap is too low: %s, base fee: %s", selp.BlobGasFeeCap().String(), basefee.String())
}
// validate sidecar
if blkCtx, ok := GetBlockCtx(ctx); (ok && !blkCtx.SkipSidecarValidation) || selp.BlobTxSidecar() != nil {
if err := selp.ValidateSidecar(); err != nil {
return errors.Wrap(err, "failed to validate blob sidecar")
}
}
}
}
return nil
Expand Down
4 changes: 4 additions & 0 deletions action/tx_blob.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import (
"github.com/pkg/errors"
)

var _ validateSidecar = (*BlobTx)(nil)

// BlobTx represents EIP-4844 blob transaction
type BlobTx struct {
chainID uint32
Expand Down Expand Up @@ -131,6 +133,8 @@ func (tx *BlobTx) SanityCheck() error {
return tx.blob.SanityCheck()
}

func (tx *BlobTx) ValidateSidecar() error { return tx.blob.ValidateSidecar() }

func (tx *BlobTx) toProto() *iotextypes.ActionCore {
actCore := iotextypes.ActionCore{
Version: BlobTxType,
Expand Down
2 changes: 1 addition & 1 deletion api/web3server.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ func (svr *web3Handler) handleWeb3Req(ctx context.Context, web3Req *gjson.Result
res, err = svr.ethAccounts()
case "eth_gasPrice":
res, err = svr.gasPrice()
case "eth_maxPriorityFee":
case "eth_maxPriorityFeePerGas":
res, err = svr.maxPriorityFee()
case "eth_getBlockByHash":
res, err = svr.getBlockByHash(web3Req)
Expand Down
2 changes: 1 addition & 1 deletion api/web3server_integrity_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ func gasPrice(t *testing.T, handler *hTTPHandler) {

func maxPriorityFee(t *testing.T, handler *hTTPHandler) {
require := require.New(t)
result := serveTestHTTP(require, handler, "eth_maxPriorityFee", "[]")
result := serveTestHTTP(require, handler, "eth_maxPriorityFeePerGas", "[]")
actual, ok := result.(string)
require.True(ok)
require.Equal(uint64ToHex(1000000000000), actual)
Expand Down
36 changes: 27 additions & 9 deletions blockchain/blockchain.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ type (
// CommitBlock validates and appends a block to the chain
CommitBlock(blk *block.Block) error
// ValidateBlock validates a new block before adding it to the blockchain
ValidateBlock(blk *block.Block) error
ValidateBlock(*block.Block, ...BlockValidationOption) error

// AddSubscriber make you listen to every single produced block
AddSubscriber(BlockCreationSubscriber) error
Expand Down Expand Up @@ -160,6 +160,20 @@ func ClockOption(clk clock.Clock) Option {
}
}

type (
BlockValidationCfg struct {
skipSidecarValidation bool
}

BlockValidationOption func(*BlockValidationCfg)
)

func SkipSidecarValidationOption() BlockValidationOption {
return func(opts *BlockValidationCfg) {
opts.skipSidecarValidation = true
}
}

// NewBlockchain creates a new blockchain and DB instance
func NewBlockchain(cfg Config, g genesis.Genesis, dao blockdao.BlockDAO, bbf BlockBuilderFactory, opts ...Option) Blockchain {
// create the Blockchain
Expand Down Expand Up @@ -258,7 +272,7 @@ func (bc *blockchain) TipHeight() uint64 {
}

// ValidateBlock validates a new block before adding it to the blockchain
func (bc *blockchain) ValidateBlock(blk *block.Block) error {
func (bc *blockchain) ValidateBlock(blk *block.Block, opts ...BlockValidationOption) error {
bc.mu.RLock()
defer bc.mu.RUnlock()
timer := bc.timerFactory.NewTimer("ValidateBlock")
Expand Down Expand Up @@ -311,21 +325,25 @@ func (bc *blockchain) ValidateBlock(blk *block.Block) error {
if err != nil {
return err
}
cfg := BlockValidationCfg{}
for _, opt := range opts {
opt(&cfg)
}
ctx = protocol.WithBlockCtx(ctx,
protocol.BlockCtx{
BlockHeight: blk.Height(),
BlockTimeStamp: blk.Timestamp(),
GasLimit: bc.genesis.BlockGasLimitByHeight(blk.Height()),
Producer: producerAddr,
BaseFee: blk.BaseFee(),
ExcessBlobGas: blk.ExcessBlobGas(),
BlockHeight: blk.Height(),
BlockTimeStamp: blk.Timestamp(),
GasLimit: bc.genesis.BlockGasLimitByHeight(blk.Height()),
Producer: producerAddr,
BaseFee: blk.BaseFee(),
ExcessBlobGas: blk.ExcessBlobGas(),
SkipSidecarValidation: cfg.skipSidecarValidation,
},
)
ctx = protocol.WithFeatureCtx(ctx)
if bc.blockValidator == nil {
return nil
}

return bc.blockValidator.Validate(ctx, blk)
}

Expand Down
77 changes: 40 additions & 37 deletions blockchain/genesis/genesis.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,43 +43,44 @@ func init() {
func defaultConfig() Genesis {
return Genesis{
Blockchain: Blockchain{
Timestamp: 1546329600,
BlockGasLimit: 20000000,
TsunamiBlockGasLimit: 50000000,
ActionGasLimit: 5000000,
BlockInterval: 10 * time.Second,
NumSubEpochs: 2,
DardanellesNumSubEpochs: 30,
NumDelegates: 24,
NumCandidateDelegates: 36,
TimeBasedRotation: false,
MaxBlobsPerBlock: 6,
PacificBlockHeight: 432001,
AleutianBlockHeight: 864001,
BeringBlockHeight: 1512001,
CookBlockHeight: 1641601,
DardanellesBlockHeight: 1816201,
DaytonaBlockHeight: 3238921,
EasterBlockHeight: 4478761,
FbkMigrationBlockHeight: 5157001,
FairbankBlockHeight: 5165641,
GreenlandBlockHeight: 6544441,
HawaiiBlockHeight: 11267641,
IcelandBlockHeight: 12289321,
JutlandBlockHeight: 13685401,
KamchatkaBlockHeight: 13816441,
LordHoweBlockHeight: 13979161,
MidwayBlockHeight: 16509241,
NewfoundlandBlockHeight: 17662681,
OkhotskBlockHeight: 21542761,
PalauBlockHeight: 22991401,
QuebecBlockHeight: 24838201,
RedseaBlockHeight: 26704441,
SumatraBlockHeight: 28516681,
TsunamiBlockHeight: 29275561,
UpernavikBlockHeight: 31174201,
VanuatuBlockHeight: 41174201,
ToBeEnabledBlockHeight: math.MaxUint64,
Timestamp: 1546329600,
BlockGasLimit: 20000000,
TsunamiBlockGasLimit: 50000000,
ActionGasLimit: 5000000,
BlockInterval: 10 * time.Second,
NumSubEpochs: 2,
DardanellesNumSubEpochs: 30,
NumDelegates: 24,
NumCandidateDelegates: 36,
TimeBasedRotation: false,
MaxBlobsPerBlock: 6,
MinBlocksForBlobRetention: 345600,
PacificBlockHeight: 432001,
AleutianBlockHeight: 864001,
BeringBlockHeight: 1512001,
CookBlockHeight: 1641601,
DardanellesBlockHeight: 1816201,
DaytonaBlockHeight: 3238921,
EasterBlockHeight: 4478761,
FbkMigrationBlockHeight: 5157001,
FairbankBlockHeight: 5165641,
GreenlandBlockHeight: 6544441,
HawaiiBlockHeight: 11267641,
IcelandBlockHeight: 12289321,
JutlandBlockHeight: 13685401,
KamchatkaBlockHeight: 13816441,
LordHoweBlockHeight: 13979161,
MidwayBlockHeight: 16509241,
NewfoundlandBlockHeight: 17662681,
OkhotskBlockHeight: 21542761,
PalauBlockHeight: 22991401,
QuebecBlockHeight: 24838201,
RedseaBlockHeight: 26704441,
SumatraBlockHeight: 28516681,
TsunamiBlockHeight: 29275561,
UpernavikBlockHeight: 31174201,
VanuatuBlockHeight: 41174201,
ToBeEnabledBlockHeight: math.MaxUint64,
},
Account: Account{
InitBalanceMap: make(map[string]string),
Expand Down Expand Up @@ -186,6 +187,8 @@ type (
TimeBasedRotation bool `yaml:"timeBasedRotation"`
// MaxBlobsPerBlock is the maximum number of blobs per block
MaxBlobsPerBlock uint64 `yaml:"maxBlobsPerBlock"`
// MinBlocksForBlobRetention is the minimum number of blocks for blob retention
MinBlocksForBlobRetention uint64 `yaml:"minBlocksForBlobRetention"`
// PacificBlockHeight is the start height of using the logic of Pacific version
// TODO: PacificBlockHeight is not added into protobuf definition for backward compatibility
PacificBlockHeight uint64 `yaml:"pacificHeight"`
Expand Down
27 changes: 23 additions & 4 deletions chainservice/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,20 @@ func (builder *Builder) buildBlockSyncer() error {
chain := builder.cs.chain
consens := builder.cs.consensus
blockdao := builder.cs.blockdao
cfg := builder.cfg
// estimateTipHeight estimates the height of the block at the given time
// it ignores the influence of the block missing in the blockchain
// it must >= the real head height of the block
estimateTipHeight := func(blk *block.Block, duration time.Duration) uint64 {
if blk.Height() >= cfg.Genesis.DardanellesBlockHeight {
return blk.Height() + uint64(duration.Seconds()/float64(cfg.DardanellesUpgrade.BlockInterval))
}
durationToDardanelles := time.Duration(cfg.Genesis.DardanellesBlockHeight-blk.Height()) * time.Duration(cfg.Genesis.BlockInterval)
if duration < durationToDardanelles {
return blk.Height() + uint64(duration.Seconds()/float64(cfg.Genesis.BlockInterval))
}
return cfg.Genesis.DardanellesBlockHeight + uint64((duration-durationToDardanelles).Seconds()/float64(cfg.DardanellesUpgrade.BlockInterval))
}

blocksync, err := blocksync.NewBlockSyncer(
builder.cfg.BlockSync,
Expand Down Expand Up @@ -570,8 +584,13 @@ func (builder *Builder) buildBlockSyncer() error {
retries = 4
}
var err error
opts := []blockchain.BlockValidationOption{}
if now := time.Now(); now.After(blk.Timestamp()) &&
blk.Height()+cfg.Genesis.MinBlocksForBlobRetention <= estimateTipHeight(blk, now.Sub(blk.Timestamp())) {
opts = append(opts, blockchain.SkipSidecarValidationOption())
}
for i := 0; i < retries; i++ {
if err = chain.ValidateBlock(blk); err == nil {
if err = chain.ValidateBlock(blk, opts...); err == nil {
if err = chain.CommitBlock(blk); err == nil {
break
}
Expand Down Expand Up @@ -831,13 +850,13 @@ func (builder *Builder) build(forSubChain, forTest bool) (*ChainService, error)
if err := builder.buildConsensusComponent(); err != nil {
return nil, err
}
if err := builder.buildBlockSyncer(); err != nil {
if err := builder.buildNodeInfoManager(); err != nil {
return nil, err
}
if err := builder.buildActionSyncer(); err != nil {
if err := builder.buildBlockSyncer(); err != nil {
return nil, err
}
if err := builder.buildNodeInfoManager(); err != nil {
if err := builder.buildActionSyncer(); err != nil {
return nil, err
}
cs := builder.cs
Expand Down
Loading

0 comments on commit df51d33

Please sign in to comment.