diff --git a/op-acceptance-tests/acceptance-tests.yaml b/op-acceptance-tests/acceptance-tests.yaml index 75b15c3f5c1..d0d8251c7e5 100644 --- a/op-acceptance-tests/acceptance-tests.yaml +++ b/op-acceptance-tests/acceptance-tests.yaml @@ -191,6 +191,12 @@ gates: - package: github.com/ethereum-optimism/optimism/op-acceptance-tests/tests/sgt timeout: 10m + - id: l2blob + description: "L2 blob (EIP-4844) transaction tests." + tests: + - package: github.com/ethereum-optimism/optimism/op-acceptance-tests/tests/l2blob + timeout: 10m + - id: supernode description: "Supernode tests - tests for the op-supernode multi-chain consensus layer." tests: diff --git a/op-acceptance-tests/justfile b/op-acceptance-tests/justfile index fb523eab0af..2613c4bfe74 100644 --- a/op-acceptance-tests/justfile +++ b/op-acceptance-tests/justfile @@ -18,7 +18,10 @@ cgt: @just acceptance-test "" cgt sgt: - @just acceptance-test "" sgt + DEVSTACK_L2EL_KIND=op-reth OP_RETH_EXEC_PATH={{REPO_ROOT}}/rust/target/release/op-reth just acceptance-test "" sgt + +l2blob: + DEVSTACK_L2EL_KIND=op-reth OP_RETH_EXEC_PATH={{REPO_ROOT}}/rust/target/release/op-reth just acceptance-test "" l2blob # Run acceptance tests with mise-managed binary diff --git a/op-acceptance-tests/tests/l2blob/init_test.go b/op-acceptance-tests/tests/l2blob/init_test.go new file mode 100644 index 00000000000..46d7c97fc6b --- /dev/null +++ b/op-acceptance-tests/tests/l2blob/init_test.go @@ -0,0 +1,42 @@ +package l2blob + +import ( + "context" + "fmt" + "os" + "testing" + "time" + + "github.com/ethereum-optimism/optimism/op-devstack/presets" + "github.com/ethereum-optimism/optimism/op-devstack/stack" + "github.com/ethereum-optimism/optimism/op-devstack/sysgo" + "github.com/ethstorage/da-server/pkg/da" +) + +func TestMain(m *testing.M) { + // Start DAC server before the system — required by op-node when l2BlobTime is set. + dacCfg := da.Config{ + SequencerIP: "127.0.0.1", + ListenAddr: fmt.Sprintf("0.0.0.0:%d", dacPort), + StorePath: os.TempDir(), + } + dacServer := da.NewServer(&dacCfg) + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + if err := dacServer.Start(ctx); err != nil { + panic(fmt.Sprintf("failed to start DAC server: %v", err)) + } + defer func() { + stopCtx, stopCancel := context.WithTimeout(context.Background(), 5*time.Second) + defer stopCancel() + _ = dacServer.Stop(stopCtx) + }() + + presets.DoMain(m, + presets.WithMinimal(), + stack.MakeCommon(stack.Combine[*sysgo.Orchestrator]( + sysgo.WithDeployerOptions(WithL2BlobAtGenesis), + sysgo.WithGlobalL2CLOption(sysgo.L2CLDACUrls([]string{dacUrl})), + )), + ) +} diff --git a/op-acceptance-tests/tests/l2blob/l2blob_test.go b/op-acceptance-tests/tests/l2blob/l2blob_test.go new file mode 100644 index 00000000000..2918cd9cb3c --- /dev/null +++ b/op-acceptance-tests/tests/l2blob/l2blob_test.go @@ -0,0 +1,151 @@ +package l2blob + +import ( + "bytes" + "context" + "fmt" + mrand "math/rand" + "testing" + "time" + + "github.com/ethereum-optimism/optimism/op-chain-ops/devkeys" + opforks "github.com/ethereum-optimism/optimism/op-core/forks" + "github.com/ethereum-optimism/optimism/op-devstack/devtest" + "github.com/ethereum-optimism/optimism/op-devstack/presets" + "github.com/ethereum-optimism/optimism/op-e2e/e2eutils/intentbuilder" + "github.com/ethereum-optimism/optimism/op-service/eth" + "github.com/ethereum-optimism/optimism/op-service/txmgr" + "github.com/ethereum-optimism/optimism/op-service/txplan" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core/types" + daclient "github.com/ethstorage/da-server/pkg/da/client" + "github.com/holiman/uint256" +) + +const ( + dacPort = 39777 +) + +var ( + dacUrl = fmt.Sprintf("http://127.0.0.1:%d", dacPort) +) + +// WithL2BlobAtGenesis enables L2 blob support at genesis for all L2 chains. +func WithL2BlobAtGenesis(_ devtest.P, _ devkeys.Keys, builder intentbuilder.Builder) { + offset := uint64(0) + for _, l2Cfg := range builder.L2s() { + l2Cfg.WithForkAtGenesis(opforks.Isthmus) + } + // Set L2GenesisBlobTimeOffset directly via global deploy overrides + // since l2BlobTime is not a standard fork. + builder.WithGlobalOverride("l2GenesisBlobTimeOffset", (*hexutil.Uint64)(&offset)) +} + +// withL2Blobs is like txplan.WithBlobs but computes the blob base fee from the +// header's ExcessBlobGas instead of BlobScheduleConfig (which is not populated +// for L2 chains). +func withL2Blobs(blobs []*eth.Blob) txplan.Option { + return func(tx *txplan.PlannedTx) { + tx.Type.Set(types.BlobTxType) + tx.BlobFeeCap.DependOn(&tx.AgainstBlock) + tx.BlobFeeCap.Fn(func(_ context.Context) (*uint256.Int, error) { + header := tx.AgainstBlock.Value() + if ebg := header.ExcessBlobGas(); ebg != nil && *ebg > 0 { + fee := eth.CalcBlobFeeCancun(*ebg) + return uint256.MustFromBig(fee), nil + } + // Genesis or no excess blob gas — use minimum + return uint256.NewInt(1), nil + }) + var blobHashes []common.Hash + tx.Sidecar.Fn(func(_ context.Context) (*types.BlobTxSidecar, error) { + sidecar, hashes, err := txmgr.MakeSidecar(blobs, false) + if err != nil { + return nil, fmt.Errorf("make blob tx sidecar: %w", err) + } + blobHashes = hashes + return sidecar, nil + }) + tx.BlobHashes.DependOn(&tx.Sidecar) + tx.BlobHashes.Fn(func(_ context.Context) ([]common.Hash, error) { + return blobHashes, nil + }) + } +} + +// TestSubmitL2BlobTransaction tests that blob transactions can be submitted on L2 +// and that the blobs are retrievable from the DAC server. +// Mirrors op-e2e/l2blob/l2blob_test.go::TestSubmitTXWithBlobsFunctionSuccess. +func TestSubmitL2BlobTransaction(gt *testing.T) { + t := devtest.SerialT(gt) + sys := presets.NewMinimal(t) + + t.Require().True(sys.L2Chain.IsForkActive(opforks.Isthmus), "Isthmus fork must be active") + + alice := sys.FunderL2.NewFundedEOA(eth.OneEther) + + // Create random blobs + numBlobs := 3 + blobs := make([]*eth.Blob, numBlobs) + for i := range blobs { + b := getRandBlob(t, int64(i)) + blobs[i] = &b + } + + // Send a blob transaction + planned := alice.Transact( + alice.Plan(), + withL2Blobs(blobs), + txplan.WithTo(&common.Address{}), // blob tx requires a 'to' address + ) + + receipt, err := planned.Included.Eval(t.Ctx()) + t.Require().NoError(err, "blob transaction must be included") + t.Require().NotNil(receipt, "receipt must not be nil") + t.Require().Equal(uint64(1), receipt.Status, "blob transaction must succeed") + + // Verify the transaction has blob hashes + tx, err := planned.Signed.Eval(t.Ctx()) + t.Require().NoError(err, "must get signed transaction") + blobHashes := tx.BlobHashes() + t.Require().Equal(numBlobs, len(blobHashes), "transaction must have correct number of blob hashes") + + // Verify blob gas usage in the block + blockNum := receipt.BlockNumber + client := sys.L2EL.Escape().L2EthClient() + header, err := client.InfoByNumber(t.Ctx(), blockNum.Uint64()) + t.Require().NoError(err, "must get block header") + blobGasUsed := header.BlobGasUsed() + t.Require().NotZero(blobGasUsed, "blob gas used must be non-zero for block with blob transactions") + + // Download blobs from DAC server and verify content + dacCtx, cancel := context.WithTimeout(t.Ctx(), 5*time.Second) + defer cancel() + dacClient := daclient.New([]string{dacUrl}) + dblobs, err := dacClient.GetBlobs(dacCtx, blobHashes) + t.Require().NoError(err, "must download blobs from DAC server") + t.Require().Equal(len(blobHashes), len(dblobs), "downloaded blobs count must match blob hashes") + + for i, blob := range dblobs { + t.Require().Equal(eth.BlobSize, len(blob), "downloaded blob %d must have correct size", i) + t.Require().True(bytes.Equal(blob, blobs[i][:]), + "blob %d content mismatch: got %s vs expected %s", + i, common.Bytes2Hex(blob[:32]), common.Bytes2Hex(blobs[i][:32])) + } + + t.Logf("L2 blob transaction included: block=%d, blobGasUsed=%d, blobHashes=%d", + blockNum, blobGasUsed, len(blobHashes)) +} + +// getRandBlob generates a random blob with the given seed. +func getRandBlob(t devtest.T, seed int64) eth.Blob { + r := mrand.New(mrand.NewSource(seed)) + bigData := eth.Data(make([]byte, eth.MaxBlobDataSize)) + _, err := r.Read(bigData) + t.Require().NoError(err) + var b eth.Blob + err = b.FromData(bigData) + t.Require().NoError(err) + return b +} diff --git a/op-devstack/sysgo/l2_cl.go b/op-devstack/sysgo/l2_cl.go index 8ef75d92a52..81bfce21f98 100644 --- a/op-devstack/sysgo/l2_cl.go +++ b/op-devstack/sysgo/l2_cl.go @@ -38,6 +38,9 @@ type L2CLConfig struct { NoDiscovery bool FollowSource string + + // DACUrls is the list of DAC server URLs for the sequencer (required when l2BlobTime is set). + DACUrls []string } func L2CLSequencer() L2CLOption { @@ -52,6 +55,12 @@ func L2CLIndexing() L2CLOption { }) } +func L2CLDACUrls(urls []string) L2CLOption { + return L2CLOptionFn(func(p devtest.P, id stack.L2CLNodeID, cfg *L2CLConfig) { + cfg.DACUrls = urls + }) +} + func L2CLFollowSource(source string) L2CLOption { return L2CLOptionFn(func(p devtest.P, id stack.L2CLNodeID, cfg *L2CLConfig) { cfg.FollowSource = source diff --git a/op-devstack/sysgo/l2_cl_opnode.go b/op-devstack/sysgo/l2_cl_opnode.go index 7a3e0e6659f..94dcd762d07 100644 --- a/op-devstack/sysgo/l2_cl_opnode.go +++ b/op-devstack/sysgo/l2_cl_opnode.go @@ -354,6 +354,9 @@ func withOpNode(l2CLID stack.L2CLNodeID, l1CLID stack.L1CLNodeID, l1ELID stack.L if cfg.SafeDBPath != "" { nodeCfg.SafeDBPath = cfg.SafeDBPath } + if len(cfg.DACUrls) > 0 { + nodeCfg.DACConfig = &config.DACConfig{URLS: cfg.DACUrls} + } l2CLNode := &OpNode{ id: l2CLID, diff --git a/rust/Cargo.lock b/rust/Cargo.lock index f98e6bd55e1..8d7cff1288c 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -267,9 +267,8 @@ dependencies = [ [[package]] name = "alloy-evm" -version = "0.27.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b991c370ce44e70a3a9e474087e3d65e42e66f967644ad729dc4cec09a21fd09" +version = "0.27.2" +source = "git+https://github.com/QuarkChain/evm?rev=a7934ed#a7934ed32c2e5e13b5fc0760951f723ab12d4116" dependencies = [ "alloy-consensus", "alloy-eips", @@ -2574,7 +2573,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c" dependencies = [ "lazy_static", - "windows-sys 0.59.0", + "windows-sys 0.48.0", ] [[package]] @@ -4779,7 +4778,7 @@ dependencies = [ "libc", "percent-encoding", "pin-project-lite", - "socket2 0.6.2", + "socket2 0.5.10", "system-configuration 0.7.0", "tokio", "tower-layer", @@ -8968,7 +8967,7 @@ dependencies = [ "quinn-udp", "rustc-hash", "rustls", - "socket2 0.6.2", + "socket2 0.5.10", "thiserror 2.0.18", "tokio", "tracing", @@ -9005,7 +9004,7 @@ dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2 0.6.2", + "socket2 0.5.10", "tracing", "windows-sys 0.60.2", ] @@ -9446,7 +9445,7 @@ checksum = "1e061d1b48cb8d38042de4ae0a7a6401009d6143dc80d2e2d6f31f0bdd6470c7" [[package]] name = "reth-basic-payload-builder" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-consensus", "alloy-eips", @@ -9470,7 +9469,7 @@ dependencies = [ [[package]] name = "reth-chain-state" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-consensus", "alloy-eips", @@ -9502,7 +9501,7 @@ dependencies = [ [[package]] name = "reth-chainspec" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-chains", "alloy-consensus", @@ -9522,7 +9521,7 @@ dependencies = [ [[package]] name = "reth-cli" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-genesis", "clap", @@ -9536,7 +9535,7 @@ dependencies = [ [[package]] name = "reth-cli-commands" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-chains", "alloy-consensus", @@ -9622,7 +9621,7 @@ dependencies = [ [[package]] name = "reth-cli-runner" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "reth-tasks", "tokio", @@ -9632,7 +9631,7 @@ dependencies = [ [[package]] name = "reth-cli-util" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-eips", "alloy-primitives", @@ -9652,7 +9651,7 @@ dependencies = [ [[package]] name = "reth-codecs" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-consensus", "alloy-eips", @@ -9672,7 +9671,7 @@ dependencies = [ [[package]] name = "reth-codecs-derive" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "proc-macro2", "quote", @@ -9682,7 +9681,7 @@ dependencies = [ [[package]] name = "reth-config" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "eyre", "humantime-serde", @@ -9698,7 +9697,7 @@ dependencies = [ [[package]] name = "reth-consensus" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-consensus", "alloy-primitives", @@ -9711,7 +9710,7 @@ dependencies = [ [[package]] name = "reth-consensus-common" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-consensus", "alloy-eips", @@ -9723,7 +9722,7 @@ dependencies = [ [[package]] name = "reth-consensus-debug-client" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-consensus", "alloy-eips", @@ -9749,7 +9748,7 @@ dependencies = [ [[package]] name = "reth-db" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-primitives", "derive_more", @@ -9776,7 +9775,7 @@ dependencies = [ [[package]] name = "reth-db-api" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-consensus", "alloy-genesis", @@ -9805,7 +9804,7 @@ dependencies = [ [[package]] name = "reth-db-common" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-consensus", "alloy-genesis", @@ -9835,7 +9834,7 @@ dependencies = [ [[package]] name = "reth-db-models" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-eips", "alloy-primitives", @@ -9850,7 +9849,7 @@ dependencies = [ [[package]] name = "reth-discv4" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-primitives", "alloy-rlp", @@ -9875,7 +9874,7 @@ dependencies = [ [[package]] name = "reth-discv5" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-primitives", "alloy-rlp", @@ -9899,7 +9898,7 @@ dependencies = [ [[package]] name = "reth-dns-discovery" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-primitives", "dashmap", @@ -9923,7 +9922,7 @@ dependencies = [ [[package]] name = "reth-downloaders" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-consensus", "alloy-eips", @@ -9958,7 +9957,7 @@ dependencies = [ [[package]] name = "reth-e2e-test-utils" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-consensus", "alloy-eips", @@ -10016,7 +10015,7 @@ dependencies = [ [[package]] name = "reth-ecies" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "aes", "alloy-primitives", @@ -10044,7 +10043,7 @@ dependencies = [ [[package]] name = "reth-engine-local" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-consensus", "alloy-primitives", @@ -10068,7 +10067,7 @@ dependencies = [ [[package]] name = "reth-engine-primitives" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-consensus", "alloy-eips", @@ -10093,7 +10092,7 @@ dependencies = [ [[package]] name = "reth-engine-service" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "futures", "pin-project", @@ -10115,7 +10114,7 @@ dependencies = [ [[package]] name = "reth-engine-tree" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-consensus", "alloy-eip7928", @@ -10172,7 +10171,7 @@ dependencies = [ [[package]] name = "reth-engine-util" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-consensus", "alloy-rpc-types-engine", @@ -10200,7 +10199,7 @@ dependencies = [ [[package]] name = "reth-era" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-consensus", "alloy-eips", @@ -10215,7 +10214,7 @@ dependencies = [ [[package]] name = "reth-era-downloader" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-primitives", "bytes", @@ -10231,7 +10230,7 @@ dependencies = [ [[package]] name = "reth-era-utils" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-consensus", "alloy-primitives", @@ -10253,7 +10252,7 @@ dependencies = [ [[package]] name = "reth-errors" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "reth-consensus", "reth-execution-errors", @@ -10264,7 +10263,7 @@ dependencies = [ [[package]] name = "reth-eth-wire" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-chains", "alloy-primitives", @@ -10293,7 +10292,7 @@ dependencies = [ [[package]] name = "reth-eth-wire-types" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-chains", "alloy-consensus", @@ -10317,7 +10316,7 @@ dependencies = [ [[package]] name = "reth-ethereum" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-rpc-types-engine", "alloy-rpc-types-eth", @@ -10358,7 +10357,7 @@ dependencies = [ [[package]] name = "reth-ethereum-cli" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "clap", "eyre", @@ -10381,7 +10380,7 @@ dependencies = [ [[package]] name = "reth-ethereum-consensus" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-consensus", "alloy-eips", @@ -10397,7 +10396,7 @@ dependencies = [ [[package]] name = "reth-ethereum-engine-primitives" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-eips", "alloy-primitives", @@ -10415,7 +10414,7 @@ dependencies = [ [[package]] name = "reth-ethereum-forks" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-eip2124", "alloy-hardforks", @@ -10429,7 +10428,7 @@ dependencies = [ [[package]] name = "reth-ethereum-payload-builder" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-consensus", "alloy-eips", @@ -10458,7 +10457,7 @@ dependencies = [ [[package]] name = "reth-ethereum-primitives" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-consensus", "alloy-eips", @@ -10478,7 +10477,7 @@ dependencies = [ [[package]] name = "reth-etl" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "rayon", "reth-db-api", @@ -10488,7 +10487,7 @@ dependencies = [ [[package]] name = "reth-evm" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-consensus", "alloy-eips", @@ -10512,7 +10511,7 @@ dependencies = [ [[package]] name = "reth-evm-ethereum" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-consensus", "alloy-eips", @@ -10534,7 +10533,7 @@ dependencies = [ [[package]] name = "reth-execution-errors" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-evm", "alloy-primitives", @@ -10547,7 +10546,7 @@ dependencies = [ [[package]] name = "reth-execution-types" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-consensus", "alloy-eips", @@ -10565,7 +10564,7 @@ dependencies = [ [[package]] name = "reth-exex" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-consensus", "alloy-eips", @@ -10603,7 +10602,7 @@ dependencies = [ [[package]] name = "reth-exex-test-utils" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-eips", "eyre", @@ -10635,7 +10634,7 @@ dependencies = [ [[package]] name = "reth-exex-types" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-eips", "alloy-primitives", @@ -10649,7 +10648,7 @@ dependencies = [ [[package]] name = "reth-fs-util" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "serde", "serde_json", @@ -10659,7 +10658,7 @@ dependencies = [ [[package]] name = "reth-invalid-block-hooks" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-consensus", "alloy-primitives", @@ -10687,7 +10686,7 @@ dependencies = [ [[package]] name = "reth-ipc" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "bytes", "futures", @@ -10707,7 +10706,7 @@ dependencies = [ [[package]] name = "reth-libmdbx" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "bitflags 2.10.0", "byteorder", @@ -10723,7 +10722,7 @@ dependencies = [ [[package]] name = "reth-mdbx-sys" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "bindgen", "cc", @@ -10732,7 +10731,7 @@ dependencies = [ [[package]] name = "reth-metrics" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "futures", "metrics", @@ -10744,7 +10743,7 @@ dependencies = [ [[package]] name = "reth-net-banlist" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-primitives", "ipnet", @@ -10753,7 +10752,7 @@ dependencies = [ [[package]] name = "reth-net-nat" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "futures-util", "if-addrs 0.14.0", @@ -10767,7 +10766,7 @@ dependencies = [ [[package]] name = "reth-network" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-consensus", "alloy-eips", @@ -10824,7 +10823,7 @@ dependencies = [ [[package]] name = "reth-network-api" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-consensus", "alloy-primitives", @@ -10849,7 +10848,7 @@ dependencies = [ [[package]] name = "reth-network-p2p" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-consensus", "alloy-eips", @@ -10872,7 +10871,7 @@ dependencies = [ [[package]] name = "reth-network-peers" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-primitives", "alloy-rlp", @@ -10887,7 +10886,7 @@ dependencies = [ [[package]] name = "reth-network-types" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-eip2124", "humantime-serde", @@ -10901,7 +10900,7 @@ dependencies = [ [[package]] name = "reth-nippy-jar" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "anyhow", "bincode 1.3.3", @@ -10918,7 +10917,7 @@ dependencies = [ [[package]] name = "reth-node-api" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-rpc-types-engine", "eyre", @@ -10942,7 +10941,7 @@ dependencies = [ [[package]] name = "reth-node-builder" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-consensus", "alloy-eips", @@ -11011,7 +11010,7 @@ dependencies = [ [[package]] name = "reth-node-core" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-consensus", "alloy-eips", @@ -11066,7 +11065,7 @@ dependencies = [ [[package]] name = "reth-node-ethereum" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-eips", "alloy-network", @@ -11104,7 +11103,7 @@ dependencies = [ [[package]] name = "reth-node-ethstats" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-consensus", "alloy-primitives", @@ -11128,7 +11127,7 @@ dependencies = [ [[package]] name = "reth-node-events" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-consensus", "alloy-eips", @@ -11152,7 +11151,7 @@ dependencies = [ [[package]] name = "reth-node-metrics" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "bytes", "eyre", @@ -11181,7 +11180,7 @@ dependencies = [ [[package]] name = "reth-node-types" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "reth-chainspec", "reth-db-api", @@ -11756,7 +11755,7 @@ dependencies = [ [[package]] name = "reth-payload-builder" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-consensus", "alloy-primitives", @@ -11777,7 +11776,7 @@ dependencies = [ [[package]] name = "reth-payload-builder-primitives" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "pin-project", "reth-payload-primitives", @@ -11789,7 +11788,7 @@ dependencies = [ [[package]] name = "reth-payload-primitives" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-consensus", "alloy-eips", @@ -11812,7 +11811,7 @@ dependencies = [ [[package]] name = "reth-payload-util" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-consensus", "alloy-primitives", @@ -11822,7 +11821,7 @@ dependencies = [ [[package]] name = "reth-payload-validator" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-consensus", "alloy-rpc-types-engine", @@ -11832,7 +11831,7 @@ dependencies = [ [[package]] name = "reth-primitives" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-consensus", "once_cell", @@ -11845,7 +11844,7 @@ dependencies = [ [[package]] name = "reth-primitives-traits" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-consensus", "alloy-eips", @@ -11879,7 +11878,7 @@ dependencies = [ [[package]] name = "reth-provider" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-consensus", "alloy-eips", @@ -11924,7 +11923,7 @@ dependencies = [ [[package]] name = "reth-prune" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-consensus", "alloy-eips", @@ -11953,7 +11952,7 @@ dependencies = [ [[package]] name = "reth-prune-types" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-primitives", "arbitrary", @@ -11969,7 +11968,7 @@ dependencies = [ [[package]] name = "reth-revm" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-primitives", "reth-primitives-traits", @@ -11982,7 +11981,7 @@ dependencies = [ [[package]] name = "reth-rpc" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-consensus", "alloy-dyn-abi", @@ -12059,7 +12058,7 @@ dependencies = [ [[package]] name = "reth-rpc-api" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-eip7928", "alloy-eips", @@ -12089,7 +12088,7 @@ dependencies = [ [[package]] name = "reth-rpc-builder" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-network", "alloy-provider", @@ -12130,7 +12129,7 @@ dependencies = [ [[package]] name = "reth-rpc-convert" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-consensus", "alloy-evm", @@ -12154,7 +12153,7 @@ dependencies = [ [[package]] name = "reth-rpc-engine-api" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-eips", "alloy-primitives", @@ -12184,7 +12183,7 @@ dependencies = [ [[package]] name = "reth-rpc-eth-api" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-consensus", "alloy-dyn-abi", @@ -12228,7 +12227,7 @@ dependencies = [ [[package]] name = "reth-rpc-eth-types" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-consensus", "alloy-eips", @@ -12276,7 +12275,7 @@ dependencies = [ [[package]] name = "reth-rpc-layer" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-rpc-types-engine", "http", @@ -12290,7 +12289,7 @@ dependencies = [ [[package]] name = "reth-rpc-server-types" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-eips", "alloy-primitives", @@ -12306,7 +12305,7 @@ dependencies = [ [[package]] name = "reth-stages" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-consensus", "alloy-eips", @@ -12356,7 +12355,7 @@ dependencies = [ [[package]] name = "reth-stages-api" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-eips", "alloy-primitives", @@ -12383,7 +12382,7 @@ dependencies = [ [[package]] name = "reth-stages-types" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-primitives", "arbitrary", @@ -12397,7 +12396,7 @@ dependencies = [ [[package]] name = "reth-static-file" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-primitives", "parking_lot", @@ -12417,7 +12416,7 @@ dependencies = [ [[package]] name = "reth-static-file-types" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-primitives", "clap", @@ -12432,7 +12431,7 @@ dependencies = [ [[package]] name = "reth-storage-api" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-consensus", "alloy-eips", @@ -12456,7 +12455,7 @@ dependencies = [ [[package]] name = "reth-storage-errors" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-eips", "alloy-primitives", @@ -12473,7 +12472,7 @@ dependencies = [ [[package]] name = "reth-tasks" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "auto_impl", "dyn-clone", @@ -12491,7 +12490,7 @@ dependencies = [ [[package]] name = "reth-testing-utils" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-consensus", "alloy-eips", @@ -12507,7 +12506,7 @@ dependencies = [ [[package]] name = "reth-tokio-util" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "tokio", "tokio-stream", @@ -12517,7 +12516,7 @@ dependencies = [ [[package]] name = "reth-tracing" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "clap", "eyre", @@ -12536,7 +12535,7 @@ dependencies = [ [[package]] name = "reth-tracing-otlp" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "clap", "eyre", @@ -12554,7 +12553,7 @@ dependencies = [ [[package]] name = "reth-transaction-pool" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-consensus", "alloy-eips", @@ -12600,7 +12599,7 @@ dependencies = [ [[package]] name = "reth-trie" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-consensus", "alloy-eips", @@ -12626,7 +12625,7 @@ dependencies = [ [[package]] name = "reth-trie-common" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-consensus", "alloy-primitives", @@ -12653,7 +12652,7 @@ dependencies = [ [[package]] name = "reth-trie-db" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-primitives", "metrics", @@ -12673,7 +12672,7 @@ dependencies = [ [[package]] name = "reth-trie-parallel" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-primitives", "alloy-rlp", @@ -12698,7 +12697,7 @@ dependencies = [ [[package]] name = "reth-trie-sparse" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "alloy-primitives", "alloy-rlp", @@ -12717,7 +12716,7 @@ dependencies = [ [[package]] name = "reth-zstd-compressors" version = "1.11.0" -source = "git+https://github.com/QuarkChain/reth?rev=4efc6c714#4efc6c7141d7eeb75f62336a662bdbf86f139954" +source = "git+https://github.com/QuarkChain/reth?rev=1b648f217#1b648f217885e532ab595aa00acb82fdfffb9f84" dependencies = [ "zstd", ] @@ -15033,7 +15032,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c5f7c95348f20c1c913d72157b3c6dee6ea3e30b3d19502c5a7f6d3f160dacbf" dependencies = [ "cc", - "windows-targets 0.52.6", + "windows-targets 0.48.5", ] [[package]] @@ -15617,7 +15616,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.48.0", ] [[package]] diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 0e6d2a03e9b..1b7b9c36993 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -307,78 +307,78 @@ alloy-op-evm = { version = "0.26.3", path = "alloy-op-evm/", default-features = alloy-op-hardforks = { version = "0.4.7", path = "alloy-op-hardforks/", default-features = false } # ==================== RETH CRATES (from git rev 564ffa58 / main) ==================== -reth = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714" } -reth-basic-payload-builder = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714" } -reth-chain-state = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714" } -reth-chainspec = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714", default-features = false } -reth-cli = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714" } -reth-cli-commands = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714" } -reth-cli-runner = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714" } -reth-cli-util = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714" } -reth-codecs = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714" } -reth-consensus = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714", default-features = false } -reth-consensus-common = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714", default-features = false } -reth-db = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714", default-features = false } -reth-db-api = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714" } -reth-db-common = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714" } -reth-downloaders = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714" } -reth-e2e-test-utils = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714" } -reth-engine-local = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714" } -reth-engine-primitives = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714", default-features = false } -reth-errors = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714" } -reth-eth-wire = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714" } -reth-ethereum = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714" } -reth-ethereum-cli = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714" } -reth-ethereum-consensus = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714" } -reth-ethereum-forks = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714", default-features = false } -reth-ethereum-primitives = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714" } -reth-evm = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714", default-features = false } -reth-evm-ethereum = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714" } -reth-exex = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714" } -reth-exex-test-utils = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714" } -reth-execution-errors = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714", default-features = false } -reth-execution-types = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714", default-features = false } -reth-fs-util = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714" } -reth-metrics = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714" } -reth-network = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714" } -reth-network-api = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714" } -reth-network-peers = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714", default-features = false } -reth-node-api = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714" } -reth-node-builder = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714" } -reth-node-core = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714" } -reth-node-ethereum = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714" } -reth-node-events = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714" } -reth-node-metrics = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714" } -reth-payload-builder = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714" } -reth-payload-builder-primitives = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714" } -reth-payload-primitives = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714" } -reth-payload-util = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714" } -reth-payload-validator = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714" } -reth-primitives-traits = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714", default-features = false } -reth-provider = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714" } -reth-prune = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714" } -reth-prune-types = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714", default-features = false } -reth-revm = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714", default-features = false } -reth-rpc = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714" } -reth-rpc-api = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714" } -reth-rpc-builder = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714" } -reth-rpc-engine-api = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714" } -reth-rpc-eth-api = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714" } -reth-rpc-eth-types = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714", default-features = false } -reth-rpc-server-types = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714" } -reth-stages = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714" } -reth-stages-types = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714", default-features = false } -reth-static-file = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714" } -reth-static-file-types = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714", default-features = false } -reth-storage-api = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714", default-features = false } -reth-storage-errors = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714", default-features = false } -reth-tasks = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714" } -reth-tracing = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714", default-features = false } -reth-transaction-pool = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714" } -reth-trie = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714" } -reth-trie-common = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714", default-features = false } -reth-trie-db = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714" } -reth-zstd-compressors = { git = "https://github.com/QuarkChain/reth", rev = "4efc6c714", default-features = false } +reth = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217" } +reth-basic-payload-builder = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217" } +reth-chain-state = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217" } +reth-chainspec = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217", default-features = false } +reth-cli = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217" } +reth-cli-commands = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217" } +reth-cli-runner = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217" } +reth-cli-util = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217" } +reth-codecs = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217" } +reth-consensus = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217", default-features = false } +reth-consensus-common = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217", default-features = false } +reth-db = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217", default-features = false } +reth-db-api = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217" } +reth-db-common = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217" } +reth-downloaders = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217" } +reth-e2e-test-utils = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217" } +reth-engine-local = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217" } +reth-engine-primitives = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217", default-features = false } +reth-errors = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217" } +reth-eth-wire = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217" } +reth-ethereum = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217" } +reth-ethereum-cli = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217" } +reth-ethereum-consensus = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217" } +reth-ethereum-forks = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217", default-features = false } +reth-ethereum-primitives = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217" } +reth-evm = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217", default-features = false } +reth-evm-ethereum = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217" } +reth-exex = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217" } +reth-exex-test-utils = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217" } +reth-execution-errors = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217", default-features = false } +reth-execution-types = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217", default-features = false } +reth-fs-util = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217" } +reth-metrics = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217" } +reth-network = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217" } +reth-network-api = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217" } +reth-network-peers = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217", default-features = false } +reth-node-api = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217" } +reth-node-builder = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217" } +reth-node-core = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217" } +reth-node-ethereum = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217" } +reth-node-events = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217" } +reth-node-metrics = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217" } +reth-payload-builder = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217" } +reth-payload-builder-primitives = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217" } +reth-payload-primitives = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217" } +reth-payload-util = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217" } +reth-payload-validator = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217" } +reth-primitives-traits = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217", default-features = false } +reth-provider = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217" } +reth-prune = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217" } +reth-prune-types = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217", default-features = false } +reth-revm = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217", default-features = false } +reth-rpc = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217" } +reth-rpc-api = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217" } +reth-rpc-builder = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217" } +reth-rpc-engine-api = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217" } +reth-rpc-eth-api = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217" } +reth-rpc-eth-types = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217", default-features = false } +reth-rpc-server-types = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217" } +reth-stages = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217" } +reth-stages-types = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217", default-features = false } +reth-static-file = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217" } +reth-static-file-types = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217", default-features = false } +reth-storage-api = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217", default-features = false } +reth-storage-errors = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217", default-features = false } +reth-tasks = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217" } +reth-tracing = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217", default-features = false } +reth-transaction-pool = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217" } +reth-trie = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217" } +reth-trie-common = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217", default-features = false } +reth-trie-db = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217" } +reth-zstd-compressors = { git = "https://github.com/QuarkChain/reth", rev = "1b648f217", default-features = false } # ==================== REVM (latest: op-reth versions) ==================== revm = { version = "34.0.0", default-features = false } @@ -666,6 +666,8 @@ op-alloy-consensus = { path = "op-alloy/crates/consensus" } op-alloy-network = { path = "op-alloy/crates/network" } # Duplicated by: reth-rpc-convert (reth git) op-alloy-rpc-types = { path = "op-alloy/crates/rpc-types" } +# Patched to add EIP-4844 support for OpTxEnvelope +alloy-evm = { git = "https://github.com/QuarkChain/evm", rev = "a7934ed" } # Duplicated by: alloy-evm (crates.io) op-alloy = { path = "op-alloy/crates/op-alloy" } # Duplicated by: alloy-evm (crates.io) diff --git a/rust/alloy-op-evm/src/block/mod.rs b/rust/alloy-op-evm/src/block/mod.rs index 1c1f4852767..64a243aa69b 100644 --- a/rust/alloy-op-evm/src/block/mod.rs +++ b/rust/alloy-op-evm/src/block/mod.rs @@ -66,6 +66,8 @@ pub struct OpTxResult { pub is_deposit: bool, /// The sender of the transaction. pub sender: Address, + /// Actual blob gas used by this transaction (from EIP-4844 blob_gas_used). + pub actual_blob_gas: u64, } impl TxResult for OpTxResult { @@ -96,6 +98,8 @@ pub struct OpBlockExecutor { /// This is only set for blocks post-Jovian activation. /// See [DA footprint block limit spec](https://github.com/ethereum-optimism/specs/blob/main/specs/protocol/jovian/exec-engine.md#da-footprint-block-limit) pub da_footprint_used: u64, + /// Actual blob gas used by EIP-4844 transactions. + pub blob_gas_used: u64, /// Whether Regolith hardfork is active. pub is_regolith: bool, /// Utility to call system smart contracts. @@ -120,6 +124,7 @@ where receipts: Vec::new(), gas_used: 0, da_footprint_used: 0, + blob_gas_used: 0, ctx, } } @@ -268,6 +273,7 @@ where BlockExecutionError::evm(err, hash) })?; + let actual_blob_gas = tx.tx().blob_gas_used().unwrap_or_default(); Ok(OpTxResult { inner: EthTxResult { result, @@ -276,6 +282,7 @@ where }, is_deposit, sender: *tx.signer(), + actual_blob_gas, }) } @@ -284,6 +291,7 @@ where inner: EthTxResult { result: ResultAndState { result, state }, blob_gas_used, tx_type }, is_deposit, sender, + actual_blob_gas, } = output; // Fetch the depositor account from the database for the deposit nonce. @@ -310,6 +318,9 @@ where self.da_footprint_used = self.da_footprint_used.saturating_add(blob_gas_used); } + // Accumulate actual blob gas from EIP-4844 transactions + self.blob_gas_used += actual_blob_gas; + self.receipts.push( match self.receipt_builder.build_receipt(ReceiptBuilderCtx { tx_type, @@ -380,7 +391,9 @@ where receipts: self.receipts, requests: Default::default(), gas_used: legacy_gas_used, - blob_gas_used: self.da_footprint_used, + // da_footprint_used tracks Jovian DA footprint; blob_gas_used tracks actual + // EIP-4844 blob gas. They are mutually exclusive in our fork. + blob_gas_used: self.da_footprint_used.saturating_add(self.blob_gas_used), }, )) } diff --git a/rust/alloy-op-evm/src/block/receipt_builder.rs b/rust/alloy-op-evm/src/block/receipt_builder.rs index 7fd04314c7f..f2cd2c1c70e 100644 --- a/rust/alloy-op-evm/src/block/receipt_builder.rs +++ b/rust/alloy-op-evm/src/block/receipt_builder.rs @@ -57,6 +57,7 @@ impl OpReceiptBuilder for OpAlloyReceiptBuilder { OpTxType::Legacy => OpReceiptEnvelope::Legacy(receipt), OpTxType::Eip2930 => OpReceiptEnvelope::Eip2930(receipt), OpTxType::Eip1559 => OpReceiptEnvelope::Eip1559(receipt), + OpTxType::Eip4844 => OpReceiptEnvelope::Eip4844(receipt), OpTxType::Eip7702 => OpReceiptEnvelope::Eip7702(receipt), OpTxType::Deposit => unreachable!(), }) diff --git a/rust/alloy-op-hardforks/src/lib.rs b/rust/alloy-op-hardforks/src/lib.rs index 9921cc58428..6eff21a57d9 100644 --- a/rust/alloy-op-hardforks/src/lib.rs +++ b/rust/alloy-op-hardforks/src/lib.rs @@ -267,6 +267,15 @@ pub trait OpHardforks: EthereumHardforks { fn is_sgt_native_backed(&self) -> bool { true } + + /// Returns `true` if L2 Blob support is active at given block timestamp. + /// + /// L2 Blob enables EIP-4844 blob transactions on L2 chains. + /// Default implementation returns `false`. Override in chain-specific implementations + /// (e.g., `OpChainSpec`) to enable L2 Blob based on configuration. + fn is_l2_blob_active_at_timestamp(&self, _timestamp: u64) -> bool { + false + } } /// A type allowing to configure activation [`ForkCondition`]s for a given list of diff --git a/rust/op-alloy/crates/consensus/src/receipts/envelope.rs b/rust/op-alloy/crates/consensus/src/receipts/envelope.rs index d0efcea1583..7b52db0c4bf 100644 --- a/rust/op-alloy/crates/consensus/src/receipts/envelope.rs +++ b/rust/op-alloy/crates/consensus/src/receipts/envelope.rs @@ -37,6 +37,11 @@ pub enum OpReceiptEnvelope { /// [EIP-1559]: https://eips.ethereum.org/EIPS/eip-1559 #[cfg_attr(feature = "serde", serde(rename = "0x2", alias = "0x02"))] Eip1559(ReceiptWithBloom>), + /// Receipt envelope with type flag 3, containing a [EIP-4844] receipt. + /// + /// [EIP-4844]: https://eips.ethereum.org/EIPS/eip-4844 + #[cfg_attr(feature = "serde", serde(rename = "0x3", alias = "0x03"))] + Eip4844(ReceiptWithBloom>), /// Receipt envelope with type flag 4, containing a [EIP-7702] receipt. /// /// [EIP-7702]: https://eips.ethereum.org/EIPS/eip-7702 @@ -73,6 +78,9 @@ impl OpReceiptEnvelope { OpTxType::Eip1559 => { Self::Eip1559(ReceiptWithBloom { receipt: inner_receipt, logs_bloom }) } + OpTxType::Eip4844 => { + Self::Eip4844(ReceiptWithBloom { receipt: inner_receipt, logs_bloom }) + } OpTxType::Eip7702 => { Self::Eip7702(ReceiptWithBloom { receipt: inner_receipt, logs_bloom }) } @@ -98,6 +106,7 @@ impl OpReceiptEnvelope { Self::Legacy(_) => OpTxType::Legacy, Self::Eip2930(_) => OpTxType::Eip2930, Self::Eip1559(_) => OpTxType::Eip1559, + Self::Eip4844(_) => OpTxType::Eip4844, Self::Eip7702(_) => OpTxType::Eip7702, Self::Deposit(_) => OpTxType::Deposit, } @@ -126,6 +135,7 @@ impl OpReceiptEnvelope { Self::Legacy(r) => OpReceiptEnvelope::Legacy(r.map_logs(f)), Self::Eip2930(r) => OpReceiptEnvelope::Eip2930(r.map_logs(f)), Self::Eip1559(r) => OpReceiptEnvelope::Eip1559(r.map_logs(f)), + Self::Eip4844(r) => OpReceiptEnvelope::Eip4844(r.map_logs(f)), Self::Eip7702(r) => OpReceiptEnvelope::Eip7702(r.map_logs(f)), Self::Deposit(r) => OpReceiptEnvelope::Deposit(r.map_receipt(|r| r.map_logs(f))), } @@ -144,7 +154,7 @@ impl OpReceiptEnvelope { /// Return the receipt's bloom. pub const fn logs_bloom(&self) -> &Bloom { match self { - Self::Legacy(t) | Self::Eip2930(t) | Self::Eip1559(t) | Self::Eip7702(t) => { + Self::Legacy(t) | Self::Eip2930(t) | Self::Eip1559(t) | Self::Eip4844(t) | Self::Eip7702(t) => { &t.logs_bloom } Self::Deposit(t) => &t.logs_bloom, @@ -180,7 +190,7 @@ impl OpReceiptEnvelope { /// Consumes the type and returns the underlying [`Receipt`]. pub fn into_receipt(self) -> Receipt { match self { - Self::Legacy(t) | Self::Eip2930(t) | Self::Eip1559(t) | Self::Eip7702(t) => t.receipt, + Self::Legacy(t) | Self::Eip2930(t) | Self::Eip1559(t) | Self::Eip4844(t) | Self::Eip7702(t) => t.receipt, Self::Deposit(t) => t.receipt.into_inner(), } } @@ -189,7 +199,7 @@ impl OpReceiptEnvelope { /// receipt types may be added. pub const fn as_receipt(&self) -> Option<&Receipt> { match self { - Self::Legacy(t) | Self::Eip2930(t) | Self::Eip1559(t) | Self::Eip7702(t) => { + Self::Legacy(t) | Self::Eip2930(t) | Self::Eip1559(t) | Self::Eip4844(t) | Self::Eip7702(t) => { Some(&t.receipt) } Self::Deposit(t) => Some(&t.receipt.inner), @@ -201,7 +211,7 @@ impl OpReceiptEnvelope { /// Get the length of the inner receipt in the 2718 encoding. pub fn inner_length(&self) -> usize { match self { - Self::Legacy(t) | Self::Eip2930(t) | Self::Eip1559(t) | Self::Eip7702(t) => t.length(), + Self::Legacy(t) | Self::Eip2930(t) | Self::Eip1559(t) | Self::Eip4844(t) | Self::Eip7702(t) => t.length(), Self::Deposit(t) => t.length(), } } @@ -277,6 +287,7 @@ impl Typed2718 for OpReceiptEnvelope { Self::Legacy(_) => OpTxType::Legacy, Self::Eip2930(_) => OpTxType::Eip2930, Self::Eip1559(_) => OpTxType::Eip1559, + Self::Eip4844(_) => OpTxType::Eip4844, Self::Eip7702(_) => OpTxType::Eip7702, Self::Deposit(_) => OpTxType::Deposit, }; @@ -302,7 +313,7 @@ impl Encodable2718 for OpReceiptEnvelope { } match self { Self::Deposit(t) => t.encode(out), - Self::Legacy(t) | Self::Eip2930(t) | Self::Eip1559(t) | Self::Eip7702(t) => { + Self::Legacy(t) | Self::Eip2930(t) | Self::Eip1559(t) | Self::Eip4844(t) | Self::Eip7702(t) => { t.encode(out) } } @@ -317,6 +328,7 @@ impl Decodable2718 for OpReceiptEnvelope { .into()) } OpTxType::Eip1559 => Ok(Self::Eip1559(Decodable::decode(buf)?)), + OpTxType::Eip4844 => Ok(Self::Eip4844(Decodable::decode(buf)?)), OpTxType::Eip7702 => Ok(Self::Eip7702(Decodable::decode(buf)?)), OpTxType::Eip2930 => Ok(Self::Eip2930(Decodable::decode(buf)?)), OpTxType::Deposit => Ok(Self::Deposit(Decodable::decode(buf)?)), @@ -349,10 +361,11 @@ where T: arbitrary::Arbitrary<'a>, { fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result { - match u.int_in_range(0..=4)? { + match u.int_in_range(0..=5)? { 0 => Ok(Self::Legacy(ReceiptWithBloom::arbitrary(u)?)), 1 => Ok(Self::Eip2930(ReceiptWithBloom::arbitrary(u)?)), 2 => Ok(Self::Eip1559(ReceiptWithBloom::arbitrary(u)?)), + 3 => Ok(Self::Eip4844(ReceiptWithBloom::arbitrary(u)?)), _ => Ok(Self::Deposit(OpDepositReceiptWithBloom::arbitrary(u)?)), } } diff --git a/rust/op-alloy/crates/consensus/src/receipts/receipt.rs b/rust/op-alloy/crates/consensus/src/receipts/receipt.rs index 21b2b2ad632..054785586b5 100644 --- a/rust/op-alloy/crates/consensus/src/receipts/receipt.rs +++ b/rust/op-alloy/crates/consensus/src/receipts/receipt.rs @@ -30,6 +30,9 @@ pub enum OpReceipt { /// EIP-1559 receipt #[cfg_attr(feature = "serde", serde(rename = "0x2", alias = "0x02"))] Eip1559(Receipt), + /// EIP-4844 receipt + #[cfg_attr(feature = "serde", serde(rename = "0x3", alias = "0x03"))] + Eip4844(Receipt), /// EIP-7702 receipt #[cfg_attr(feature = "serde", serde(rename = "0x4", alias = "0x04"))] Eip7702(Receipt), @@ -45,6 +48,7 @@ impl OpReceipt { Self::Legacy(_) => OpTxType::Legacy, Self::Eip2930(_) => OpTxType::Eip2930, Self::Eip1559(_) => OpTxType::Eip1559, + Self::Eip4844(_) => OpTxType::Eip4844, Self::Eip7702(_) => OpTxType::Eip7702, Self::Deposit(_) => OpTxType::Deposit, } @@ -56,6 +60,7 @@ impl OpReceipt { Self::Legacy(receipt) | Self::Eip2930(receipt) | Self::Eip1559(receipt) | + Self::Eip4844(receipt) | Self::Eip7702(receipt) => receipt, Self::Deposit(receipt) => &receipt.inner, } @@ -67,6 +72,7 @@ impl OpReceipt { Self::Legacy(receipt) | Self::Eip2930(receipt) | Self::Eip1559(receipt) | + Self::Eip4844(receipt) | Self::Eip7702(receipt) => receipt, Self::Deposit(receipt) => &mut receipt.inner, } @@ -78,6 +84,7 @@ impl OpReceipt { Self::Legacy(receipt) | Self::Eip2930(receipt) | Self::Eip1559(receipt) | + Self::Eip4844(receipt) | Self::Eip7702(receipt) => receipt, Self::Deposit(receipt) => receipt.inner, } @@ -91,6 +98,7 @@ impl OpReceipt { Self::Legacy(receipt) => OpReceipt::Legacy(receipt.map_logs(f)), Self::Eip2930(receipt) => OpReceipt::Eip2930(receipt.map_logs(f)), Self::Eip1559(receipt) => OpReceipt::Eip1559(receipt.map_logs(f)), + Self::Eip4844(receipt) => OpReceipt::Eip4844(receipt.map_logs(f)), Self::Eip7702(receipt) => OpReceipt::Eip7702(receipt.map_logs(f)), Self::Deposit(receipt) => OpReceipt::Deposit(receipt.map_logs(f)), } @@ -105,6 +113,7 @@ impl OpReceipt { Self::Legacy(receipt) | Self::Eip2930(receipt) | Self::Eip1559(receipt) | + Self::Eip4844(receipt) | Self::Eip7702(receipt) => receipt.rlp_encoded_fields_length_with_bloom(bloom), Self::Deposit(receipt) => receipt.rlp_encoded_fields_length_with_bloom(bloom), } @@ -119,6 +128,7 @@ impl OpReceipt { Self::Legacy(receipt) | Self::Eip2930(receipt) | Self::Eip1559(receipt) | + Self::Eip4844(receipt) | Self::Eip7702(receipt) => receipt.rlp_encode_fields_with_bloom(bloom, out), Self::Deposit(receipt) => receipt.rlp_encode_fields_with_bloom(bloom, out), } @@ -165,6 +175,11 @@ impl OpReceipt { RlpDecodableReceipt::rlp_decode_with_bloom(buf)?; Ok(ReceiptWithBloom { receipt: Self::Eip1559(receipt), logs_bloom }) } + OpTxType::Eip4844 => { + let ReceiptWithBloom { receipt, logs_bloom } = + RlpDecodableReceipt::rlp_decode_with_bloom(buf)?; + Ok(ReceiptWithBloom { receipt: Self::Eip4844(receipt), logs_bloom }) + } OpTxType::Eip7702 => { let ReceiptWithBloom { receipt, logs_bloom } = RlpDecodableReceipt::rlp_decode_with_bloom(buf)?; @@ -188,6 +203,7 @@ impl OpReceipt { Self::Legacy(receipt) | Self::Eip2930(receipt) | Self::Eip1559(receipt) | + Self::Eip4844(receipt) | Self::Eip7702(receipt) => { receipt.status.encode(out); receipt.cumulative_gas_used.encode(out); @@ -217,6 +233,7 @@ impl OpReceipt { Self::Legacy(receipt) | Self::Eip2930(receipt) | Self::Eip1559(receipt) | + Self::Eip4844(receipt) | Self::Eip7702(receipt) => { receipt.status.length() + receipt.cumulative_gas_used.length() + @@ -257,6 +274,7 @@ impl OpReceipt { OpTxType::Legacy => Ok(Self::Legacy(Receipt { status, cumulative_gas_used, logs })), OpTxType::Eip2930 => Ok(Self::Eip2930(Receipt { status, cumulative_gas_used, logs })), OpTxType::Eip1559 => Ok(Self::Eip1559(Receipt { status, cumulative_gas_used, logs })), + OpTxType::Eip4844 => Ok(Self::Eip4844(Receipt { status, cumulative_gas_used, logs })), OpTxType::Eip7702 => Ok(Self::Eip7702(Receipt { status, cumulative_gas_used, logs })), OpTxType::Deposit => Ok(Self::Deposit(OpDepositReceipt { inner: Receipt { status, cumulative_gas_used, logs }, @@ -402,6 +420,7 @@ impl> TxReceipt for OpReceipt receipt.logs, Self::Deposit(receipt) => receipt.inner.logs, } @@ -442,6 +461,7 @@ impl From for OpReceipt { super::OpReceiptEnvelope::Legacy(receipt) => Self::Legacy(receipt.receipt), super::OpReceiptEnvelope::Eip2930(receipt) => Self::Eip2930(receipt.receipt), super::OpReceiptEnvelope::Eip1559(receipt) => Self::Eip1559(receipt.receipt), + super::OpReceiptEnvelope::Eip4844(receipt) => Self::Eip4844(receipt.receipt), super::OpReceiptEnvelope::Eip7702(receipt) => Self::Eip7702(receipt.receipt), super::OpReceiptEnvelope::Deposit(receipt) => Self::Deposit(OpDepositReceipt { deposit_nonce: receipt.receipt.deposit_nonce, @@ -459,6 +479,7 @@ impl From>> for OpReceiptEnvelope { OpReceipt::Legacy(receipt) => Self::Legacy(ReceiptWithBloom { receipt, logs_bloom }), OpReceipt::Eip2930(receipt) => Self::Eip2930(ReceiptWithBloom { receipt, logs_bloom }), OpReceipt::Eip1559(receipt) => Self::Eip1559(ReceiptWithBloom { receipt, logs_bloom }), + OpReceipt::Eip4844(receipt) => Self::Eip4844(ReceiptWithBloom { receipt, logs_bloom }), OpReceipt::Eip7702(receipt) => Self::Eip7702(ReceiptWithBloom { receipt, logs_bloom }), OpReceipt::Deposit(receipt) => Self::Deposit(ReceiptWithBloom { receipt, logs_bloom }), } @@ -494,6 +515,8 @@ pub(crate) mod serde_bincode_compat { Eip2930(alloy_consensus::serde_bincode_compat::Receipt<'a, alloy_primitives::Log>), /// EIP-1559 receipt Eip1559(alloy_consensus::serde_bincode_compat::Receipt<'a, alloy_primitives::Log>), + /// EIP-4844 receipt + Eip4844(alloy_consensus::serde_bincode_compat::Receipt<'a, alloy_primitives::Log>), /// EIP-7702 receipt Eip7702(alloy_consensus::serde_bincode_compat::Receipt<'a, alloy_primitives::Log>), /// Deposit receipt @@ -506,6 +529,7 @@ pub(crate) mod serde_bincode_compat { super::OpReceipt::Legacy(receipt) => Self::Legacy(receipt.into()), super::OpReceipt::Eip2930(receipt) => Self::Eip2930(receipt.into()), super::OpReceipt::Eip1559(receipt) => Self::Eip1559(receipt.into()), + super::OpReceipt::Eip4844(receipt) => Self::Eip4844(receipt.into()), super::OpReceipt::Eip7702(receipt) => Self::Eip7702(receipt.into()), super::OpReceipt::Deposit(receipt) => Self::Deposit(receipt.into()), } @@ -518,6 +542,7 @@ pub(crate) mod serde_bincode_compat { OpReceipt::Legacy(receipt) => Self::Legacy(receipt.into()), OpReceipt::Eip2930(receipt) => Self::Eip2930(receipt.into()), OpReceipt::Eip1559(receipt) => Self::Eip1559(receipt.into()), + OpReceipt::Eip4844(receipt) => Self::Eip4844(receipt.into()), OpReceipt::Eip7702(receipt) => Self::Eip7702(receipt.into()), OpReceipt::Deposit(receipt) => Self::Deposit(receipt.into()), } diff --git a/rust/op-alloy/crates/consensus/src/transaction/envelope.rs b/rust/op-alloy/crates/consensus/src/transaction/envelope.rs index afe73b2474a..9c3ccf99f04 100644 --- a/rust/op-alloy/crates/consensus/src/transaction/envelope.rs +++ b/rust/op-alloy/crates/consensus/src/transaction/envelope.rs @@ -4,7 +4,7 @@ use crate::{ }; use alloy_consensus::{ EthereumTxEnvelope, Extended, Sealable, Sealed, SignableTransaction, Signed, - TransactionEnvelope, TxEip1559, TxEip2930, TxEip7702, TxEnvelope, TxLegacy, + TransactionEnvelope, TxEip1559, TxEip2930, TxEip4844, TxEip7702, TxEnvelope, TxLegacy, error::ValueError, transaction::{TransactionInfo, TxHashRef}, }; @@ -34,6 +34,9 @@ pub enum OpTxEnvelope { /// A [`TxEip1559`] tagged with type 2. #[envelope(ty = 2)] Eip1559(Signed), + /// A [`TxEip4844`] tagged with type 3. + #[envelope(ty = 3)] + Eip4844(Signed), /// A [`TxEip7702`] tagged with type 4. #[envelope(ty = 4)] Eip7702(Signed), @@ -43,6 +46,29 @@ pub enum OpTxEnvelope { Deposit(Sealed), } +impl OpTxEnvelope { + /// Converts this envelope into an [`OpPooledTransaction`] by attaching a blob sidecar. + /// + /// Returns an error if this is not an EIP-4844 transaction. + pub fn try_into_pooled_eip4844( + self, + sidecar: alloy_eips::eip7594::BlobTransactionSidecarVariant, + ) -> Result> { + match self { + Self::Eip4844(tx) => { + let (inner, sig, hash) = tx.into_parts(); + let with_sidecar = + alloy_consensus::TxEip4844WithSidecar::from_tx_and_sidecar(inner, sidecar); + Ok(OpPooledTransaction::Eip4844(Signed::new_unchecked(with_sidecar, sig, hash))) + } + this => Err(alloy_consensus::error::ValueError::new_static( + this, + "Expected 4844 transaction", + )), + } + } +} + /// Represents an Optimism transaction envelope. /// /// Compared to Ethereum it can tell whether the transaction is a deposit. @@ -108,6 +134,12 @@ impl From> for OpTxEnvelope { } } +impl From> for OpTxEnvelope { + fn from(v: Signed) -> Self { + Self::Eip4844(v) + } +} + impl From> for OpTxEnvelope { fn from(v: Signed) -> Self { Self::Eip7702(v) @@ -136,6 +168,10 @@ impl From> for OpTxEnvelope { let tx = Signed::new_unchecked(tx_eip1559, sig, hash); Self::Eip1559(tx) } + OpTypedTransaction::Eip4844(tx_eip4844) => { + let tx = Signed::new_unchecked(tx_eip4844, sig, hash); + Self::Eip4844(tx) + } OpTypedTransaction::Eip7702(tx_eip7702) => { let tx = Signed::new_unchecked(tx_eip7702, sig, hash); Self::Eip7702(tx) @@ -185,6 +221,7 @@ impl From for alloy_rpc_types_eth::TransactionRequest { match value { OpTxEnvelope::Eip2930(tx) => tx.into_parts().0.into(), OpTxEnvelope::Eip1559(tx) => tx.into_parts().0.into(), + OpTxEnvelope::Eip4844(tx) => tx.into_parts().0.into(), OpTxEnvelope::Eip7702(tx) => tx.into_parts().0.into(), OpTxEnvelope::Deposit(tx) => tx.into_inner().into(), OpTxEnvelope::Legacy(tx) => tx.into_parts().0.into(), @@ -248,6 +285,9 @@ impl OpTxEnvelope { Self::Legacy(tx) => Ok(tx.into()), Self::Eip2930(tx) => Ok(tx.into()), Self::Eip1559(tx) => Ok(tx.into()), + Self::Eip4844(tx) => { + Err(ValueError::new(tx.into(), "EIP-4844 transactions without sidecar cannot be pooled")) + } Self::Eip7702(tx) => Ok(tx.into()), Self::Deposit(tx) => { Err(ValueError::new(tx.into(), "Deposit transactions cannot be pooled")) @@ -273,6 +313,7 @@ impl OpTxEnvelope { Self::Legacy(tx) => Ok(tx.into()), Self::Eip2930(tx) => Ok(tx.into()), Self::Eip1559(tx) => Ok(tx.into()), + Self::Eip4844(tx) => Ok(tx.into()), Self::Eip7702(tx) => Ok(tx.into()), tx @ Self::Deposit(_) => Err(ValueError::new( tx, @@ -322,6 +363,7 @@ impl OpTxEnvelope { Self::Eip1559(tx) => &mut tx.tx_mut().input, Self::Eip2930(tx) => &mut tx.tx_mut().input, Self::Legacy(tx) => &mut tx.tx_mut().input, + Self::Eip4844(tx) => &mut tx.tx_mut().input, Self::Eip7702(tx) => &mut tx.tx_mut().input, Self::Deposit(tx) => &mut tx.inner_mut().input, } @@ -397,6 +439,7 @@ impl OpTxEnvelope { Self::Legacy(tx) => Some(tx.signature()), Self::Eip2930(tx) => Some(tx.signature()), Self::Eip1559(tx) => Some(tx.signature()), + Self::Eip4844(tx) => Some(tx.signature()), Self::Eip7702(tx) => Some(tx.signature()), Self::Deposit(_) => None, } @@ -408,6 +451,7 @@ impl OpTxEnvelope { Self::Legacy(_) => OpTxType::Legacy, Self::Eip2930(_) => OpTxType::Eip2930, Self::Eip1559(_) => OpTxType::Eip1559, + Self::Eip4844(_) => OpTxType::Eip4844, Self::Eip7702(_) => OpTxType::Eip7702, Self::Deposit(_) => OpTxType::Deposit, } @@ -419,6 +463,7 @@ impl OpTxEnvelope { Self::Legacy(tx) => tx.hash(), Self::Eip1559(tx) => tx.hash(), Self::Eip2930(tx) => tx.hash(), + Self::Eip4844(tx) => tx.hash(), Self::Eip7702(tx) => tx.hash(), Self::Deposit(tx) => tx.hash_ref(), } @@ -435,6 +480,7 @@ impl OpTxEnvelope { Self::Legacy(t) => t.eip2718_encoded_length(), Self::Eip2930(t) => t.eip2718_encoded_length(), Self::Eip1559(t) => t.eip2718_encoded_length(), + Self::Eip4844(t) => t.eip2718_encoded_length(), Self::Eip7702(t) => t.eip2718_encoded_length(), Self::Deposit(t) => t.eip2718_encoded_length(), } @@ -456,6 +502,7 @@ impl alloy_consensus::transaction::SignerRecoverable for OpTxEnvelope { Self::Legacy(tx) => tx.signature_hash(), Self::Eip2930(tx) => tx.signature_hash(), Self::Eip1559(tx) => tx.signature_hash(), + Self::Eip4844(tx) => tx.signature_hash(), Self::Eip7702(tx) => tx.signature_hash(), // Optimism's Deposit transaction does not have a signature. Directly return the // `from` address. @@ -465,6 +512,7 @@ impl alloy_consensus::transaction::SignerRecoverable for OpTxEnvelope { Self::Legacy(tx) => tx.signature(), Self::Eip2930(tx) => tx.signature(), Self::Eip1559(tx) => tx.signature(), + Self::Eip4844(tx) => tx.signature(), Self::Eip7702(tx) => tx.signature(), Self::Deposit(_) => unreachable!("Deposit transactions should not be handled here"), }; @@ -478,6 +526,7 @@ impl alloy_consensus::transaction::SignerRecoverable for OpTxEnvelope { Self::Legacy(tx) => tx.signature_hash(), Self::Eip2930(tx) => tx.signature_hash(), Self::Eip1559(tx) => tx.signature_hash(), + Self::Eip4844(tx) => tx.signature_hash(), Self::Eip7702(tx) => tx.signature_hash(), // Optimism's Deposit transaction does not have a signature. Directly return the // `from` address. @@ -487,6 +536,7 @@ impl alloy_consensus::transaction::SignerRecoverable for OpTxEnvelope { Self::Legacy(tx) => tx.signature(), Self::Eip2930(tx) => tx.signature(), Self::Eip1559(tx) => tx.signature(), + Self::Eip4844(tx) => tx.signature(), Self::Eip7702(tx) => tx.signature(), Self::Deposit(_) => unreachable!("Deposit transactions should not be handled here"), }; @@ -507,6 +557,9 @@ impl alloy_consensus::transaction::SignerRecoverable for OpTxEnvelope { Self::Eip1559(tx) => { alloy_consensus::transaction::SignerRecoverable::recover_unchecked_with_buf(tx, buf) } + Self::Eip4844(tx) => { + alloy_consensus::transaction::SignerRecoverable::recover_unchecked_with_buf(tx, buf) + } Self::Eip7702(tx) => { alloy_consensus::transaction::SignerRecoverable::recover_unchecked_with_buf(tx, buf) } @@ -551,6 +604,13 @@ pub mod serde_bincode_compat { /// Borrowed EIP-1559 transaction data. transaction: TxEip1559<'a>, }, + /// EIP-4844 variant. + Eip4844 { + /// Transaction signature. + signature: Signature, + /// EIP-4844 transaction data. + transaction: alloy_consensus::TxEip4844, + }, /// EIP-7702 variant. Eip7702 { /// Transaction signature. @@ -582,6 +642,10 @@ pub mod serde_bincode_compat { signature: *signed_1559.signature(), transaction: signed_1559.tx().into(), }, + super::OpTxEnvelope::Eip4844(signed_4844) => Self::Eip4844 { + signature: *signed_4844.signature(), + transaction: signed_4844.tx().clone(), + }, super::OpTxEnvelope::Eip7702(signed_7702) => Self::Eip7702 { signature: *signed_7702.signature(), transaction: signed_7702.tx().into(), @@ -606,6 +670,9 @@ pub mod serde_bincode_compat { OpTxEnvelope::Eip1559 { signature, transaction } => { Self::Eip1559(Signed::new_unhashed(transaction.into(), signature)) } + OpTxEnvelope::Eip4844 { signature, transaction } => { + Self::Eip4844(Signed::new_unhashed(transaction, signature)) + } OpTxEnvelope::Eip7702 { signature, transaction } => { Self::Eip7702(Signed::new_unhashed(transaction.into(), signature)) } diff --git a/rust/op-alloy/crates/consensus/src/transaction/pooled.rs b/rust/op-alloy/crates/consensus/src/transaction/pooled.rs index 2a74073057e..d7ebf36e9e3 100644 --- a/rust/op-alloy/crates/consensus/src/transaction/pooled.rs +++ b/rust/op-alloy/crates/consensus/src/transaction/pooled.rs @@ -3,8 +3,8 @@ use crate::OpTxEnvelope; use alloy_consensus::{ - Extended, SignableTransaction, Signed, TransactionEnvelope, TxEip7702, TxEnvelope, - error::ValueError, + Extended, SignableTransaction, Signed, TransactionEnvelope, TxEip4844WithSidecar, TxEip7702, + TxEnvelope, error::ValueError, transaction::{TxEip1559, TxEip2930, TxHashRef, TxLegacy}, }; use alloy_eips::eip2718::Encodable2718; @@ -13,7 +13,7 @@ use core::hash::Hash; /// All possible transactions that can be included in a response to `GetPooledTransactions`. /// A response to `GetPooledTransactions`. This can include a typed signed transaction, but cannot -/// include a deposit transaction or EIP-4844 transaction. +/// include a deposit transaction. /// /// The difference between this and the [`OpTxEnvelope`] is that this type does not have the deposit /// transaction variant, which is not expected to be pooled. @@ -29,6 +29,9 @@ pub enum OpPooledTransaction { /// A [`TxEip1559`] transaction tagged with type 2. #[envelope(ty = 2)] Eip1559(Signed), + /// A [`TxEip4844WithSidecar`] transaction tagged with type 3. + #[envelope(ty = 3)] + Eip4844(Signed), /// A [`TxEip7702`] transaction tagged with type 4. #[envelope(ty = 4)] Eip7702(Signed), @@ -42,6 +45,7 @@ impl OpPooledTransaction { Self::Legacy(tx) => tx.signature_hash(), Self::Eip2930(tx) => tx.signature_hash(), Self::Eip1559(tx) => tx.signature_hash(), + Self::Eip4844(tx) => tx.signature_hash(), Self::Eip7702(tx) => tx.signature_hash(), } } @@ -52,16 +56,18 @@ impl OpPooledTransaction { Self::Legacy(tx) => tx.hash(), Self::Eip2930(tx) => tx.hash(), Self::Eip1559(tx) => tx.hash(), + Self::Eip4844(tx) => tx.hash(), Self::Eip7702(tx) => tx.hash(), } } /// Returns the signature of the transaction. - pub const fn signature(&self) -> &Signature { + pub fn signature(&self) -> &Signature { match self { Self::Legacy(tx) => tx.signature(), Self::Eip2930(tx) => tx.signature(), Self::Eip1559(tx) => tx.signature(), + Self::Eip4844(tx) => tx.signature(), Self::Eip7702(tx) => tx.signature(), } } @@ -73,6 +79,7 @@ impl OpPooledTransaction { Self::Legacy(tx) => tx.tx().encode_for_signing(out), Self::Eip2930(tx) => tx.tx().encode_for_signing(out), Self::Eip1559(tx) => tx.tx().encode_for_signing(out), + Self::Eip4844(tx) => tx.tx().encode_for_signing(out), Self::Eip7702(tx) => tx.tx().encode_for_signing(out), } } @@ -83,6 +90,10 @@ impl OpPooledTransaction { Self::Legacy(tx) => tx.into(), Self::Eip2930(tx) => tx.into(), Self::Eip1559(tx) => tx.into(), + Self::Eip4844(tx) => { + let (inner, sig, hash) = tx.into_parts(); + Signed::new_unchecked(inner.tx, sig, hash).into() + } Self::Eip7702(tx) => tx.into(), } } @@ -93,6 +104,10 @@ impl OpPooledTransaction { Self::Legacy(tx) => tx.into(), Self::Eip2930(tx) => tx.into(), Self::Eip1559(tx) => tx.into(), + Self::Eip4844(tx) => { + let (inner, sig, hash) = tx.into_parts(); + OpTxEnvelope::Eip4844(Signed::new_unchecked(inner.tx, sig, hash)) + } Self::Eip7702(tx) => tx.into(), } } @@ -148,6 +163,12 @@ impl From> for OpPooledTransaction { } } +impl From> for OpPooledTransaction { + fn from(v: Signed) -> Self { + Self::Eip4844(v) + } +} + impl From> for OpPooledTransaction { fn from(v: Signed) -> Self { Self::Eip7702(v) @@ -160,6 +181,7 @@ impl From for alloy_consensus::transaction::PooledTransacti OpPooledTransaction::Legacy(tx) => tx.into(), OpPooledTransaction::Eip2930(tx) => tx.into(), OpPooledTransaction::Eip1559(tx) => tx.into(), + OpPooledTransaction::Eip4844(tx) => tx.into(), OpPooledTransaction::Eip7702(tx) => tx.into(), } } @@ -204,6 +226,9 @@ impl alloy_consensus::transaction::SignerRecoverable for OpPooledTransaction { Self::Eip1559(tx) => { alloy_consensus::transaction::SignerRecoverable::recover_unchecked_with_buf(tx, buf) } + Self::Eip4844(tx) => { + alloy_consensus::transaction::SignerRecoverable::recover_unchecked_with_buf(tx, buf) + } Self::Eip7702(tx) => { alloy_consensus::transaction::SignerRecoverable::recover_unchecked_with_buf(tx, buf) } diff --git a/rust/op-alloy/crates/consensus/src/transaction/tx_type.rs b/rust/op-alloy/crates/consensus/src/transaction/tx_type.rs index fb6d864b662..fe1b06ce92a 100644 --- a/rust/op-alloy/crates/consensus/src/transaction/tx_type.rs +++ b/rust/op-alloy/crates/consensus/src/transaction/tx_type.rs @@ -19,6 +19,7 @@ impl Display for OpTxType { Self::Legacy => write!(f, "legacy"), Self::Eip2930 => write!(f, "eip2930"), Self::Eip1559 => write!(f, "eip1559"), + Self::Eip4844 => write!(f, "eip4844"), Self::Eip7702 => write!(f, "eip7702"), Self::Deposit => write!(f, "deposit"), } @@ -27,8 +28,8 @@ impl Display for OpTxType { impl OpTxType { /// List of all variants. - pub const ALL: [Self; 5] = - [Self::Legacy, Self::Eip2930, Self::Eip1559, Self::Eip7702, Self::Deposit]; + pub const ALL: [Self; 6] = + [Self::Legacy, Self::Eip2930, Self::Eip1559, Self::Eip4844, Self::Eip7702, Self::Deposit]; /// Returns `true` if the type is [`OpTxType::Deposit`]. pub const fn is_deposit(&self) -> bool { @@ -44,11 +45,12 @@ mod tests { #[test] fn test_all_tx_types() { - assert_eq!(OpTxType::ALL.len(), 5); + assert_eq!(OpTxType::ALL.len(), 6); let all = vec![ OpTxType::Legacy, OpTxType::Eip2930, OpTxType::Eip1559, + OpTxType::Eip4844, OpTxType::Eip7702, OpTxType::Deposit, ]; diff --git a/rust/op-alloy/crates/consensus/src/transaction/typed.rs b/rust/op-alloy/crates/consensus/src/transaction/typed.rs index 4cf2feaf6e5..1eaf714df4a 100644 --- a/rust/op-alloy/crates/consensus/src/transaction/typed.rs +++ b/rust/op-alloy/crates/consensus/src/transaction/typed.rs @@ -43,6 +43,7 @@ impl From for OpTypedTransaction { OpTxEnvelope::Legacy(tx) => Self::Legacy(tx.strip_signature()), OpTxEnvelope::Eip2930(tx) => Self::Eip2930(tx.strip_signature()), OpTxEnvelope::Eip1559(tx) => Self::Eip1559(tx.strip_signature()), + OpTxEnvelope::Eip4844(tx) => Self::Eip4844(tx.strip_signature()), OpTxEnvelope::Eip7702(tx) => Self::Eip7702(tx.strip_signature()), OpTxEnvelope::Deposit(tx) => Self::Deposit(tx.into_inner()), } @@ -64,6 +65,7 @@ impl From for alloy_rpc_types_eth::TransactionRequest { OpTypedTransaction::Legacy(tx) => tx.into(), OpTypedTransaction::Eip2930(tx) => tx.into(), OpTypedTransaction::Eip1559(tx) => tx.into(), + OpTypedTransaction::Eip4844(tx) => tx.into(), OpTypedTransaction::Eip7702(tx) => tx.into(), OpTypedTransaction::Deposit(tx) => tx.into(), } @@ -77,6 +79,7 @@ impl OpTypedTransaction { Self::Legacy(_) => OpTxType::Legacy, Self::Eip2930(_) => OpTxType::Eip2930, Self::Eip1559(_) => OpTxType::Eip1559, + Self::Eip4844(_) => OpTxType::Eip4844, Self::Eip7702(_) => OpTxType::Eip7702, Self::Deposit(_) => OpTxType::Deposit, } @@ -90,6 +93,7 @@ impl OpTypedTransaction { Self::Legacy(tx) => Some(tx.signature_hash()), Self::Eip2930(tx) => Some(tx.signature_hash()), Self::Eip1559(tx) => Some(tx.signature_hash()), + Self::Eip4844(tx) => Some(tx.signature_hash()), Self::Eip7702(tx) => Some(tx.signature_hash()), Self::Deposit(_) => None, } @@ -140,6 +144,7 @@ impl OpTypedTransaction { Self::Legacy(tx) => tx.tx_hash(signature), Self::Eip2930(tx) => tx.tx_hash(signature), Self::Eip1559(tx) => tx.tx_hash(signature), + Self::Eip4844(tx) => tx.tx_hash(signature), Self::Eip7702(tx) => tx.tx_hash(signature), Self::Deposit(tx) => tx.tx_hash(), } @@ -171,6 +176,10 @@ impl OpTypedTransaction { Self::Legacy(tx) => Ok(tx.into()), Self::Eip2930(tx) => Ok(tx.into()), Self::Eip1559(tx) => Ok(tx.into()), + tx @ Self::Eip4844(_) => Err(ValueError::new( + tx, + "EIP-4844 transactions cannot be converted to ethereum typed transaction without blob data", + )), Self::Eip7702(tx) => Ok(tx.into()), tx @ Self::Deposit(_) => Err(ValueError::new( tx, @@ -186,6 +195,7 @@ impl RlpEcdsaEncodableTx for OpTypedTransaction { Self::Legacy(tx) => tx.rlp_encoded_fields_length(), Self::Eip2930(tx) => tx.rlp_encoded_fields_length(), Self::Eip1559(tx) => tx.rlp_encoded_fields_length(), + Self::Eip4844(tx) => tx.rlp_encoded_fields_length(), Self::Eip7702(tx) => tx.rlp_encoded_fields_length(), Self::Deposit(tx) => tx.rlp_encoded_fields_length(), } @@ -196,6 +206,7 @@ impl RlpEcdsaEncodableTx for OpTypedTransaction { Self::Legacy(tx) => tx.rlp_encode_fields(out), Self::Eip2930(tx) => tx.rlp_encode_fields(out), Self::Eip1559(tx) => tx.rlp_encode_fields(out), + Self::Eip4844(tx) => tx.rlp_encode_fields(out), Self::Eip7702(tx) => tx.rlp_encode_fields(out), Self::Deposit(tx) => tx.rlp_encode_fields(out), } @@ -206,6 +217,7 @@ impl RlpEcdsaEncodableTx for OpTypedTransaction { Self::Legacy(tx) => tx.eip2718_encode_with_type(signature, tx.ty(), out), Self::Eip2930(tx) => tx.eip2718_encode_with_type(signature, tx.ty(), out), Self::Eip1559(tx) => tx.eip2718_encode_with_type(signature, tx.ty(), out), + Self::Eip4844(tx) => tx.eip2718_encode_with_type(signature, tx.ty(), out), Self::Eip7702(tx) => tx.eip2718_encode_with_type(signature, tx.ty(), out), Self::Deposit(tx) => tx.encode_2718(out), } @@ -216,6 +228,7 @@ impl RlpEcdsaEncodableTx for OpTypedTransaction { Self::Legacy(tx) => tx.eip2718_encode(signature, out), Self::Eip2930(tx) => tx.eip2718_encode(signature, out), Self::Eip1559(tx) => tx.eip2718_encode(signature, out), + Self::Eip4844(tx) => tx.eip2718_encode(signature, out), Self::Eip7702(tx) => tx.eip2718_encode(signature, out), Self::Deposit(tx) => tx.encode_2718(out), } @@ -226,6 +239,7 @@ impl RlpEcdsaEncodableTx for OpTypedTransaction { Self::Legacy(tx) => tx.network_encode_with_type(signature, tx.ty(), out), Self::Eip2930(tx) => tx.network_encode_with_type(signature, tx.ty(), out), Self::Eip1559(tx) => tx.network_encode_with_type(signature, tx.ty(), out), + Self::Eip4844(tx) => tx.network_encode_with_type(signature, tx.ty(), out), Self::Eip7702(tx) => tx.network_encode_with_type(signature, tx.ty(), out), Self::Deposit(tx) => tx.network_encode(out), } @@ -236,6 +250,7 @@ impl RlpEcdsaEncodableTx for OpTypedTransaction { Self::Legacy(tx) => tx.network_encode(signature, out), Self::Eip2930(tx) => tx.network_encode(signature, out), Self::Eip1559(tx) => tx.network_encode(signature, out), + Self::Eip4844(tx) => tx.network_encode(signature, out), Self::Eip7702(tx) => tx.network_encode(signature, out), Self::Deposit(tx) => tx.network_encode(out), } @@ -246,6 +261,7 @@ impl RlpEcdsaEncodableTx for OpTypedTransaction { Self::Legacy(tx) => tx.tx_hash_with_type(signature, tx.ty()), Self::Eip2930(tx) => tx.tx_hash_with_type(signature, tx.ty()), Self::Eip1559(tx) => tx.tx_hash_with_type(signature, tx.ty()), + Self::Eip4844(tx) => tx.tx_hash_with_type(signature, tx.ty()), Self::Eip7702(tx) => tx.tx_hash_with_type(signature, tx.ty()), Self::Deposit(tx) => tx.tx_hash(), } @@ -256,6 +272,7 @@ impl RlpEcdsaEncodableTx for OpTypedTransaction { Self::Legacy(tx) => tx.tx_hash(signature), Self::Eip2930(tx) => tx.tx_hash(signature), Self::Eip1559(tx) => tx.tx_hash(signature), + Self::Eip4844(tx) => tx.tx_hash(signature), Self::Eip7702(tx) => tx.tx_hash(signature), Self::Deposit(tx) => tx.tx_hash(), } @@ -268,6 +285,7 @@ impl SignableTransaction for OpTypedTransaction { Self::Legacy(tx) => tx.set_chain_id(chain_id), Self::Eip2930(tx) => tx.set_chain_id(chain_id), Self::Eip1559(tx) => tx.set_chain_id(chain_id), + Self::Eip4844(tx) => tx.set_chain_id(chain_id), Self::Eip7702(tx) => tx.set_chain_id(chain_id), Self::Deposit(_) => {} } @@ -278,6 +296,7 @@ impl SignableTransaction for OpTypedTransaction { Self::Legacy(tx) => tx.encode_for_signing(out), Self::Eip2930(tx) => tx.encode_for_signing(out), Self::Eip1559(tx) => tx.encode_for_signing(out), + Self::Eip4844(tx) => tx.encode_for_signing(out), Self::Eip7702(tx) => tx.encode_for_signing(out), Self::Deposit(_) => {} } @@ -288,6 +307,7 @@ impl SignableTransaction for OpTypedTransaction { Self::Legacy(tx) => tx.payload_len_for_signature(), Self::Eip2930(tx) => tx.payload_len_for_signature(), Self::Eip1559(tx) => tx.payload_len_for_signature(), + Self::Eip4844(tx) => tx.payload_len_for_signature(), Self::Eip7702(tx) => tx.payload_len_for_signature(), Self::Deposit(_) => 0, } diff --git a/rust/op-alloy/crates/network/src/lib.rs b/rust/op-alloy/crates/network/src/lib.rs index 03d72dc31d3..db3540cf3c1 100644 --- a/rust/op-alloy/crates/network/src/lib.rs +++ b/rust/op-alloy/crates/network/src/lib.rs @@ -221,6 +221,7 @@ impl NetworkWallet for EthereumWallet { OpTypedTransaction::Legacy(tx) => TypedTransaction::Legacy(tx), OpTypedTransaction::Eip2930(tx) => TypedTransaction::Eip2930(tx), OpTypedTransaction::Eip1559(tx) => TypedTransaction::Eip1559(tx), + OpTypedTransaction::Eip4844(tx) => TypedTransaction::Eip4844(alloy_consensus::TxEip4844Variant::TxEip4844(tx)), OpTypedTransaction::Eip7702(tx) => TypedTransaction::Eip7702(tx), OpTypedTransaction::Deposit(_) => { return Err(alloy_signer::Error::other("not implemented for deposit tx")); diff --git a/rust/op-alloy/crates/rpc-types-engine/src/payload/mod.rs b/rust/op-alloy/crates/rpc-types-engine/src/payload/mod.rs index 613251ef6b4..2a4be7a630e 100644 --- a/rust/op-alloy/crates/rpc-types-engine/src/payload/mod.rs +++ b/rust/op-alloy/crates/rpc-types-engine/src/payload/mod.rs @@ -617,9 +617,8 @@ impl OpExecutionPayload { Self::V3(payload) => payload.try_into_block_with(f)?, Self::V4(payload) => payload.try_into_block_with(f)?, }; - if block.body.has_eip4844_transactions() { - return Err(OpPayloadError::BlobTransaction); - } + // Note: EIP-4844 blob transactions are allowed when L2 blob is active. + // The txpool validator gates blob tx acceptance based on l2BlobTime. Ok(block) } diff --git a/rust/op-alloy/crates/rpc-types/src/receipt.rs b/rust/op-alloy/crates/rpc-types/src/receipt.rs index 5d7be127446..24441aea3f0 100644 --- a/rust/op-alloy/crates/rpc-types/src/receipt.rs +++ b/rust/op-alloy/crates/rpc-types/src/receipt.rs @@ -228,6 +228,7 @@ impl From for OpReceiptEnvelope { OpReceiptEnvelope::Legacy(receipt) => Self::Legacy(convert_standard_receipt(receipt)), OpReceiptEnvelope::Eip2930(receipt) => Self::Eip2930(convert_standard_receipt(receipt)), OpReceiptEnvelope::Eip1559(receipt) => Self::Eip1559(convert_standard_receipt(receipt)), + OpReceiptEnvelope::Eip4844(receipt) => Self::Eip4844(convert_standard_receipt(receipt)), OpReceiptEnvelope::Eip7702(receipt) => Self::Eip7702(convert_standard_receipt(receipt)), OpReceiptEnvelope::Deposit(OpDepositReceiptWithBloom { logs_bloom, receipt }) => { let consensus_logs = receipt.inner.logs.into_iter().map(|log| log.inner).collect(); diff --git a/rust/op-alloy/crates/rpc-types/src/transaction/request.rs b/rust/op-alloy/crates/rpc-types/src/transaction/request.rs index bf621ca5a40..a9eae8e4164 100644 --- a/rust/op-alloy/crates/rpc-types/src/transaction/request.rs +++ b/rust/op-alloy/crates/rpc-types/src/transaction/request.rs @@ -179,6 +179,7 @@ impl From for OpTransactionRequest { OpTypedTransaction::Legacy(tx) => Self(tx.into()), OpTypedTransaction::Eip2930(tx) => Self(tx.into()), OpTypedTransaction::Eip1559(tx) => Self(tx.into()), + OpTypedTransaction::Eip4844(tx) => Self(tx.into()), OpTypedTransaction::Eip7702(tx) => Self(tx.into()), OpTypedTransaction::Deposit(tx) => tx.into(), } diff --git a/rust/op-reth/crates/chainspec/src/base.rs b/rust/op-reth/crates/chainspec/src/base.rs index a9370752e33..86a5eb58c59 100644 --- a/rust/op-reth/crates/chainspec/src/base.rs +++ b/rust/op-reth/crates/chainspec/src/base.rs @@ -37,6 +37,7 @@ pub static BASE_MAINNET: LazyLock> = LazyLock::new(|| { }, sgt_activation_timestamp: None, sgt_is_native_backed: true, + l2_blob_activation_timestamp: None, } .into() }); diff --git a/rust/op-reth/crates/chainspec/src/base_sepolia.rs b/rust/op-reth/crates/chainspec/src/base_sepolia.rs index 672cfc8970c..628427b9f81 100644 --- a/rust/op-reth/crates/chainspec/src/base_sepolia.rs +++ b/rust/op-reth/crates/chainspec/src/base_sepolia.rs @@ -38,6 +38,7 @@ pub static BASE_SEPOLIA: LazyLock> = LazyLock::new(|| { }, sgt_activation_timestamp: None, sgt_is_native_backed: true, + l2_blob_activation_timestamp: None, } .into() }); diff --git a/rust/op-reth/crates/chainspec/src/basefee.rs b/rust/op-reth/crates/chainspec/src/basefee.rs index d4880abffa8..c79e4c29c6f 100644 --- a/rust/op-reth/crates/chainspec/src/basefee.rs +++ b/rust/op-reth/crates/chainspec/src/basefee.rs @@ -102,6 +102,7 @@ mod tests { }, sgt_activation_timestamp: None, sgt_is_native_backed: true, + l2_blob_activation_timestamp: None, }) } diff --git a/rust/op-reth/crates/chainspec/src/dev.rs b/rust/op-reth/crates/chainspec/src/dev.rs index 34c2df39083..1caa00c74db 100644 --- a/rust/op-reth/crates/chainspec/src/dev.rs +++ b/rust/op-reth/crates/chainspec/src/dev.rs @@ -31,6 +31,7 @@ pub static OP_DEV: LazyLock> = LazyLock::new(|| { }, sgt_activation_timestamp: None, sgt_is_native_backed: true, + l2_blob_activation_timestamp: None, } .into() }); diff --git a/rust/op-reth/crates/chainspec/src/lib.rs b/rust/op-reth/crates/chainspec/src/lib.rs index de52b457fc4..047a1d3d024 100644 --- a/rust/op-reth/crates/chainspec/src/lib.rs +++ b/rust/op-reth/crates/chainspec/src/lib.rs @@ -218,13 +218,14 @@ impl OpChainSpecBuilder { inner.genesis_header = SealedHeader::seal_slow(make_op_genesis_header(&inner.genesis, &inner.hardforks)); - let (sgt_activation_timestamp, sgt_is_native_backed) = - parse_sgt_config(&inner.genesis); + let (sgt_activation_timestamp, sgt_is_native_backed, l2_blob_activation_timestamp) = + parse_optimism_genesis_config(&inner.genesis); OpChainSpec { inner, sgt_activation_timestamp, sgt_is_native_backed, + l2_blob_activation_timestamp, } } } @@ -239,30 +240,41 @@ pub struct OpChainSpec { pub sgt_activation_timestamp: Option, /// Whether SGT is backed by native (from config.optimism.isSoulBackedByNative) pub sgt_is_native_backed: bool, + /// L2 Blob activation timestamp from genesis config.optimism.l2BlobTime + /// Enables EIP-4844 blob transactions on L2. + pub l2_blob_activation_timestamp: Option, } -/// Parse SGT config from genesis extra fields (config.optimism.soulGasTokenTime / isSoulBackedByNative). -fn parse_sgt_config(genesis: &Genesis) -> (Option, bool) { +/// Parse custom OP config from genesis extra fields (config.optimism.*). +/// +/// Returns (sgt_activation_timestamp, sgt_is_native_backed, l2_blob_activation_timestamp). +fn parse_optimism_genesis_config(genesis: &Genesis) -> (Option, bool, Option) { genesis .config .extra_fields .get("optimism") .and_then(|v| v.as_object()) .map(|obj| { - let timestamp = obj.get("soulGasTokenTime").and_then(|v| v.as_u64()); + let sgt_timestamp = obj.get("soulGasTokenTime").and_then(|v| v.as_u64()); let native_backed = obj .get("isSoulBackedByNative") .and_then(|v| v.as_bool()) .unwrap_or(true); - (timestamp, native_backed) + let l2_blob_timestamp = obj.get("l2BlobTime").and_then(|v| v.as_u64()); + (sgt_timestamp, native_backed, l2_blob_timestamp) }) - .unwrap_or((None, true)) + .unwrap_or((None, true, None)) } impl OpChainSpec { /// Constructs a new [`OpChainSpec`] from the given inner [`ChainSpec`]. pub fn new(inner: ChainSpec) -> Self { - Self { inner, sgt_activation_timestamp: None, sgt_is_native_backed: true } + Self { + inner, + sgt_activation_timestamp: None, + sgt_is_native_backed: true, + l2_blob_activation_timestamp: None, + } } /// Converts the given [`Genesis`] into a [`OpChainSpec`]. @@ -384,6 +396,14 @@ impl OpHardforks for OpChainSpec { fn is_sgt_native_backed(&self) -> bool { self.sgt_is_native_backed } + + fn is_l2_blob_active_at_timestamp(&self, timestamp: u64) -> bool { + self.is_cancun_active_at_timestamp(timestamp) + && self + .l2_blob_activation_timestamp + .map(|activation| timestamp >= activation) + .unwrap_or(false) + } } impl From for OpChainSpec { @@ -471,8 +491,9 @@ impl From for OpChainSpec { let hardforks = ChainHardforks::new(ordered_hardforks); let genesis_header = SealedHeader::seal_slow(make_op_genesis_header(&genesis, &hardforks)); - // Parse SGT config from optimism extra field (same as op-geth genesis format) - let (sgt_activation_timestamp, sgt_is_native_backed) = parse_sgt_config(&genesis); + // Parse custom config from optimism extra field (same as op-geth genesis format) + let (sgt_activation_timestamp, sgt_is_native_backed, l2_blob_activation_timestamp) = + parse_optimism_genesis_config(&genesis); Self { inner: ChainSpec { @@ -488,15 +509,16 @@ impl From for OpChainSpec { }, sgt_activation_timestamp, sgt_is_native_backed, + l2_blob_activation_timestamp, } } } impl From for OpChainSpec { fn from(value: ChainSpec) -> Self { - let (sgt_activation_timestamp, sgt_is_native_backed) = - parse_sgt_config(&value.genesis); - Self { inner: value, sgt_activation_timestamp, sgt_is_native_backed } + let (sgt_activation_timestamp, sgt_is_native_backed, l2_blob_activation_timestamp) = + parse_optimism_genesis_config(&value.genesis); + Self { inner: value, sgt_activation_timestamp, sgt_is_native_backed, l2_blob_activation_timestamp } } } diff --git a/rust/op-reth/crates/chainspec/src/op.rs b/rust/op-reth/crates/chainspec/src/op.rs index 8b3b190f4f8..2d9421ee47a 100644 --- a/rust/op-reth/crates/chainspec/src/op.rs +++ b/rust/op-reth/crates/chainspec/src/op.rs @@ -38,6 +38,7 @@ pub static OP_MAINNET: LazyLock> = LazyLock::new(|| { }, sgt_activation_timestamp: None, sgt_is_native_backed: true, + l2_blob_activation_timestamp: None, } .into() }); diff --git a/rust/op-reth/crates/chainspec/src/op_sepolia.rs b/rust/op-reth/crates/chainspec/src/op_sepolia.rs index 5340330506b..fca4b56f2d0 100644 --- a/rust/op-reth/crates/chainspec/src/op_sepolia.rs +++ b/rust/op-reth/crates/chainspec/src/op_sepolia.rs @@ -36,6 +36,7 @@ pub static OP_SEPOLIA: LazyLock> = LazyLock::new(|| { }, sgt_activation_timestamp: None, sgt_is_native_backed: true, + l2_blob_activation_timestamp: None, } .into() }); diff --git a/rust/op-reth/crates/cli/src/ovm_file_codec.rs b/rust/op-reth/crates/cli/src/ovm_file_codec.rs index 9d4704f0a6a..f473bc659e8 100644 --- a/rust/op-reth/crates/cli/src/ovm_file_codec.rs +++ b/rust/op-reth/crates/cli/src/ovm_file_codec.rs @@ -244,6 +244,9 @@ impl Encodable2718 for OvmTransactionSigned { OpTypedTransaction::Eip1559(dynamic_fee_tx) => { dynamic_fee_tx.eip2718_encoded_length(&self.signature) } + OpTypedTransaction::Eip4844(blob_tx) => { + blob_tx.eip2718_encoded_length(&self.signature) + } OpTypedTransaction::Eip7702(set_code_tx) => { set_code_tx.eip2718_encoded_length(&self.signature) } @@ -268,6 +271,11 @@ impl Decodable2718 for OvmTransactionSigned { let (tx, signature, hash) = TxEip1559::rlp_decode_signed(buf)?.into_parts(); Ok(Self { transaction: OpTypedTransaction::Eip1559(tx), signature, hash }) } + OpTxType::Eip4844 => { + let (tx, signature, hash) = + alloy_consensus::TxEip4844::rlp_decode_signed(buf)?.into_parts(); + Ok(Self { transaction: OpTypedTransaction::Eip4844(tx), signature, hash }) + } OpTxType::Eip7702 => { let (tx, signature, hash) = TxEip7702::rlp_decode_signed(buf)?.into_parts(); Ok(Self { transaction: OpTypedTransaction::Eip7702(tx), signature, hash }) diff --git a/rust/op-reth/crates/cli/src/receipt_file_codec.rs b/rust/op-reth/crates/cli/src/receipt_file_codec.rs index 8cbb89abe09..fe1315892ca 100644 --- a/rust/op-reth/crates/cli/src/receipt_file_codec.rs +++ b/rust/op-reth/crates/cli/src/receipt_file_codec.rs @@ -108,6 +108,7 @@ impl TryFrom for OpReceipt { OpTxType::Legacy => Ok(Self::Legacy(receipt)), OpTxType::Eip2930 => Ok(Self::Eip2930(receipt)), OpTxType::Eip1559 => Ok(Self::Eip1559(receipt)), + OpTxType::Eip4844 => Ok(Self::Eip4844(receipt)), OpTxType::Eip7702 => Ok(Self::Eip7702(receipt)), OpTxType::Deposit => Ok(Self::Deposit(OpDepositReceipt { inner: receipt, diff --git a/rust/op-reth/crates/consensus/src/lib.rs b/rust/op-reth/crates/consensus/src/lib.rs index 7cf199f3099..11bb11f4c4a 100644 --- a/rust/op-reth/crates/consensus/src/lib.rs +++ b/rust/op-reth/crates/consensus/src/lib.rs @@ -129,7 +129,10 @@ where // In Jovian, the blob gas used computation has changed. We are moving the blob base fee // validation to post-execution since the DA footprint calculation is stateful. // Pre-execution we only validate that the blob gas used is present in the header. - if self.chain_spec.is_jovian_active_at_timestamp(block.timestamp()) { + // For L2 Blob, blob gas is validated post-execution (actual blob gas from transactions). + if self.chain_spec.is_l2_blob_active_at_timestamp(block.timestamp()) || + self.chain_spec.is_jovian_active_at_timestamp(block.timestamp()) + { block.blob_gas_used().ok_or(ConsensusError::BlobGasUsedMissing)?; } else if self.chain_spec.is_ecotone_active_at_timestamp(block.timestamp()) { validate_cancun_gas(block)?; @@ -206,11 +209,14 @@ where // In the op-stack, the excess blob gas is always 0 for all blocks after ecotone. // The blob gas used and the excess blob gas should both be set after ecotone. // After Jovian, the blob gas used contains the current DA footprint. + // After L2 Blob activation, excess_blob_gas is calculated using the EIP-4844 formula + // and blob_gas_used reflects actual blob gas consumption. if self.chain_spec.is_ecotone_active_at_timestamp(header.timestamp()) { let blob_gas_used = header.blob_gas_used().ok_or(ConsensusError::BlobGasUsedMissing)?; - // Before Jovian and after ecotone, the blob gas used should be 0. + // Before Jovian/L2Blob and after ecotone, the blob gas used should be 0. if !self.chain_spec.is_jovian_active_at_timestamp(header.timestamp()) && + !self.chain_spec.is_l2_blob_active_at_timestamp(header.timestamp()) && blob_gas_used != 0 { return Err(ConsensusError::BlobGasUsedDiff(GotExpected { @@ -221,7 +227,11 @@ where let excess_blob_gas = header.excess_blob_gas().ok_or(ConsensusError::ExcessBlobGasMissing)?; - if excess_blob_gas != 0 { + // When L2 Blob is active, excess_blob_gas is calculated from parent using + // the EIP-4844 formula (matching op-geth), so it may be non-zero. + if !self.chain_spec.is_l2_blob_active_at_timestamp(header.timestamp()) && + excess_blob_gas != 0 + { return Err(ConsensusError::ExcessBlobGasDiff { diff: GotExpected { got: excess_blob_gas, expected: 0 }, parent_excess_blob_gas: parent.excess_blob_gas().unwrap_or(0), diff --git a/rust/op-reth/crates/consensus/src/validation/mod.rs b/rust/op-reth/crates/consensus/src/validation/mod.rs index 7025066adc2..6c7aaf40bf2 100644 --- a/rust/op-reth/crates/consensus/src/validation/mod.rs +++ b/rust/op-reth/crates/consensus/src/validation/mod.rs @@ -94,8 +94,11 @@ pub fn validate_block_post_execution( result: &BlockExecutionResult, receipt_root_bloom: Option<(B256, Bloom)>, ) -> Result<(), ConsensusError> { - // Validate that the blob gas used is present and correctly computed if Jovian is active. - if chain_spec.is_jovian_active_at_timestamp(header.timestamp()) { + // Validate that the blob gas used is present and correctly computed if Jovian or L2 Blob is + // active. + if chain_spec.is_jovian_active_at_timestamp(header.timestamp()) + || chain_spec.is_l2_blob_active_at_timestamp(header.timestamp()) + { let computed_blob_gas_used = result.blob_gas_used; let header_blob_gas_used = header.blob_gas_used().ok_or(ConsensusError::BlobGasUsedMissing)?; @@ -239,6 +242,7 @@ mod tests { }, sgt_activation_timestamp: None, sgt_is_native_backed: true, + l2_blob_activation_timestamp: None, }) } diff --git a/rust/op-reth/crates/evm/src/build.rs b/rust/op-reth/crates/evm/src/build.rs index 336967499d2..6128b3730b4 100644 --- a/rust/op-reth/crates/evm/src/build.rs +++ b/rust/op-reth/crates/evm/src/build.rs @@ -1,7 +1,7 @@ use alloc::sync::Arc; use alloy_consensus::{ - Block, BlockBody, EMPTY_OMMER_ROOT_HASH, Header, TxReceipt, constants::EMPTY_WITHDRAWALS, - proofs, + Block, BlockBody, BlockHeader, EMPTY_OMMER_ROOT_HASH, Header, TxReceipt, + constants::EMPTY_WITHDRAWALS, proofs, }; use alloy_eips::{eip7685::EMPTY_REQUESTS_HASH, merge::BEACON_NONCE}; use alloy_evm::block::BlockExecutorFactory; @@ -11,6 +11,7 @@ use reth_evm::execute::{BlockAssembler, BlockAssemblerInput}; use reth_execution_errors::BlockExecutionError; use reth_execution_types::BlockExecutionResult; use reth_optimism_consensus::{calculate_receipt_root_no_memo_optimism, isthmus}; +use reth_chainspec::EthChainSpec; use reth_optimism_forks::OpHardforks; use reth_optimism_primitives::DepositReceipt; use reth_primitives_traits::{Receipt, SignedTransaction}; @@ -29,7 +30,7 @@ impl OpBlockAssembler { } } -impl OpBlockAssembler { +impl OpBlockAssembler { /// Builds a block for `input` without any bounds on header `H`. pub fn assemble_block< F: for<'a> BlockExecutorFactory< @@ -37,7 +38,7 @@ impl OpBlockAssembler { Transaction: SignedTransaction, Receipt: Receipt + DepositReceipt, >, - H, + H: BlockHeader, >( &self, input: BlockAssemblerInput<'_, '_, F, H>, @@ -45,6 +46,7 @@ impl OpBlockAssembler { let BlockAssemblerInput { evm_env, execution_ctx: ctx, + parent, transactions, output: BlockExecutionResult { receipts, gas_used, blob_gas_used, requests: _ }, bundle_state, @@ -80,7 +82,21 @@ impl OpBlockAssembler { }; let (excess_blob_gas, blob_gas_used) = - if self.chain_spec.is_jovian_active_at_timestamp(timestamp) { + if self.chain_spec.is_l2_blob_active_at_timestamp(timestamp) { + // When L2 blob is active, calculate excess_blob_gas using the EIP-4844 formula + // from parent header, matching op-geth behavior for blob base fee market on L2. + let blob_params = self.chain_spec.blob_params_at_timestamp(timestamp); + let excess = if parent.header().excess_blob_gas().is_some() { + parent + .header() + .maybe_next_block_excess_blob_gas(blob_params) + .unwrap_or(0) + } else { + // First block after L2 blob activation: parent has no blob gas fields + 0 + }; + (Some(excess), Some(*blob_gas_used)) + } else if self.chain_spec.is_jovian_active_at_timestamp(timestamp) { // In jovian, we're using the blob gas used field to store the current da // footprint's value. (Some(0), Some(*blob_gas_used)) @@ -136,7 +152,7 @@ impl Clone for OpBlockAssembler { impl BlockAssembler for OpBlockAssembler where - ChainSpec: OpHardforks, + ChainSpec: OpHardforks + EthChainSpec, F: for<'a> BlockExecutorFactory< ExecutionCtx<'a> = OpBlockExecutionCtx, Transaction: SignedTransaction, diff --git a/rust/op-reth/crates/evm/src/lib.rs b/rust/op-reth/crates/evm/src/lib.rs index b5d55bf32a8..2f326ab663b 100644 --- a/rust/op-reth/crates/evm/src/lib.rs +++ b/rust/op-reth/crates/evm/src/lib.rs @@ -259,10 +259,23 @@ where cfg_env.sgt_enabled = sgt_config.enabled; cfg_env.sgt_is_native_backed = sgt_config.is_native_backed; - let blob_excess_gas_and_price = spec - .into_eth_spec() - .is_enabled_in(SpecId::CANCUN) - .then_some(BlobExcessGasAndPrice { excess_blob_gas: 0, blob_gasprice: 1 }); + let blob_excess_gas_and_price = + if self.chain_spec().is_l2_blob_active_at_timestamp(timestamp) { + // When L2 blob is active, derive blob gas price from the payload's + // excess_blob_gas using the EIP-4844 formula, matching op-geth behavior. + let blob_params = self.chain_spec().blob_params_at_timestamp(timestamp); + payload.payload.excess_blob_gas().map(|excess_blob_gas| { + let blob_gasprice = blob_params + .map(|params| params.calc_blob_fee(excess_blob_gas)) + .unwrap_or(1); + BlobExcessGasAndPrice { excess_blob_gas, blob_gasprice } + }) + } else { + // Standard OP-stack: no blob base fee market, excess is always 0. + spec.into_eth_spec() + .is_enabled_in(SpecId::CANCUN) + .then_some(BlobExcessGasAndPrice { excess_blob_gas: 0, blob_gasprice: 1 }) + }; let block_env = BlockEnv { number: U256::from(block_number), diff --git a/rust/op-reth/crates/evm/src/receipts.rs b/rust/op-reth/crates/evm/src/receipts.rs index 9b95cf3a489..b802f58efe1 100644 --- a/rust/op-reth/crates/evm/src/receipts.rs +++ b/rust/op-reth/crates/evm/src/receipts.rs @@ -34,6 +34,7 @@ impl OpReceiptBuilder for OpRethReceiptBuilder { OpTxType::Legacy => OpReceipt::Legacy(receipt), OpTxType::Eip1559 => OpReceipt::Eip1559(receipt), OpTxType::Eip2930 => OpReceipt::Eip2930(receipt), + OpTxType::Eip4844 => OpReceipt::Eip4844(receipt), OpTxType::Eip7702 => OpReceipt::Eip7702(receipt), OpTxType::Deposit => unreachable!(), }) diff --git a/rust/op-reth/crates/node/src/node.rs b/rust/op-reth/crates/node/src/node.rs index c74d40dbc86..065bef07d35 100644 --- a/rust/op-reth/crates/node/src/node.rs +++ b/rust/op-reth/crates/node/src/node.rs @@ -1078,8 +1078,12 @@ where let blob_store = reth_node_builder::components::create_blob_store(ctx)?; let mut builder = - TransactionValidationTaskExecutor::eth_builder(ctx.provider().clone(), evm_config) - .no_eip4844() + TransactionValidationTaskExecutor::eth_builder(ctx.provider().clone(), evm_config); + // Disable EIP-4844 blob transactions unless L2 blob is active + if !ctx.chain_spec().is_l2_blob_active_at_timestamp(ctx.head().timestamp) { + builder = builder.no_eip4844(); + } + builder = builder .with_max_tx_input_bytes(ctx.config().txpool.max_tx_input_bytes) .kzg_settings(ctx.kzg_settings()?) .set_tx_fee_cap(ctx.config().rpc.rpc_tx_fee_cap) diff --git a/rust/op-reth/crates/payload/src/builder.rs b/rust/op-reth/crates/payload/src/builder.rs index 2477a8bf9a9..79189831ac2 100644 --- a/rust/op-reth/crates/payload/src/builder.rs +++ b/rust/op-reth/crates/payload/src/builder.rs @@ -37,7 +37,7 @@ use reth_revm::{ witness::ExecutionWitnessRecord, }; use reth_storage_api::{StateProvider, StateProviderFactory, errors::ProviderError}; -use reth_transaction_pool::{BestTransactionsAttributes, PoolTransaction, TransactionPool}; +use reth_transaction_pool::{BestTransactionsAttributes, EthBlobTransactionSidecar, EthPoolTransaction, PoolTransaction, TransactionPool}; use revm::context::{Block, BlockEnv}; use std::{marker::PhantomData, sync::Arc}; use tracing::{debug, trace, warn}; @@ -153,7 +153,7 @@ impl OpPayloadBuilder OpPayloadBuilder where - Pool: TransactionPool>, + Pool: TransactionPool + EthPoolTransaction>, Client: StateProviderFactory + ChainSpecProvider, N: OpPayloadPrimitives, Evm: ConfigureEvm< @@ -177,7 +177,7 @@ where ) -> Result>, PayloadBuilderError> where Txs: - PayloadTransactions + OpPooledTx>, + PayloadTransactions + OpPooledTx + EthPoolTransaction>, { let BuildArguments { mut cached_reads, config, cancel, best_payload } = args; @@ -239,7 +239,7 @@ impl PayloadBuilder where N: OpPayloadPrimitives, Client: StateProviderFactory + ChainSpecProvider + Clone, - Pool: TransactionPool>, + Pool: TransactionPool + EthPoolTransaction>, Evm: ConfigureEvm< Primitives = N, NextBlockEnvCtx: BuildNextEnv, @@ -330,7 +330,7 @@ impl OpBuilder<'_, Txs> { ChainSpec: EthChainSpec + OpHardforks, N: OpPayloadPrimitives, Txs: - PayloadTransactions + OpPooledTx>, + PayloadTransactions + OpPooledTx + EthPoolTransaction>, Attrs: OpAttributes, { let Self { best } = self; @@ -388,8 +388,9 @@ impl OpBuilder<'_, Txs> { let no_tx_pool = ctx.attributes().no_tx_pool(); - let payload = + let mut payload = OpBuiltPayload::new(ctx.payload_id(), sealed_block, info.total_fees, Some(executed)); + payload.sidecars = info.blob_sidecars; if no_tx_pool { // if `no_tx_pool` is set only transactions from the payload attributes will be included @@ -488,12 +489,14 @@ pub struct ExecutionInfo { pub cumulative_da_bytes_used: u64, /// Tracks fees from executed mempool transactions pub total_fees: U256, + /// Collected blob sidecars from EIP-4844 transactions + pub blob_sidecars: Vec, } impl ExecutionInfo { /// Create a new instance with allocated slots. pub const fn new() -> Self { - Self { cumulative_gas_used: 0, cumulative_da_bytes_used: 0, total_fees: U256::ZERO } + Self { cumulative_gas_used: 0, cumulative_da_bytes_used: 0, total_fees: U256::ZERO, blob_sidecars: Vec::new() } } /// Returns true if the transaction would exceed the block limits: @@ -625,8 +628,12 @@ where let mut info = ExecutionInfo::new(); for sequencer_tx in self.attributes().sequencer_transactions() { - // A sequencer's block should never contain blob transactions. - if sequencer_tx.value().is_eip4844() { + // A sequencer's block should never contain blob transactions unless L2 blob is active. + if sequencer_tx.value().is_eip4844() + && !self + .chain_spec + .is_l2_blob_active_at_timestamp(self.attributes().timestamp()) + { return Err(PayloadBuilderError::other( OpPayloadBuilderError::BlobTransactionRejected, )); @@ -670,7 +677,7 @@ where info: &mut ExecutionInfo, builder: &mut Builder, mut best_txs: impl PayloadTransactions< - Transaction: PoolTransaction> + OpPooledTx, + Transaction: PoolTransaction> + OpPooledTx + EthPoolTransaction, >, ) -> Result, PayloadBuilderError> where @@ -687,9 +694,11 @@ where let tx_da_limit = self.builder_config.da_config.max_da_tx_size(); let base_fee = builder.evm_mut().block().basefee(); - while let Some(tx) = best_txs.next(()) { + while let Some(mut tx) = best_txs.next(()) { let interop = tx.interop_deadline(); let tx_da_size = tx.estimated_da_size(); + // Extract blob sidecar before converting to consensus (which strips it). + let blob_sidecar = tx.take_blob(); let tx = tx.into_consensus(); let da_footprint_gas_scalar = self @@ -716,8 +725,14 @@ where continue; } - // A sequencer's block should never contain blob or deposit transactions from the pool. - if tx.is_eip4844() || tx.is_deposit() { + // A sequencer's block should never contain deposit transactions from the pool. + // Blob transactions are also rejected unless L2 blob is active. + if tx.is_deposit() + || (tx.is_eip4844() + && !self + .chain_spec + .is_l2_blob_active_at_timestamp(self.attributes().timestamp())) + { best_txs.mark_invalid(tx.signer(), tx.nonce()); continue; } @@ -763,6 +778,11 @@ where info.cumulative_gas_used += gas_used; info.cumulative_da_bytes_used += tx_da_size; + // Collect blob sidecar for the payload response + if let EthBlobTransactionSidecar::Present(sidecar) = blob_sidecar { + info.blob_sidecars.push(sidecar); + } + // update and add to total fees let miner_fee = tx .effective_tip_per_gas(base_fee) @@ -773,3 +793,4 @@ where Ok(None) } } + diff --git a/rust/op-reth/crates/payload/src/payload.rs b/rust/op-reth/crates/payload/src/payload.rs index 516a598ab1e..19aa31d824f 100644 --- a/rust/op-reth/crates/payload/src/payload.rs +++ b/rust/op-reth/crates/payload/src/payload.rs @@ -180,6 +180,8 @@ pub struct OpBuiltPayload { pub(crate) executed_block: Option>, /// The fees of the block pub(crate) fees: U256, + /// The blob sidecars of EIP-4844 transactions in this payload. + pub(crate) sidecars: Vec, } // === impl BuiltPayload === @@ -192,7 +194,7 @@ impl OpBuiltPayload { fees: U256, executed_block: Option>, ) -> Self { - Self { id, block, fees, executed_block } + Self { id, block, fees, executed_block, sidecars: Vec::new() } } /// Returns the identifier of the payload. @@ -275,7 +277,7 @@ where N: NodePrimitives>, { fn from(value: OpBuiltPayload) -> Self { - let OpBuiltPayload { block, fees, .. } = value; + let OpBuiltPayload { block, fees, sidecars, .. } = value; let parent_beacon_block_root = block.parent_beacon_block_root.unwrap_or_default(); @@ -285,17 +287,8 @@ where &Arc::unwrap_or_clone(block).into_block(), ), block_value: fees, - // From the engine API spec: - // - // > Client software **MAY** use any heuristics to decide whether to set - // `shouldOverrideBuilder` flag or not. If client software does not implement any - // heuristic this flag **SHOULD** be set to `false`. - // - // Spec: - // should_override_builder: false, - // No blobs for OP. - blobs_bundle: BlobsBundleV1 { blobs: vec![], commitments: vec![], proofs: vec![] }, + blobs_bundle: crate::payload::sidecars_to_blobs_bundle(sidecars), parent_beacon_block_root, } } @@ -307,7 +300,7 @@ where N: NodePrimitives>, { fn from(value: OpBuiltPayload) -> Self { - let OpBuiltPayload { block, fees, .. } = value; + let OpBuiltPayload { block, fees, sidecars, .. } = value; let parent_beacon_block_root = block.parent_beacon_block_root.unwrap_or_default(); @@ -332,8 +325,7 @@ where // Spec: // should_override_builder: false, - // No blobs for OP. - blobs_bundle: BlobsBundleV1 { blobs: vec![], commitments: vec![], proofs: vec![] }, + blobs_bundle: crate::payload::sidecars_to_blobs_bundle(sidecars), parent_beacon_block_root, execution_requests: vec![], } @@ -345,6 +337,31 @@ where /// Returns an 8-byte identifier by hashing the payload components with sha256 hash. /// /// Note: This must be updated whenever the [`OpPayloadAttributes`] changes for a hardfork. +/// Converts a list of blob transaction sidecars into a [`BlobsBundleV1`]. +pub(crate) fn sidecars_to_blobs_bundle( + sidecars: Vec, +) -> BlobsBundleV1 { + use alloy_eips::eip7594::BlobTransactionSidecarVariant; + let mut blobs = Vec::new(); + let mut commitments = Vec::new(); + let mut proofs = Vec::new(); + for sidecar in sidecars { + match sidecar { + BlobTransactionSidecarVariant::Eip4844(s) => { + blobs.extend_from_slice(&s.blobs); + commitments.extend_from_slice(&s.commitments); + proofs.extend_from_slice(&s.proofs); + } + BlobTransactionSidecarVariant::Eip7594(s) => { + blobs.extend_from_slice(&s.blobs); + commitments.extend_from_slice(&s.commitments); + // EIP-7594 uses cell proofs, not KZG proofs + } + } + } + BlobsBundleV1 { blobs, commitments, proofs } +} + /// See also pub fn payload_id_optimism( parent: &B256, diff --git a/rust/op-reth/crates/primitives/src/receipt.rs b/rust/op-reth/crates/primitives/src/receipt.rs index 1a7baed9c0f..1f61139c2e6 100644 --- a/rust/op-reth/crates/primitives/src/receipt.rs +++ b/rust/op-reth/crates/primitives/src/receipt.rs @@ -69,6 +69,8 @@ pub(super) mod serde_bincode_compat { Eip2930(alloy_consensus::serde_bincode_compat::Receipt<'a, alloy_primitives::Log>), /// EIP-1559 receipt Eip1559(alloy_consensus::serde_bincode_compat::Receipt<'a, alloy_primitives::Log>), + /// EIP-4844 receipt + Eip4844(alloy_consensus::serde_bincode_compat::Receipt<'a, alloy_primitives::Log>), /// EIP-7702 receipt Eip7702(alloy_consensus::serde_bincode_compat::Receipt<'a, alloy_primitives::Log>), /// Deposit receipt @@ -83,6 +85,7 @@ pub(super) mod serde_bincode_compat { super::OpReceipt::Legacy(receipt) => Self::Legacy(receipt.into()), super::OpReceipt::Eip2930(receipt) => Self::Eip2930(receipt.into()), super::OpReceipt::Eip1559(receipt) => Self::Eip1559(receipt.into()), + super::OpReceipt::Eip4844(receipt) => Self::Eip4844(receipt.into()), super::OpReceipt::Eip7702(receipt) => Self::Eip7702(receipt.into()), super::OpReceipt::Deposit(receipt) => Self::Deposit(receipt.into()), } @@ -95,6 +98,7 @@ pub(super) mod serde_bincode_compat { OpReceipt::Legacy(receipt) => Self::Legacy(receipt.into()), OpReceipt::Eip2930(receipt) => Self::Eip2930(receipt.into()), OpReceipt::Eip1559(receipt) => Self::Eip1559(receipt.into()), + OpReceipt::Eip4844(receipt) => Self::Eip4844(receipt.into()), OpReceipt::Eip7702(receipt) => Self::Eip7702(receipt.into()), OpReceipt::Deposit(receipt) => Self::Deposit(receipt.into()), } diff --git a/rust/op-reth/crates/rpc/src/eth/receipt.rs b/rust/op-reth/crates/rpc/src/eth/receipt.rs index 77243039e97..c7e3aec2adc 100644 --- a/rust/op-reth/crates/rpc/src/eth/receipt.rs +++ b/rust/op-reth/crates/rpc/src/eth/receipt.rs @@ -299,6 +299,7 @@ impl OpReceiptBuilder { OpReceipt::Legacy(receipt) => OpReceipt::Legacy(map_logs(receipt)), OpReceipt::Eip2930(receipt) => OpReceipt::Eip2930(map_logs(receipt)), OpReceipt::Eip1559(receipt) => OpReceipt::Eip1559(map_logs(receipt)), + OpReceipt::Eip4844(receipt) => OpReceipt::Eip4844(map_logs(receipt)), OpReceipt::Eip7702(receipt) => OpReceipt::Eip7702(map_logs(receipt)), OpReceipt::Deposit(receipt) => OpReceipt::Deposit(receipt.map_inner(map_logs)), }; diff --git a/rust/op-reth/crates/txpool/src/transaction.rs b/rust/op-reth/crates/txpool/src/transaction.rs index 1ed83561047..ff650d85f7d 100644 --- a/rust/op-reth/crates/txpool/src/transaction.rs +++ b/rust/op-reth/crates/txpool/src/transaction.rs @@ -26,6 +26,49 @@ use std::{ }, }; +/// Trait for consensus transaction types that can attach a blob sidecar +/// and convert to a pooled EIP-4844 transaction. +pub trait IntoPooledEip4844 { + /// Attach a blob sidecar to this consensus transaction, producing a pooled transaction. + /// Returns `None` if this is not an EIP-4844 transaction. + fn into_pooled_with_sidecar( + self, + sidecar: BlobTransactionSidecarVariant, + ) -> Option; +} + +impl IntoPooledEip4844 for OpTransactionSigned { + fn into_pooled_with_sidecar( + self, + sidecar: BlobTransactionSidecarVariant, + ) -> Option { + // OpTransactionSigned = OpTxEnvelope, which has try_into_pooled_eip4844 + self.try_into_pooled_eip4844(sidecar).ok() + } +} + +/// Trait for pooled transaction types that may contain a blob sidecar. +pub trait TakeBlobSidecar { + /// Extract the blob sidecar from this pooled transaction, if present. + /// Returns `None` for non-blob transactions. + fn take_blob_sidecar(&mut self) -> Option; +} + +impl TakeBlobSidecar for op_alloy_consensus::OpPooledTransaction { + fn take_blob_sidecar(&mut self) -> Option { + match self { + op_alloy_consensus::OpPooledTransaction::Eip4844(signed) => { + // Replace the sidecar with a default empty one and return the original + let (tx_with_sidecar, sig, hash) = signed.clone().into_parts(); + let sidecar = tx_with_sidecar.sidecar; + // Reconstruct with empty sidecar (it will be stripped during consensus conversion anyway) + Some(sidecar.into()) + } + _ => None, + } + } +} + /// Marker for no-interop transactions pub(crate) const NO_INTEROP_TX: u64 = 0; @@ -124,7 +167,7 @@ impl DataAvailabilitySized for OpPooledTransact impl PoolTransaction for OpPooledTransaction where Cons: SignedTransaction + From, - Pooled: SignedTransaction + TryFrom, + Pooled: SignedTransaction + TryFrom + TakeBlobSidecar, { type TryFromConsensusError = >::Error; type Consensus = Cons; @@ -145,7 +188,17 @@ where fn from_pooled(tx: Recovered) -> Self { let encoded_len = tx.encode_2718_len(); - Self::new(tx.convert(), encoded_len) + let (mut pooled, signer) = tx.into_parts(); + // Extract blob sidecar before converting to consensus format (which strips it). + let blob_sidecar = pooled.take_blob_sidecar() + .map(EthBlobTransactionSidecar::Present); + let consensus: Cons = pooled.into(); + let recovered = Recovered::new_unchecked(consensus, signer); + let mut this = Self::new(recovered, encoded_len); + if let Some(sidecar) = blob_sidecar { + this.inner.blob_sidecar = sidecar; + } + this } fn hash(&self) -> &TxHash { @@ -257,34 +310,47 @@ where impl EthPoolTransaction for OpPooledTransaction where - Cons: SignedTransaction + From, - Pooled: SignedTransaction + TryFrom, + Cons: SignedTransaction + From + IntoPooledEip4844, + Pooled: SignedTransaction + TryFrom + TakeBlobSidecar, >::Error: core::error::Error, { fn take_blob(&mut self) -> EthBlobTransactionSidecar { - EthBlobTransactionSidecar::None + if self.is_eip4844() { + std::mem::replace(&mut self.inner.blob_sidecar, EthBlobTransactionSidecar::Missing) + } else { + EthBlobTransactionSidecar::None + } } fn try_into_pooled_eip4844( self, - _sidecar: Arc, + sidecar: Arc, ) -> Option> { - None + let (consensus_tx, signer) = self.inner.transaction.into_parts(); + let pooled = consensus_tx.into_pooled_with_sidecar(Arc::unwrap_or_clone(sidecar))?; + Some(Recovered::new_unchecked(pooled, signer)) } fn try_from_eip4844( - _tx: Recovered, - _sidecar: BlobTransactionSidecarVariant, + tx: Recovered, + sidecar: BlobTransactionSidecarVariant, ) -> Option { - None + let (consensus_tx, signer) = tx.into_parts(); + let pooled = consensus_tx.into_pooled_with_sidecar(sidecar)?; + let recovered = Recovered::new_unchecked(pooled, signer); + Some(Self::from_pooled(recovered)) } fn validate_blob( &self, - _sidecar: &BlobTransactionSidecarVariant, - _settings: &KzgSettings, + sidecar: &BlobTransactionSidecarVariant, + settings: &KzgSettings, ) -> Result<(), BlobTransactionValidationError> { - Err(BlobTransactionValidationError::NotBlobTransaction(self.ty())) + if self.is_eip4844() { + sidecar.validate(&self.inner.transaction.blob_versioned_hashes().unwrap_or_default(), settings) + } else { + Err(BlobTransactionValidationError::NotBlobTransaction(self.ty())) + } } } @@ -300,7 +366,7 @@ pub trait OpPooledTx: impl OpPooledTx for OpPooledTransaction where Cons: SignedTransaction + From, - Pooled: SignedTransaction + TryFrom, + Pooled: SignedTransaction + TryFrom + TakeBlobSidecar, >::Error: core::error::Error, { fn encoded_2718(&self) -> Cow<'_, Bytes> { diff --git a/rust/op-reth/crates/txpool/src/validator.rs b/rust/op-reth/crates/txpool/src/validator.rs index c8f4fdbea21..13447898b69 100644 --- a/rust/op-reth/crates/txpool/src/validator.rs +++ b/rust/op-reth/crates/txpool/src/validator.rs @@ -174,7 +174,7 @@ where /// /// This behaves the same as [`EthTransactionValidator::validate_one_with_state`], but in /// addition applies OP validity checks: - /// - ensures tx is not eip4844 + /// - ensures tx is not eip4844 (unless L2 blob is active) /// - ensures cross chain transactions are valid wrt locally configured safety level /// - ensures that the account has enough balance to cover the L1 gas cost pub async fn validate_one_with_state( @@ -183,7 +183,9 @@ where transaction: Tx, state: &mut Option>, ) -> TransactionValidationOutcome { - if transaction.is_eip4844() { + if transaction.is_eip4844() + && !self.chain_spec().is_l2_blob_active_at_timestamp(self.block_timestamp()) + { return TransactionValidationOutcome::Invalid( transaction, InvalidTransactionError::TxTypeNotSupported.into(),