Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
diegoximenes committed Feb 28, 2025
1 parent 94b8f88 commit bceef0d
Show file tree
Hide file tree
Showing 2 changed files with 168 additions and 168 deletions.
206 changes: 103 additions & 103 deletions arbnode/batch_poster.go
Original file line number Diff line number Diff line change
Expand Up @@ -530,108 +530,108 @@ func (b *BatchPoster) GetParentChainIsUsingEIP7623(ctx context.Context) *bool {
return b.parentChainIsUsingEIP7623.Load()
}

func (b *BatchPoster) setParentChainIsUsingEIP7623(ctx context.Context) {
// Before EIP-7623 tx.gasUsed is defined as:
// tx.gasUsed = (
// 21000
// + STANDARD_TOKEN_COST * tokens_in_calldata
// + execution_gas_used
// + isContractCreation * (32000 + INITCODE_WORD_COST * words(calldata))
// )
//
// With EIP-7623 tx.gasUsed is defined as:
// tx.gasUsed = (
// 21000
// +
// max(
// STANDARD_TOKEN_COST * tokens_in_calldata
// + execution_gas_used
// + isContractCreation * (32000 + INITCODE_WORD_COST * words(calldata)),
// TOTAL_COST_FLOOR_PER_TOKEN * tokens_in_calldata
// )
// )
//
// STANDARD_TOKEN_COST = 4
// TOTAL_COST_FLOOR_PER_TOKEN = 10
//
// To infer whether the parent chain is using EIP-7623 we estimate gas usage of two parent chain native token transfer transactions,
// that then have equal execution_gas_used.
// Also, in both transactions isContractCreation is zero, and tokens_in_calldata is big enough so
// (TOTAL_COST_FLOOR_PER_TOKEN * tokens_in_calldata > STANDARD_TOKEN_COST * tokens_in_calldata + execution_gas_used).
// Also, the used calldatas only have non-zero bytes, so tokens_in_calldata is defined as length(calldata) * 4.
//
// The difference between the transactions is:
// length(calldata_tx_2) == length(calldata_tx_1) + 1
//
// So, if parent chain is not running EIP-7623:
// tx_2.gasUsed - tx_1.gasUsed =
// STANDARD_TOKEN_COST * 4 * (length(calldata_tx_2) - length(calldata_tx_1)) =
// 16
//
// And if the parent chain is running EIP-7623:
// tx_2.gasUsed - tx_1.gasUsed =
// TOTAL_COST_FLOOR_PER_TOKEN * 4 * (length(calldata_tx_2) - length(calldata_tx_1)) =
// 40

rpcClient := b.l1Reader.Client()
latestHeader, err := rpcClient.HeaderByNumber(ctx, nil)
if err != nil {
log.Warn("HeaderByNumber failed", "err", err)
return
}
config := b.config()
maxFeePerGas := arbmath.BigMulByUBips(latestHeader.BaseFee, config.GasEstimateBaseFeeMultipleBips)
to := b.dataPoster.Sender()

data := []byte{}
for i := 0; i < 100_000; i++ {
data = append(data, 1)
}

gas1, err := estimateGas(rpcClient.Client(), ctx, estimateGasParams{
From: b.dataPoster.Sender(),
To: &to,
Data: data,
MaxFeePerGas: (*hexutil.Big)(maxFeePerGas),
})
if err != nil {
log.Warn("estimateGas failed", "err", err)
return
}

data = append(data, 1)
gas2, err := estimateGas(rpcClient.Client(), ctx, estimateGasParams{
From: b.dataPoster.Sender(),
To: &to,
Data: data,
MaxFeePerGas: (*hexutil.Big)(maxFeePerGas),
})
if err != nil {
log.Warn("estimateGas failed", "err", err)
return
}

// Takes into consideration that eth_estimateGas is an approximation.
// As an example, go-ethereum can only return an estimate that is equal
// or bigger than the true estimate, and currently defines the allowed error ratio as 0.015
var parentChainIsUsingEIP7623 bool
diffIsClose := func(gas1, gas2, lowerTargetDiff, upperTargetDiff uint64) bool {
diff := gas2 - gas1
return diff >= lowerTargetDiff && diff <= upperTargetDiff
}
if diffIsClose(gas1, gas2, 14, 18) {
// targetDiff is 16
parentChainIsUsingEIP7623 = false
} else if diffIsClose(gas1, gas2, 36, 44) {
// targetDiff is 40
parentChainIsUsingEIP7623 = true
} else {
log.Error("setParentChainIsUsingEIP7623 failed, unexpected gas difference", "gas1", gas1, "gas2", gas2, "diff", gas2-gas1)
return
}

b.parentChainIsUsingEIP7623.Store(&parentChainIsUsingEIP7623)
}
// func (b *BatchPoster) setParentChainIsUsingEIP7623(ctx context.Context) {
// // Before EIP-7623 tx.gasUsed is defined as:
// // tx.gasUsed = (
// // 21000
// // + STANDARD_TOKEN_COST * tokens_in_calldata
// // + execution_gas_used
// // + isContractCreation * (32000 + INITCODE_WORD_COST * words(calldata))
// // )
// //
// // With EIP-7623 tx.gasUsed is defined as:
// // tx.gasUsed = (
// // 21000
// // +
// // max(
// // STANDARD_TOKEN_COST * tokens_in_calldata
// // + execution_gas_used
// // + isContractCreation * (32000 + INITCODE_WORD_COST * words(calldata)),
// // TOTAL_COST_FLOOR_PER_TOKEN * tokens_in_calldata
// // )
// // )
// //
// // STANDARD_TOKEN_COST = 4
// // TOTAL_COST_FLOOR_PER_TOKEN = 10
// //
// // To infer whether the parent chain is using EIP-7623 we estimate gas usage of two parent chain native token transfer transactions,
// // that then have equal execution_gas_used.
// // Also, in both transactions isContractCreation is zero, and tokens_in_calldata is big enough so
// // (TOTAL_COST_FLOOR_PER_TOKEN * tokens_in_calldata > STANDARD_TOKEN_COST * tokens_in_calldata + execution_gas_used).
// // Also, the used calldatas only have non-zero bytes, so tokens_in_calldata is defined as length(calldata) * 4.
// //
// // The difference between the transactions is:
// // length(calldata_tx_2) == length(calldata_tx_1) + 1
// //
// // So, if parent chain is not running EIP-7623:
// // tx_2.gasUsed - tx_1.gasUsed =
// // STANDARD_TOKEN_COST * 4 * (length(calldata_tx_2) - length(calldata_tx_1)) =
// // 16
// //
// // And if the parent chain is running EIP-7623:
// // tx_2.gasUsed - tx_1.gasUsed =
// // TOTAL_COST_FLOOR_PER_TOKEN * 4 * (length(calldata_tx_2) - length(calldata_tx_1)) =
// // 40
//
// rpcClient := b.l1Reader.Client()
// latestHeader, err := rpcClient.HeaderByNumber(ctx, nil)
// if err != nil {
// log.Warn("HeaderByNumber failed", "err", err)
// return
// }
// config := b.config()
// maxFeePerGas := arbmath.BigMulByUBips(latestHeader.BaseFee, config.GasEstimateBaseFeeMultipleBips)
// to := b.dataPoster.Sender()
//
// data := []byte{}
// for i := 0; i < 100_000; i++ {
// data = append(data, 1)
// }
//
// gas1, err := estimateGas(rpcClient.Client(), ctx, estimateGasParams{
// From: b.dataPoster.Sender(),
// To: &to,
// Data: data,
// MaxFeePerGas: (*hexutil.Big)(maxFeePerGas),
// })
// if err != nil {
// log.Warn("estimateGas failed", "err", err)
// return
// }
//
// data = append(data, 1)
// gas2, err := estimateGas(rpcClient.Client(), ctx, estimateGasParams{
// From: b.dataPoster.Sender(),
// To: &to,
// Data: data,
// MaxFeePerGas: (*hexutil.Big)(maxFeePerGas),
// })
// if err != nil {
// log.Warn("estimateGas failed", "err", err)
// return
// }
//
// // Takes into consideration that eth_estimateGas is an approximation.
// // As an example, go-ethereum can only return an estimate that is equal
// // or bigger than the true estimate, and currently defines the allowed error ratio as 0.015
// var parentChainIsUsingEIP7623 bool
// diffIsClose := func(gas1, gas2, lowerTargetDiff, upperTargetDiff uint64) bool {
// diff := gas2 - gas1
// return diff >= lowerTargetDiff && diff <= upperTargetDiff
// }
// if diffIsClose(gas1, gas2, 14, 18) {
// // targetDiff is 16
// parentChainIsUsingEIP7623 = false
// } else if diffIsClose(gas1, gas2, 36, 44) {
// // targetDiff is 40
// parentChainIsUsingEIP7623 = true
// } else {
// log.Error("setParentChainIsUsingEIP7623 failed, unexpected gas difference", "gas1", gas1, "gas2", gas2, "diff", gas2-gas1)
// return
// }
//
// b.parentChainIsUsingEIP7623.Store(&parentChainIsUsingEIP7623)
// }

// getTxsInfoByBlock fetches all the transactions inside block of id 'number' using json rpc
// and returns an array of txInfo which has fields that are necessary in checking for batch reverts
Expand Down Expand Up @@ -1813,7 +1813,7 @@ func (b *BatchPoster) Start(ctxIn context.Context) {
resetAllEphemeralErrs()
return b.config().PollInterval
}
b.setParentChainIsUsingEIP7623(ctx)
// b.setParentChainIsUsingEIP7623(ctx)
posted, err := b.maybePostSequencerBatch(ctx)
if err == nil {
resetAllEphemeralErrs()
Expand Down
130 changes: 65 additions & 65 deletions system_tests/batch_poster_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -468,68 +468,68 @@ func TestBatchPosterDelayBufferDontForceNonDelayedMessages(t *testing.T) {
CheckBatchCount(t, builder, initialBatchCount+1)
}

func TestParentChainNonEIP7623(t *testing.T) {
t.Parallel()

ctx, cancel := context.WithCancel(context.Background())
defer cancel()

builder := NewNodeBuilder(ctx).
DefaultConfig(t, true).
WithArbOSVersion(11) // ArbOS 11 doesn't use EIP-7623

// Build L1 and L2
cleanupL1AndL2 := builder.Build(t)
defer cleanupL1AndL2()
firstNodeL2TestClient := builder.L2
secondNodeL2NodeConfig := arbnode.ConfigDefaultL1NonSequencerTest()
secondNodeL2TestClient, cleanupL2SecondNode := builder.Build2ndNode(t, &SecondNodeParams{nodeConfig: secondNodeL2NodeConfig})
defer cleanupL2SecondNode()

// Force L2 batch posting so parentChainIsUsingEIP7623 is set
accountName := "User2"
builder.L2Info.GenerateAccount(accountName)
tx := builder.L2Info.PrepareTx("Owner", accountName, builder.L2Info.TransferGas, big.NewInt(1e12), nil)
err := firstNodeL2TestClient.Client.SendTransaction(ctx, tx)
Require(t, err)
_, err = firstNodeL2TestClient.EnsureTxSucceeded(tx)
Require(t, err)
_, err = WaitForTx(ctx, secondNodeL2TestClient.Client, tx.Hash(), time.Second*15)
Require(t, err)

// Check if L2's parent chain is using EIP-7623
isUsingEIP7623 := builder.L2.ConsensusNode.BatchPoster.GetParentChainIsUsingEIP7623(ctx)
if isUsingEIP7623 == nil {
t.Fatal("Failed to get parent chain EIP-7623 status")
}
if *isUsingEIP7623 {
t.Fatal("L3's parent chain should not be using EIP-7623")
}

// Build L3
cleanupL3FirstNode := builder.BuildL3OnL2(t)
defer cleanupL3FirstNode()
firstNodeL3TestClient := builder.L3
secondNodeL3NodeConfig := arbnode.ConfigDefaultL1NonSequencerTest()
secondNodeL3TestClient, cleanupL3SecondNode := builder.Build2ndNodeOnL3(t, &SecondNodeParams{nodeConfig: secondNodeL3NodeConfig})
defer cleanupL3SecondNode()

// Force L3 batch posting so parentChainIsUsingEIP7623 is set
builder.L3Info.GenerateAccount(accountName)
tx = builder.L3Info.PrepareTx("Owner", accountName, builder.L3Info.TransferGas, big.NewInt(1e12), nil)
err = firstNodeL3TestClient.Client.SendTransaction(ctx, tx)
Require(t, err)
_, err = firstNodeL3TestClient.EnsureTxSucceeded(tx)
Require(t, err)
_, err = WaitForTx(ctx, secondNodeL3TestClient.Client, tx.Hash(), time.Second*15)
Require(t, err)

// Check if L3's parent chain is using EIP-7623
isUsingEIP7623 = builder.L3.ConsensusNode.BatchPoster.GetParentChainIsUsingEIP7623(ctx)
if isUsingEIP7623 == nil {
t.Fatal("Failed to get parent chain EIP-7623 status")
}
if *isUsingEIP7623 {
t.Fatal("L3's parent chain should not be using EIP-7623")
}
}
// func TestParentChainNonEIP7623(t *testing.T) {
// t.Parallel()
//
// ctx, cancel := context.WithCancel(context.Background())
// defer cancel()
//
// builder := NewNodeBuilder(ctx).
// DefaultConfig(t, true).
// WithArbOSVersion(11) // ArbOS 11 doesn't use EIP-7623
//
// // Build L1 and L2
// cleanupL1AndL2 := builder.Build(t)
// defer cleanupL1AndL2()
// firstNodeL2TestClient := builder.L2
// secondNodeL2NodeConfig := arbnode.ConfigDefaultL1NonSequencerTest()
// secondNodeL2TestClient, cleanupL2SecondNode := builder.Build2ndNode(t, &SecondNodeParams{nodeConfig: secondNodeL2NodeConfig})
// defer cleanupL2SecondNode()
//
// // Force L2 batch posting so parentChainIsUsingEIP7623 is set
// accountName := "User2"
// builder.L2Info.GenerateAccount(accountName)
// tx := builder.L2Info.PrepareTx("Owner", accountName, builder.L2Info.TransferGas, big.NewInt(1e12), nil)
// err := firstNodeL2TestClient.Client.SendTransaction(ctx, tx)
// Require(t, err)
// _, err = firstNodeL2TestClient.EnsureTxSucceeded(tx)
// Require(t, err)
// _, err = WaitForTx(ctx, secondNodeL2TestClient.Client, tx.Hash(), time.Second*15)
// Require(t, err)
//
// // Check if L2's parent chain is using EIP-7623
// isUsingEIP7623 := builder.L2.ConsensusNode.BatchPoster.GetParentChainIsUsingEIP7623(ctx)
// if isUsingEIP7623 == nil {
// t.Fatal("Failed to get parent chain EIP-7623 status")
// }
// if *isUsingEIP7623 {
// t.Fatal("L3's parent chain should not be using EIP-7623")
// }
//
// // Build L3
// cleanupL3FirstNode := builder.BuildL3OnL2(t)
// defer cleanupL3FirstNode()
// firstNodeL3TestClient := builder.L3
// secondNodeL3NodeConfig := arbnode.ConfigDefaultL1NonSequencerTest()
// secondNodeL3TestClient, cleanupL3SecondNode := builder.Build2ndNodeOnL3(t, &SecondNodeParams{nodeConfig: secondNodeL3NodeConfig})
// defer cleanupL3SecondNode()
//
// // Force L3 batch posting so parentChainIsUsingEIP7623 is set
// builder.L3Info.GenerateAccount(accountName)
// tx = builder.L3Info.PrepareTx("Owner", accountName, builder.L3Info.TransferGas, big.NewInt(1e12), nil)
// err = firstNodeL3TestClient.Client.SendTransaction(ctx, tx)
// Require(t, err)
// _, err = firstNodeL3TestClient.EnsureTxSucceeded(tx)
// Require(t, err)
// _, err = WaitForTx(ctx, secondNodeL3TestClient.Client, tx.Hash(), time.Second*15)
// Require(t, err)
//
// // Check if L3's parent chain is using EIP-7623
// isUsingEIP7623 = builder.L3.ConsensusNode.BatchPoster.GetParentChainIsUsingEIP7623(ctx)
// if isUsingEIP7623 == nil {
// t.Fatal("Failed to get parent chain EIP-7623 status")
// }
// if *isUsingEIP7623 {
// t.Fatal("L3's parent chain should not be using EIP-7623")
// }
// }

0 comments on commit bceef0d

Please sign in to comment.