diff --git a/consensus/dummy/consensus.go b/consensus/dummy/consensus.go index 797966156b..717f41af66 100644 --- a/consensus/dummy/consensus.go +++ b/consensus/dummy/consensus.go @@ -263,6 +263,9 @@ func (self *DummyEngine) verifyHeader(chain consensus.ChainHeaderReader, header if err := eip4844.VerifyEIP4844Header(parent, header); err != nil { return err } + if *header.BlobGasUsed > 0 { // VerifyEIP4844Header ensures BlobGasUsed is non-nil + return fmt.Errorf("blobs not enabled on avalanche networks: used %d blob gas, expected 0", *header.BlobGasUsed) + } } return nil } diff --git a/core/state_processor_test.go b/core/state_processor_test.go index f6dcb789a6..0c27446964 100644 --- a/core/state_processor_test.go +++ b/core/state_processor_test.go @@ -117,7 +117,8 @@ func TestStateProcessorErrors(t *testing.T) { }, GasLimit: params.CortinaGasLimit, } - blockchain, _ = NewBlockChain(db, DefaultCacheConfig, gspec, dummy.NewCoinbaseFaker(), vm.Config{}, common.Hash{}, false) + // FullFaker used to skip header verification that enforces no blobs. + blockchain, _ = NewBlockChain(db, DefaultCacheConfig, gspec, dummy.NewFullFaker(), vm.Config{}, common.Hash{}, false) tooBigInitCode = [params.MaxInitCodeSize + 1]byte{} ) @@ -236,7 +237,8 @@ func TestStateProcessorErrors(t *testing.T) { want: "could not apply tx 0 [0x6c11015985ce82db691d7b2d017acda296db88b811c3c60dc71449c76256c716]: max fee per gas less than block base fee: address 0x71562b71999873DB5b286dF957af199Ec94617F7, maxFeePerGas: 1, baseFee: 225000000000", }, } { - block := GenerateBadBlock(gspec.ToBlock(), dummy.NewCoinbaseFaker(), tt.txs, gspec.Config) + // FullFaker used to skip header verification that enforces no blobs. + block := GenerateBadBlock(gspec.ToBlock(), dummy.NewFullFaker(), tt.txs, gspec.Config) _, err := blockchain.InsertChain(types.Blocks{block}) if err == nil { t.Fatal("block imported without errors") diff --git a/internal/ethapi/api_test.go b/internal/ethapi/api_test.go index 9d8a26045a..b74507c1be 100644 --- a/internal/ethapi/api_test.go +++ b/internal/ethapi/api_test.go @@ -1436,7 +1436,8 @@ func setupReceiptBackend(t *testing.T, genBlocks int) (*testBackend, []common.Ha // Set the terminal total difficulty in the config // genesis.Config.TerminalTotalDifficulty = big.NewInt(0) // genesis.Config.TerminalTotalDifficultyPassed = true - backend := newTestBackend(t, genBlocks, genesis, dummy.NewCoinbaseFaker(), func(i int, b *core.BlockGen) { + // FullFaker used to skip header verification that enforces no blobs. + backend := newTestBackend(t, genBlocks, genesis, dummy.NewFullFaker(), func(i int, b *core.BlockGen) { var ( tx *types.Transaction err error diff --git a/plugin/evm/block_verification.go b/plugin/evm/block_verification.go index 38f2bc29fa..f0f8db1658 100644 --- a/plugin/evm/block_verification.go +++ b/plugin/evm/block_verification.go @@ -287,6 +287,11 @@ func (v blockValidator) SyntacticVerify(b *Block, rules params.Rules) error { case *ethHeader.ParentBeaconRoot != (common.Hash{}): return fmt.Errorf("invalid parentBeaconRoot: have %x, expected empty hash", ethHeader.ParentBeaconRoot) } + if ethHeader.BlobGasUsed == nil { + return fmt.Errorf("blob gas used must not be nil in Cancun") + } else if *ethHeader.BlobGasUsed > 0 { + return fmt.Errorf("blobs not enabled on avalanche networks: used %d blob gas, expected 0", *ethHeader.BlobGasUsed) + } } return nil } diff --git a/plugin/evm/vm_test.go b/plugin/evm/vm_test.go index e7e702874e..ecd5fc626a 100644 --- a/plugin/evm/vm_test.go +++ b/plugin/evm/vm_test.go @@ -21,7 +21,9 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rlp" + "github.com/holiman/uint256" + "github.com/ava-labs/coreth/constants" "github.com/ava-labs/coreth/eth/filters" "github.com/ava-labs/coreth/internal/ethapi" "github.com/ava-labs/coreth/metrics" @@ -41,7 +43,6 @@ import ( "github.com/ava-labs/avalanchego/snow" "github.com/ava-labs/avalanchego/snow/validators" "github.com/ava-labs/avalanchego/utils/cb58" - "github.com/ava-labs/avalanchego/utils/constants" "github.com/ava-labs/avalanchego/utils/crypto/bls" "github.com/ava-labs/avalanchego/utils/crypto/secp256k1" "github.com/ava-labs/avalanchego/utils/formatting" @@ -55,6 +56,7 @@ import ( "github.com/ava-labs/avalanchego/vms/secp256k1fx" commonEng "github.com/ava-labs/avalanchego/snow/engine/common" + constantsEng "github.com/ava-labs/avalanchego/utils/constants" "github.com/ava-labs/coreth/consensus/dummy" "github.com/ava-labs/coreth/core" @@ -217,9 +219,9 @@ func NewContext() *snow.Context { ctx.ValidatorState = &validators.TestState{ GetSubnetIDF: func(_ context.Context, chainID ids.ID) (ids.ID, error) { subnetID, ok := map[ids.ID]ids.ID{ - constants.PlatformChainID: constants.PrimaryNetworkID, - testXChainID: constants.PrimaryNetworkID, - testCChainID: constants.PrimaryNetworkID, + constantsEng.PlatformChainID: constantsEng.PrimaryNetworkID, + testXChainID: constantsEng.PrimaryNetworkID, + testCChainID: constantsEng.PrimaryNetworkID, }[chainID] if !ok { return ids.Empty, errors.New("unknown chain") @@ -4090,6 +4092,50 @@ func TestParentBeaconRootBlock(t *testing.T) { } } +func TestNoBlobsAllowed(t *testing.T) { + ctx := context.Background() + require := require.New(t) + + gspec := new(core.Genesis) + err := json.Unmarshal([]byte(genesisJSONCancun), gspec) + require.NoError(err) + + // Make one block with a single blob tx + signer := types.NewCancunSigner(gspec.Config.ChainID) + blockGen := func(_ int, b *core.BlockGen) { + b.SetCoinbase(constants.BlackholeAddr) + fee := big.NewInt(500) + fee.Add(fee, b.BaseFee()) + tx, err := types.SignTx(types.NewTx(&types.BlobTx{ + Nonce: 0, + GasTipCap: uint256.NewInt(1), + GasFeeCap: uint256.MustFromBig(fee), + Gas: params.TxGas, + To: testEthAddrs[0], + BlobFeeCap: uint256.NewInt(1), + BlobHashes: []common.Hash{{1}}, + Value: new(uint256.Int), + }), signer, testKeys[0].ToECDSA()) + require.NoError(err) + b.AddTx(tx) + } + // FullFaker used to skip header verification so we can generate a block with blobs + _, blocks, _, err := core.GenerateChainWithGenesis(gspec, dummy.NewFullFaker(), 1, 10, blockGen) + require.NoError(err) + + // Create a VM with the genesis (will use header verification) + _, vm, _, _, _ := GenesisVM(t, true, genesisJSONCancun, "", "") + defer func() { require.NoError(vm.Shutdown(ctx)) }() + + // Verification should fail + vmBlock, err := vm.newBlock(blocks[0]) + require.NoError(err) + _, err = vm.ParseBlock(ctx, vmBlock.Bytes()) + require.ErrorContains(err, "blobs not enabled on avalanche networks") + err = vmBlock.Verify(ctx) + require.ErrorContains(err, "blobs not enabled on avalanche networks") +} + func TestMinFeeSetAtEUpgrade(t *testing.T) { require := require.New(t) now := time.Now()