From 5c99fe12a3bf83eeba80b7e51a637ecf8b858614 Mon Sep 17 00:00:00 2001 From: StefanIliev545 Date: Thu, 21 Dec 2023 06:52:49 +0200 Subject: [PATCH 01/26] Fixes. --- go/common/types.go | 14 +++ go/enclave/components/batch_executor.go | 48 ++++++---- go/enclave/enclave.go | 52 ++++++++-- go/enclave/evm/evm_facade.go | 89 ++++++++++++++---- go/enclave/gas/oracle.go | 15 +++ go/host/rpc/clientapi/client_api_eth.go | 22 ++++- integration/common/constants.go | 2 +- integration/eth2network/eth2_configs.go | 2 +- .../helpful/spin_up_local_network_test.go | 1 - tools/walletextension/README.md | 2 +- tools/walletextension/api/static/favicon.ico | Bin 996 -> 0 bytes tools/walletextension/container_run.sh | 6 +- 12 files changed, 201 insertions(+), 52 deletions(-) delete mode 100644 tools/walletextension/api/static/favicon.ico diff --git a/go/common/types.go b/go/common/types.go index d3afa6def0..8fe0ec7e09 100644 --- a/go/common/types.go +++ b/go/common/types.go @@ -44,6 +44,12 @@ type ( L2Receipt = types.Receipt L2Receipts = types.Receipts + L2PricedTransaction struct { + Tx *L2Tx + PublishingCost *big.Int + } + L2PricedTransactions []L2PricedTransaction + CrossChainMessage = MessageBus.StructsCrossChainMessage CrossChainMessages = []CrossChainMessage ValueTransferEvent struct { @@ -72,6 +78,14 @@ type ( EncodedBatchRequest []byte ) +func (txs L2PricedTransactions) ToTransactions() types.Transactions { + ret := make(types.Transactions, 0) + for _, tx := range txs { + ret = append(ret, tx.Tx) + } + return ret +} + const ( L2GenesisHeight = uint64(0) L1GenesisHeight = uint64(0) diff --git a/go/enclave/components/batch_executor.go b/go/enclave/components/batch_executor.go index 226486461d..9be6ff2cf6 100644 --- a/go/enclave/components/batch_executor.go +++ b/go/enclave/components/batch_executor.go @@ -66,9 +66,9 @@ func NewBatchExecutor( // payL1Fees - this function modifies the state db according to the transactions contained within the batch context // in order to subtract gas fees from the balance. It returns a list of the transactions that have prepaid for their L1 // publishing costs. -func (executor *batchExecutor) payL1Fees(stateDB *state.StateDB, context *BatchExecutionContext) (common.L2Transactions, common.L2Transactions) { - transactions := make(common.L2Transactions, 0) - freeTransactions := make(common.L2Transactions, 0) +func (executor *batchExecutor) payL1Fees(stateDB *state.StateDB, context *BatchExecutionContext) (common.L2PricedTransactions, common.L2PricedTransactions) { + transactions := make(common.L2PricedTransactions, 0) + freeTransactions := make(common.L2PricedTransactions, 0) block, _ := executor.storage.FetchBlock(context.BlockPtr) for _, tx := range context.Transactions { @@ -93,18 +93,25 @@ func (executor *batchExecutor) payL1Fees(stateDB *state.StateDB, context *BatchE isFreeTransaction = isFreeTransaction && tx.GasPrice().Cmp(gethcommon.Big0) == 0 if isFreeTransaction { - freeTransactions = append(freeTransactions, tx) + freeTransactions = append(freeTransactions, common.L2PricedTransaction{ + Tx: tx, + PublishingCost: big.NewInt(0), + }) continue } if accBalance.Cmp(cost) == -1 { executor.logger.Info(fmt.Sprintf("insufficient account balance for tx - want: %d have: %d", cost, accBalance), log.TxKey, tx.Hash(), "addr", sender.Hex()) continue } - stateDB.SubBalance(*sender, cost) - stateDB.AddBalance(context.Creator, cost) + + /*stateDB.SubBalance(*sender, cost) + stateDB.AddBalance(context.Creator, cost)*/ // todo - add refund logic. - transactions = append(transactions, tx) + transactions = append(transactions, common.L2PricedTransaction{ + Tx: tx, + PublishingCost: big.NewInt(0).Set(cost), + }) } return transactions, freeTransactions } @@ -180,16 +187,24 @@ func (executor *batchExecutor) ComputeBatch(context *BatchExecutionContext, fail transactionsToProcess, freeTransactions := executor.payL1Fees(stateDB, context) - crossChainTransactions = append(crossChainTransactions, freeTransactions...) + xchainTxs := make(common.L2PricedTransactions, 0) + for _, xTx := range crossChainTransactions { + xchainTxs = append(xchainTxs, common.L2PricedTransaction{ + Tx: xTx, + PublishingCost: big.NewInt(0), + }) + } + + xchainTxs = append(xchainTxs, freeTransactions...) successfulTxs, excludedTxs, txReceipts, err := executor.processTransactions(batch, 0, transactionsToProcess, stateDB, context.ChainConfig, false) if err != nil { return nil, fmt.Errorf("could not process transactions. Cause: %w", err) } - executor.refundL1Fees(stateDB, context, excludedTxs) + //executor.refundL1Fees(stateDB, context, excludedTxs) - ccSuccessfulTxs, _, ccReceipts, err := executor.processTransactions(batch, len(successfulTxs), crossChainTransactions, stateDB, context.ChainConfig, true) + ccSuccessfulTxs, _, ccReceipts, err := executor.processTransactions(batch, len(successfulTxs), xchainTxs, stateDB, context.ChainConfig, true) if err != nil { return nil, err } @@ -201,7 +216,7 @@ func (executor *batchExecutor) ComputeBatch(context *BatchExecutionContext, fail // we need to copy the batch to reset the internal hash cache copyBatch := *batch copyBatch.Header.Root = stateDB.IntermediateRoot(false) - copyBatch.Transactions = append(successfulTxs, freeTransactions...) + copyBatch.Transactions = append(successfulTxs, freeTransactions.ToTransactions()...) copyBatch.ResetHash() if err = executor.populateOutboundCrossChainData(©Batch, block, txReceipts); err != nil { @@ -222,6 +237,7 @@ func (executor *batchExecutor) ComputeBatch(context *BatchExecutionContext, fail // the logs and receipts produced by the EVM have the wrong hash which must be adjusted for _, receipt := range allReceipts { + executor.logger.Info("New receipt! ", log.TxKey, receipt.TxHash) receipt.BlockHash = copyBatch.Hash() for _, l := range receipt.Logs { l.BlockHash = copyBatch.Hash() @@ -400,7 +416,7 @@ func (executor *batchExecutor) verifyInboundCrossChainTransactions(transactions func (executor *batchExecutor) processTransactions( batch *core.Batch, tCount int, - txs []*common.L2Tx, + txs common.L2PricedTransactions, stateDB *state.StateDB, cc *params.ChainConfig, noBaseFee bool, @@ -411,18 +427,18 @@ func (executor *batchExecutor) processTransactions( txResults := evm.ExecuteTransactions(txs, stateDB, batch.Header, executor.storage, cc, tCount, noBaseFee, executor.logger) for _, tx := range txs { - result, f := txResults[tx.Hash()] + result, f := txResults[tx.Tx.Hash()] if !f { return nil, nil, nil, fmt.Errorf("there should be an entry for each transaction") } rec, foundReceipt := result.(*types.Receipt) if foundReceipt { - executedTransactions = append(executedTransactions, tx) + executedTransactions = append(executedTransactions, tx.Tx) txReceipts = append(txReceipts, rec) } else { // Exclude all errors - excludedTransactions = append(excludedTransactions, tx) - executor.logger.Info("Excluding transaction from batch", log.TxKey, tx.Hash(), log.BatchHashKey, batch.Hash(), "cause", result) + excludedTransactions = append(excludedTransactions, tx.Tx) + executor.logger.Info("Excluding transaction from batch", log.TxKey, tx.Tx.Hash(), log.BatchHashKey, batch.Hash(), "cause", result) } } sort.Sort(sortByTxIndex(txReceipts)) diff --git a/go/enclave/enclave.go b/go/enclave/enclave.go index 88025246f3..8ff00056e3 100644 --- a/go/enclave/enclave.go +++ b/go/enclave/enclave.go @@ -77,9 +77,10 @@ type enclaveImpl struct { crossChainProcessors *crosschain.Processors sharedSecretProcessor *components.SharedSecretProcessor - chain l2chain.ObscuroChain - service nodetype.NodeType - registry components.BatchRegistry + chain l2chain.ObscuroChain + service nodetype.NodeType + registry components.BatchRegistry + gasOracle gas.Oracle // todo (#627) - use the ethconfig.Config instead GlobalGasCap uint64 // 5_000_000_000, // todo (#627) - make config @@ -271,9 +272,10 @@ func NewEnclave( debugger: debug, stopControl: stopcontrol.New(), - chain: chain, - registry: registry, - service: service, + chain: chain, + registry: registry, + service: service, + gasOracle: gasOracle, GlobalGasCap: 5_000_000_000, // todo (#627) - make config BaseFee: gethcommon.Big0, @@ -684,6 +686,20 @@ func (e *enclaveImpl) GetTransactionCount(encryptedParams common.EncryptedParams address := gethcommon.HexToAddress(addressStr) + seqNo := e.registry.HeadBatchSeq().Uint64() + if len(paramList) == 3 { + tag, err := gethencoding.ExtractBlockNumber(paramList[2]) + if err != nil { + return responses.AsPlaintextError(fmt.Errorf("unexpected tag parameter. Cause: %w", err)), nil + } + + b, err := e.registry.GetBatchAtHeight(*tag) + if err != nil { + return responses.AsPlaintextError(fmt.Errorf("cant retrieve batch for tag. Cause: %w", err)), nil + } + seqNo = b.SeqNo().Uint64() + } + // extract, create and validate the VK encryption handler vkHandler, err := createVKHandler(&address, paramList[0], e.config.ObscuroChainID) if err != nil { @@ -691,7 +707,7 @@ func (e *enclaveImpl) GetTransactionCount(encryptedParams common.EncryptedParams } var nonce uint64 - l2Head, err := e.storage.FetchBatchBySeqNo(e.registry.HeadBatchSeq().Uint64()) + l2Head, err := e.storage.FetchBatchBySeqNo(seqNo) if err == nil { // todo - we should return an error when head state is not available, but for current test situations with race // conditions we allow it to return zero while head state is uninitialized @@ -1028,6 +1044,24 @@ func (e *enclaveImpl) EstimateGas(encryptedParams common.EncryptedParamsEstimate return responses.AsEncryptedError(err, vkHandler), nil } + block, err := e.blockResolver.FetchHeadBlock() + if err != nil { + return responses.AsPlaintextError(fmt.Errorf("internal server error")), err + } + + l1Cost, err := e.gasOracle.EstimateL1CostForMsg(callMsg, block) + if err != nil { + return responses.AsPlaintextError(fmt.Errorf("internal server error")), err + } + + batch, err := e.storage.FetchHeadBatch() + if err != nil { + return responses.AsPlaintextError(fmt.Errorf("internal server error")), err + } + + publishingGas := big.NewInt(0).Div(l1Cost, batch.Header.BaseFee) + publishingGas.Add(publishingGas, big.NewInt(0).Mod(l1Cost, batch.Header.BaseFee)) + executionGasEstimate, err := e.DoEstimateGas(callMsg, blockNumber, e.GlobalGasCap) if err != nil { err = fmt.Errorf("unable to estimate transaction - %w", err) @@ -1045,7 +1079,9 @@ func (e *enclaveImpl) EstimateGas(encryptedParams common.EncryptedParamsEstimate return responses.AsEncryptedError(err, vkHandler), nil } - return responses.AsEncryptedResponse(&executionGasEstimate, vkHandler), nil + totalGasEstimate := hexutil.Uint64(publishingGas.Uint64() + uint64(executionGasEstimate)) + + return responses.AsEncryptedResponse(&totalGasEstimate, vkHandler), nil } func (e *enclaveImpl) GetLogs(encryptedParams common.EncryptedParamsGetLogs) (*responses.Logs, common.SystemError) { //nolint diff --git a/go/enclave/evm/evm_facade.go b/go/enclave/evm/evm_facade.go index cb841a5311..acb5ffaba7 100644 --- a/go/enclave/evm/evm_facade.go +++ b/go/enclave/evm/evm_facade.go @@ -5,6 +5,7 @@ import ( "fmt" "math" "math/big" + _ "unsafe" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common/hexutil" @@ -31,7 +32,7 @@ import ( // header - the header of the rollup where this transaction will be included // fromTxIndex - for the receipts and events, the evm needs to know for each transaction the order in which it was executed in the block. func ExecuteTransactions( - txs []*common.L2Tx, + txs common.L2PricedTransactions, s *state.StateDB, header *common.BatchHeader, storage storage.Storage, @@ -67,24 +68,27 @@ func ExecuteTransactions( header.Number.Uint64(), ) if err != nil { - result[t.Hash()] = err - logger.Info("Failed to execute tx:", log.TxKey, t.Hash(), log.CtrErrKey, err) + result[t.Tx.Hash()] = err + logger.Info("Failed to execute tx:", log.TxKey, t.Tx.Hash(), log.CtrErrKey, err) continue } - result[t.Hash()] = r + result[t.Tx.Hash()] = r logReceipt(r, logger) } s.Finalise(true) return result } +//go:linkname applyTransaction github.com/ethereum/go-ethereum/core.applyTransaction +func applyTransaction(msg *gethcore.Message, config *params.ChainConfig, gp *gethcore.GasPool, statedb *state.StateDB, blockNumber *big.Int, blockHash gethcommon.Hash, tx *types.Transaction, usedGas *uint64, evm *vm.EVM) (*types.Receipt, error) + func executeTransaction( s *state.StateDB, cc *params.ChainConfig, chain *ObscuroChainContext, gp *gethcore.GasPool, header *types.Header, - t *common.L2Tx, + t common.L2PricedTransaction, usedGas *uint64, vmCfg vm.Config, tCount int, @@ -92,26 +96,62 @@ func executeTransaction( batchHeight uint64, ) (*types.Receipt, error) { rules := cc.Rules(big.NewInt(0), true, 0) - from, err := types.Sender(types.LatestSigner(cc), t) + from, err := types.Sender(types.LatestSigner(cc), t.Tx) if err != nil { return nil, err } - s.Prepare(rules, from, gethcommon.Address{}, t.To(), nil, nil) + s.Prepare(rules, from, gethcommon.Address{}, t.Tx.To(), nil, nil) snap := s.Snapshot() - s.SetTxContext(t.Hash(), tCount) + s.SetTxContext(t.Tx.Hash(), tCount) before := header.MixDigest // calculate a random value per transaction header.MixDigest = crypto.CalculateTxRnd(before.Bytes(), tCount) - receipt, err := gethcore.ApplyTransaction(cc, chain, nil, gp, s, header, t, usedGas, vmCfg) - // adjust the receipt to point to the right batch hash - if receipt != nil { - receipt.Logs = s.GetLogs(t.Hash(), batchHeight, batchHash) - receipt.BlockHash = batchHash - receipt.BlockNumber = big.NewInt(int64(batchHeight)) - for _, l := range receipt.Logs { - l.BlockHash = batchHash + applyTx := func( + config *params.ChainConfig, + bc gethcore.ChainContext, + author *gethcommon.Address, + gp *gethcore.GasPool, + statedb *state.StateDB, + header *types.Header, + tx common.L2PricedTransaction, + usedGas *uint64, + cfg vm.Config, + ) (*types.Receipt, error) { + msg, err := gethcore.TransactionToMessage(tx.Tx, types.MakeSigner(config, header.Number, header.Time), header.BaseFee) + if err != nil { + return nil, err + } + l1cost := tx.PublishingCost + l1Gas := big.NewInt(0) + hasL1Cost := l1cost.Cmp(big.NewInt(0)) != 0 + + if hasL1Cost { + l1Gas.Div(l1cost, header.BaseFee) + l1Gas.Add(l1Gas, big.NewInt(0).Mod(l1cost, header.BaseFee)) + + if msg.GasLimit < l1Gas.Uint64() { + return nil, fmt.Errorf("gas limit for tx too low. Want at least: %d have: %d", l1Gas, msg.GasLimit) + } + msg.GasLimit -= l1Gas.Uint64() + + statedb.SubBalance(msg.From, l1cost) + statedb.AddBalance(header.Coinbase, l1cost) + + } + + // Create a new context to be used in the EVM environment + blockContext := gethcore.NewEVMBlockContext(header, bc, author) + vmenv := vm.NewEVM(blockContext, vm.TxContext{BlobHashes: tx.Tx.BlobHashes()}, statedb, config, cfg) + receipt, err := applyTransaction(msg, config, gp, statedb, header.Number, header.Hash(), tx.Tx, usedGas, vmenv) + if err != nil { + if hasL1Cost { + statedb.SubBalance(header.Coinbase, l1cost) + statedb.AddBalance(msg.From, l1cost) + } + + return receipt, err } // Do not increase the balance of zero address as it is the contract deployment address. @@ -121,7 +161,22 @@ func executeTransaction( executionGasCost := big.NewInt(0).Mul(gasUsed, header.BaseFee) // As the baseFee is burned, we add it back to the coinbase. // Geth should automatically add the tips. - s.AddBalance(header.Coinbase, executionGasCost) + statedb.AddBalance(header.Coinbase, executionGasCost) + } + receipt.GasUsed += l1Gas.Uint64() + + return receipt, err + } + + receipt, err := applyTx(cc, chain, nil, gp, s, header, t, usedGas, vmCfg) + + // adjust the receipt to point to the right batch hash + if receipt != nil { + receipt.Logs = s.GetLogs(t.Tx.Hash(), batchHeight, batchHash) + receipt.BlockHash = batchHash + receipt.BlockNumber = big.NewInt(int64(batchHeight)) + for _, l := range receipt.Logs { + l.BlockHash = batchHash } } diff --git a/go/enclave/gas/oracle.go b/go/enclave/gas/oracle.go index 31ff3ae3fa..efa13c3ebe 100644 --- a/go/enclave/gas/oracle.go +++ b/go/enclave/gas/oracle.go @@ -4,7 +4,9 @@ import ( "math/big" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rlp" + "github.com/ten-protocol/go-ten/go/common/gethapi" ) // Oracle - the interface for the future precompiled gas oracle contract @@ -12,6 +14,7 @@ import ( type Oracle interface { ProcessL1Block(block *types.Block) EstimateL1StorageGasCost(tx *types.Transaction, block *types.Block) (*big.Int, error) + EstimateL1CostForMsg(args *gethapi.TransactionArgs, block *types.Block) (*big.Int, error) } type oracle struct { @@ -49,3 +52,15 @@ func (o *oracle) EstimateL1StorageGasCost(tx *types.Transaction, block *types.Bl l1Gas := CalculateL1GasUsed(encodedTx, big.NewInt(0)) return big.NewInt(0).Mul(l1Gas, block.BaseFee()), nil } + +func (o *oracle) EstimateL1CostForMsg(args *gethapi.TransactionArgs, block *types.Block) (*big.Int, error) { + encoded := make([]byte, 0) + if args.Data != nil { + encoded = append(encoded, *args.Data...) + } + + nonZeroGas := big.NewInt(int64(params.TxDataNonZeroGasEIP2028)) + overhead := big.NewInt(0).Mul(big.NewInt(150), nonZeroGas) + l1Gas := CalculateL1GasUsed(encoded, overhead) + return big.NewInt(0).Mul(l1Gas, block.BaseFee()), nil +} diff --git a/go/host/rpc/clientapi/client_api_eth.go b/go/host/rpc/clientapi/client_api_eth.go index 49bdfe03bf..672d1f7e39 100644 --- a/go/host/rpc/clientapi/client_api_eth.go +++ b/go/host/rpc/clientapi/client_api_eth.go @@ -184,15 +184,29 @@ func (api *EthereumAPI) GetStorageAt(_ context.Context, encryptedParams common.E // FeeHistory is a placeholder for an RPC method required by MetaMask/Remix. // rpc.DecimalOrHex -> []byte -func (api *EthereumAPI) FeeHistory(context.Context, []byte, rpc.BlockNumber, []float64) (*FeeHistoryResult, error) { +func (api *EthereumAPI) FeeHistory(context.Context, string, rpc.BlockNumber, []float64) (*FeeHistoryResult, error) { // todo (#1621) - return a non-dummy fee history + header, err := api.host.DB().GetHeadBatchHeader() + if err != nil { + api.logger.Error(fmt.Sprintf("Unable to retrieve header for fee history. Cause: %w", err)) + return nil, fmt.Errorf("unable to retrieve fee history") + } + + batches := make([]*common.BatchHeader, 0) + batches = append(batches, header) - return &FeeHistoryResult{ - OldestBlock: (*hexutil.Big)(big.NewInt(0)), + feeHist := &FeeHistoryResult{ + OldestBlock: (*hexutil.Big)(header.Number), Reward: [][]*hexutil.Big{}, BaseFee: []*hexutil.Big{}, GasUsedRatio: []float64{}, - }, nil + } + + for _, header := range batches { + feeHist.GasUsedRatio = append(feeHist.GasUsedRatio, 0.9) //todo @siliev - fix when baseFee is dynamic + feeHist.BaseFee = append(feeHist.BaseFee, (*hexutil.Big)(header.BaseFee)) + } + return feeHist, nil } // FeeHistoryResult is the structure returned by Geth `eth_feeHistory` API. diff --git a/integration/common/constants.go b/integration/common/constants.go index 63e4ab993c..04ffcc1417 100644 --- a/integration/common/constants.go +++ b/integration/common/constants.go @@ -83,7 +83,7 @@ func DefaultEnclaveConfig() *config.EnclaveConfig { MaxBatchSize: 1024 * 25, MaxRollupSize: 1024 * 64, GasPaymentAddress: gethcommon.HexToAddress("0xd6C9230053f45F873Cb66D8A02439380a37A4fbF"), - BaseFee: new(big.Int).SetUint64(1), + BaseFee: new(big.Int).SetUint64(params.InitialBaseFee / 100), GasLimit: new(big.Int).SetUint64(params.MaxGasLimit / 6), } } diff --git a/integration/eth2network/eth2_configs.go b/integration/eth2network/eth2_configs.go index 582095f855..8921fb97b4 100644 --- a/integration/eth2network/eth2_configs.go +++ b/integration/eth2network/eth2_configs.go @@ -46,7 +46,7 @@ BELLATRIX_FORK_VERSION: 0x20000089 TERMINAL_TOTAL_DIFFICULTY: 10 # Capella -CAPELLA_FORK_EPOCH: 90000000000000000 +CAPELLA_FORK_EPOCH: 90000000000000000 CAPELLA_FORK_VERSION: 0x20000089 # Time parameters diff --git a/integration/networktest/tests/helpful/spin_up_local_network_test.go b/integration/networktest/tests/helpful/spin_up_local_network_test.go index 83a5f4888c..753076a87e 100644 --- a/integration/networktest/tests/helpful/spin_up_local_network_test.go +++ b/integration/networktest/tests/helpful/spin_up_local_network_test.go @@ -30,7 +30,6 @@ const ( ) func TestRunLocalNetwork(t *testing.T) { - networktest.TestOnlyRunsInIDE(t) networktest.EnsureTestLogsSetUp("local-geth-network") networkConnector, cleanUp, err := env.LocalDevNetwork().Prepare() if err != nil { diff --git a/tools/walletextension/README.md b/tools/walletextension/README.md index d11b4da5cc..e7d7a3c331 100644 --- a/tools/walletextension/README.md +++ b/tools/walletextension/README.md @@ -12,7 +12,7 @@ following commands from the `tools/walletextension/main` folder: ``` env GOOS=darwin GOARCH=amd64 go build -o ../bin/wallet_extension_macos_amd64 . -env GOOS=darwin GOARCH=arm64 go build -o ../bin/wallet_extension_macos_arm64 . + env GOOS=darwin GOARCH=arm64 go build -o ../bin/wallet_extension_macos_arm64 . env GOOS=windows GOARCH=amd64 go build -o ../bin/wallet_extension_win_amd64.exe . env GOOS=linux GOARCH=amd64 go build -o ../bin/wallet_extension_linux_amd64 . ``` diff --git a/tools/walletextension/api/static/favicon.ico b/tools/walletextension/api/static/favicon.ico deleted file mode 100644 index 1bb8f324a18a956628274ccbacffa64f1eeabc5f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 996 zcmVPx#1ZP1_K>z@;j|==^1poj532;bRa{vGf6951U69E94oEQKA19?eAK~!i%?U_#~ zJy8_L&-2LhzsUcxV_`wrVId1ik%*KXODVFjKv~Jw#!6W}DK?~}Y$R4F3Qmu&@xu#>QZ6Z4C|%4q#_z2cpp^bar+^I2`7v z-(!^1QdU${gfuWZ866!J#(r5>R~J4$K612|?d@$WC@2v2l{BH#Wl2d%I5aeb4-XGK z?0?3`$Ax_iYiw-9_xE>>^k;8x4V$FMS=?QS9vo;I0SyMr%ggMIPjz)QD}eR&byjXpPEO$R@{+II zePof^Mrp1By&%4dPkMSf(2m7d0LRD2th_kejF%h^Ykz!IR7m=!>6ZLMjs3=a>p0ysN6gWcU-Q&aH>R0u+SeLW;3#D7Hl zSQeR4I?#=_>Gz(v;vRtJZ02Ys1XUOe`rW z!KtY!Zn5a=>$AtC?+o@LPESwUejgJ$ZR_dj;akZuJ3DLlr4Juh-Q>r{#)e(UWoKuz z*W&K(&c2_>;{Ja!GBQ}nk(HIj3Set%3)6-(tuC7dN zaCCIUN=)1zIE>S=zrP=Hb933_kFonui40Wxv&SMQCkJ|adx5G=^Yilc_0_C_78e&` zWo5;4fK^sj!rDtj^(ZA5BMkk;eoq%d|0; Date: Thu, 21 Dec 2023 07:10:51 +0200 Subject: [PATCH 02/26] More fixes. --- integration/common/constants.go | 2 +- integration/common/utils.go | 4 +++- integration/simulation/simulation.go | 5 +++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/integration/common/constants.go b/integration/common/constants.go index 04ffcc1417..87f471389f 100644 --- a/integration/common/constants.go +++ b/integration/common/constants.go @@ -83,7 +83,7 @@ func DefaultEnclaveConfig() *config.EnclaveConfig { MaxBatchSize: 1024 * 25, MaxRollupSize: 1024 * 64, GasPaymentAddress: gethcommon.HexToAddress("0xd6C9230053f45F873Cb66D8A02439380a37A4fbF"), - BaseFee: new(big.Int).SetUint64(params.InitialBaseFee / 100), + BaseFee: new(big.Int).SetUint64(1), //params.InitialBaseFee / 100), GasLimit: new(big.Int).SetUint64(params.MaxGasLimit / 6), } } diff --git a/integration/common/utils.go b/integration/common/utils.go index 676e6db689..dfd4f082b1 100644 --- a/integration/common/utils.go +++ b/integration/common/utils.go @@ -96,13 +96,15 @@ func PrefundWallets(ctx context.Context, faucetWallet wallet.Wallet, faucetClien txHashes := make([]gethcommon.Hash, len(wallets)) for idx, w := range wallets { destAddr := w.Address() - tx := &types.LegacyTx{ + txData := &types.LegacyTx{ Nonce: startingNonce + uint64(idx), Value: alloc, Gas: uint64(1_000_000), GasPrice: gethcommon.Big1, To: &destAddr, } + + tx := faucetClient.EstimateGasAndGasPrice(txData) signedTx, err := faucetWallet.SignTransaction(tx) if err != nil { panic(err) diff --git a/integration/simulation/simulation.go b/integration/simulation/simulation.go index e8c697afd2..aed705d603 100644 --- a/integration/simulation/simulation.go +++ b/integration/simulation/simulation.go @@ -225,7 +225,7 @@ func (s *Simulation) deployObscuroERC20s() { // 0x526c84529b2b8c11f57d93d3f5537aca3aecef9b - this is the address of the L2 contract which is currently hardcoded. contractBytes := erc20contract.L2BytecodeWithDefaultSupply(string(token), gethcommon.HexToAddress("0x526c84529b2b8c11f57d93d3f5537aca3aecef9b")) - deployContractTx := types.DynamicFeeTx{ + deployContractTxData := types.DynamicFeeTx{ Nonce: NextNonce(s.ctx, s.RPCHandles, owner), Gas: 1025_000_000, GasFeeCap: gethcommon.Big1, // This field is used to derive the gas price for dynamic fee transactions. @@ -233,7 +233,8 @@ func (s *Simulation) deployObscuroERC20s() { GasTipCap: gethcommon.Big1, } - signedTx, err := owner.SignTransaction(&deployContractTx) + deployContractTx := s.RPCHandles.ObscuroWalletRndClient(owner).EstimateGasAndGasPrice(&deployContractTxData) + signedTx, err := owner.SignTransaction(deployContractTx) if err != nil { panic(err) } From 18b5ebdbde4ac93c74fb91bb747b37b93f5322af Mon Sep 17 00:00:00 2001 From: StefanIliev545 Date: Thu, 21 Dec 2023 08:43:27 +0200 Subject: [PATCH 03/26] Fixes?. --- .../simulation/transaction_injector.go | 33 +++++++++---------- .../transaction_injector_tracker.go | 2 +- tools/hardhatdeployer/obscuro_deployer.go | 3 +- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/integration/simulation/transaction_injector.go b/integration/simulation/transaction_injector.go index 497470a86c..66e142abc9 100644 --- a/integration/simulation/transaction_injector.go +++ b/integration/simulation/transaction_injector.go @@ -141,10 +141,10 @@ func (ti *TransactionInjector) Start() { }) } - wg.Go(func() error { + /*wg.Go(func() error { ti.issueRandomTransfers() return nil - }) + })*/ //todo - fix wg.Go(func() error { ti.issueRandomValueTransfers() @@ -219,7 +219,7 @@ func (ti *TransactionInjector) issueRandomTransfers() { for len(ti.wallets.SimObsWallets) > 1 && fromWallet.Address().Hex() == toWallet.Address().Hex() { toWallet = ti.rndObsWallet() } - tx := ti.newObscuroTransferTx(fromWallet, toWallet.Address(), testcommon.RndBtw(1, 500)) + tx := ti.newObscuroTransferTx(fromWallet, toWallet.Address(), testcommon.RndBtw(1, 500), testcommon.HOC) tx = obscuroClient.EstimateGasAndGasPrice(tx) signedTx, err := fromWallet.SignTransaction(tx) if err != nil { @@ -287,24 +287,22 @@ func (ti *TransactionInjector) bridgeRandomGasTransfers() { func (ti *TransactionInjector) issueRandomDeposits() { // todo (@stefan) - this implementation transfers from the hoc and poc owner contracts // a better implementation should use the bridge - fromWalletHoc := ti.wallets.Tokens[testcommon.HOC].L2Owner - fromWalletPoc := ti.wallets.Tokens[testcommon.POC].L2Owner - for txCounter := 0; ti.shouldKeepIssuing(txCounter); txCounter++ { - fromWallet := fromWalletHoc + fromWalletToken := testcommon.HOC if txCounter%2 == 0 { - fromWallet = fromWalletPoc + fromWalletToken = testcommon.POC } + fromWallet := ti.wallets.Tokens[fromWalletToken].L2Owner toWallet := ti.rndObsWallet() obscuroClient := ti.rpcHandles.ObscuroWalletRndClient(fromWallet) v := testcommon.RndBtw(500, 2000) - tx := ti.newObscuroTransferTx(fromWallet, toWallet.Address(), v) - tx = obscuroClient.EstimateGasAndGasPrice(tx) + txData := ti.newObscuroTransferTx(fromWallet, toWallet.Address(), v, fromWalletToken) + tx := obscuroClient.EstimateGasAndGasPrice(txData) signedTx, err := fromWallet.SignTransaction(tx) if err != nil { panic(err) } - ti.logger.Info("Deposit transaction injected into L2.", log.TxKey, signedTx.Hash(), "fromAddress", fromWallet.Address(), "toAddress", toWallet.Address()) + ti.logger.Info("Deposit transaction injected into L2.", log.TxKey, signedTx.Hash(), "fromAddress", fromWallet.Address(), "toAddress", toWallet.Address()) ti.stats.Deposit(big.NewInt(int64(v))) @@ -337,8 +335,9 @@ func (ti *TransactionInjector) issueInvalidL2Txs() { for len(ti.wallets.SimObsWallets) > 1 && fromWallet.Address().Hex() == toWallet.Address().Hex() { toWallet = ti.rndObsWallet() } - tx := ti.newCustomObscuroWithdrawalTx(testcommon.RndBtw(1, 100)) + txData := ti.newCustomObscuroWithdrawalTx(testcommon.RndBtw(1, 100)) + tx := ti.rpcHandles.ObscuroWalletRndClient(fromWallet).EstimateGasAndGasPrice(txData) signedTx := ti.createInvalidSignage(tx, fromWallet) err := ti.rpcHandles.ObscuroWalletRndClient(fromWallet).SendTransaction(ti.ctx, signedTx) @@ -368,24 +367,24 @@ func (ti *TransactionInjector) rndObsWallet() wallet.Wallet { return ti.wallets.SimObsWallets[rand.Intn(len(ti.wallets.SimObsWallets))] //nolint:gosec } -func (ti *TransactionInjector) newObscuroTransferTx(from wallet.Wallet, dest gethcommon.Address, amount uint64) types.TxData { +func (ti *TransactionInjector) newObscuroTransferTx(from wallet.Wallet, dest gethcommon.Address, amount uint64, ercType testcommon.ERC20) types.TxData { data := erc20contractlib.CreateTransferTxData(dest, common.ValueInWei(big.NewInt(int64(amount)))) - return ti.newTx(data, from.GetNonceAndIncrement()) + return ti.newTx(data, from.GetNonceAndIncrement(), ercType) } func (ti *TransactionInjector) newCustomObscuroWithdrawalTx(amount uint64) types.TxData { transferERC20data := erc20contractlib.CreateTransferTxData(testcommon.BridgeAddress, common.ValueInWei(big.NewInt(int64(amount)))) - return ti.newTx(transferERC20data, 1) + return ti.newTx(transferERC20data, 1, testcommon.HOC) } -func (ti *TransactionInjector) newTx(data []byte, nonce uint64) types.TxData { +func (ti *TransactionInjector) newTx(data []byte, nonce uint64, ercType testcommon.ERC20) types.TxData { return &types.LegacyTx{ Nonce: nonce, Value: gethcommon.Big0, Gas: uint64(1_000_000), GasPrice: gethcommon.Big1, Data: data, - To: ti.wallets.Tokens[testcommon.HOC].L2ContractAddress, + To: ti.wallets.Tokens[ercType].L2ContractAddress, } } diff --git a/integration/simulation/transaction_injector_tracker.go b/integration/simulation/transaction_injector_tracker.go index b0fe77dab5..b1c36a1247 100644 --- a/integration/simulation/transaction_injector_tracker.go +++ b/integration/simulation/transaction_injector_tracker.go @@ -62,7 +62,7 @@ func (m *txInjectorTracker) trackTransferL2Tx(tx *common.L2Tx) { func (m *txInjectorTracker) trackNativeValueTransferL2Tx(tx *common.L2Tx) { m.l2TransactionsLock.Lock() defer m.l2TransactionsLock.Unlock() - m.NativeValueTransferL2Transactions = append(m.TransferL2Transactions, tx) + m.NativeValueTransferL2Transactions = append(m.NativeValueTransferL2Transactions, tx) } // GetL1Transactions returns all generated L1 L2Txs diff --git a/tools/hardhatdeployer/obscuro_deployer.go b/tools/hardhatdeployer/obscuro_deployer.go index a3e4153e75..c3ab1b9cea 100644 --- a/tools/hardhatdeployer/obscuro_deployer.go +++ b/tools/hardhatdeployer/obscuro_deployer.go @@ -60,13 +60,14 @@ func fundDeployerWithFaucet(cfg *Config, client *obsclient.AuthObsClient, logger } destAddr := client.Address() - tx := &types.LegacyTx{ + txData := &types.LegacyTx{ Nonce: nonce, Value: big.NewInt(Prealloc), Gas: uint64(1_000_000), GasPrice: gethcommon.Big1, To: &destAddr, } + tx := faucetClient.EstimateGasAndGasPrice(txData) signedTx, err := faucetWallet.SignTransaction(tx) if err != nil { return fmt.Errorf("failed to sign faucet transaction: %w", err) From 3b57b36eedcdf27ff0d310cf729c7a1d7f626d46 Mon Sep 17 00:00:00 2001 From: StefanIliev545 Date: Thu, 21 Dec 2023 08:46:56 +0200 Subject: [PATCH 04/26] log change. --- integration/simulation/transaction_injector.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration/simulation/transaction_injector.go b/integration/simulation/transaction_injector.go index 66e142abc9..c289a67c33 100644 --- a/integration/simulation/transaction_injector.go +++ b/integration/simulation/transaction_injector.go @@ -192,7 +192,7 @@ func (ti *TransactionInjector) issueRandomValueTransfers() { if err != nil { panic(err) } - ti.logger.Info("Transfer transaction injected into L2.", log.TxKey, signedTx.Hash(), "fromAddress", fromWallet.Address(), "toAddress", toWallet.Address()) + ti.logger.Info("Native value transfer transaction injected into L2.", log.TxKey, signedTx.Hash(), "fromAddress", fromWallet.Address(), "toAddress", toWallet.Address()) ti.stats.Transfer() From d26086044f326b7dbcee97085c4914f747d238ad Mon Sep 17 00:00:00 2001 From: StefanIliev545 Date: Thu, 21 Dec 2023 09:08:59 +0200 Subject: [PATCH 05/26] More fixes for sim tests. --- integration/simulation/output_stats.go | 2 ++ integration/simulation/stats/stats.go | 7 +++++++ integration/simulation/transaction_injector.go | 2 +- .../simulation/transaction_injector_tracker.go | 13 +++++++------ 4 files changed, 17 insertions(+), 7 deletions(-) diff --git a/integration/simulation/output_stats.go b/integration/simulation/output_stats.go index 0d886d60e3..fb810592d6 100644 --- a/integration/simulation/output_stats.go +++ b/integration/simulation/output_stats.go @@ -133,6 +133,7 @@ func (o *OutputStats) String() string { "totalWithdrawnAmount: %d\n"+ "rollupWithMoreRecentProof: %d\n"+ "nrTransferTransactions: %d\n"+ + "nrNativeTransferTransactions: %d\n"+ "nrBlockParsedERC20Deposits: %d\n"+ "gasBridgeCount: %d\n", o.simulation.Stats.NrMiners, @@ -151,6 +152,7 @@ func (o *OutputStats) String() string { o.simulation.Stats.TotalWithdrawalRequestedAmount, o.simulation.Stats.RollupWithMoreRecentProofCount, o.simulation.Stats.NrTransferTransactions, + o.simulation.Stats.NrNativeTransferTransactions, o.canonicalERC20DepositCount, len(o.simulation.TxInjector.TxTracker.GasBridgeTransactions), ) diff --git a/integration/simulation/stats/stats.go b/integration/simulation/stats/stats.go index 8e63970816..cf97f29dfe 100644 --- a/integration/simulation/stats/stats.go +++ b/integration/simulation/stats/stats.go @@ -27,6 +27,7 @@ type Stats struct { TotalWithdrawalRequestedAmount *big.Int RollupWithMoreRecentProofCount uint64 NrTransferTransactions int + NrNativeTransferTransactions int statsMu *sync.RWMutex } @@ -76,6 +77,12 @@ func (s *Stats) Transfer() { s.statsMu.Unlock() } +func (s *Stats) NativeTransfer() { + s.statsMu.Lock() + s.NrNativeTransferTransactions++ + s.statsMu.Unlock() +} + func (s *Stats) Withdrawal(v *big.Int) { s.statsMu.Lock() s.TotalWithdrawalRequestedAmount = s.TotalWithdrawalRequestedAmount.Add(s.TotalWithdrawalRequestedAmount, v) diff --git a/integration/simulation/transaction_injector.go b/integration/simulation/transaction_injector.go index c289a67c33..626d8a5d37 100644 --- a/integration/simulation/transaction_injector.go +++ b/integration/simulation/transaction_injector.go @@ -194,7 +194,7 @@ func (ti *TransactionInjector) issueRandomValueTransfers() { } ti.logger.Info("Native value transfer transaction injected into L2.", log.TxKey, signedTx.Hash(), "fromAddress", fromWallet.Address(), "toAddress", toWallet.Address()) - ti.stats.Transfer() + ti.stats.NativeTransfer() err = obscuroClient.SendTransaction(ti.ctx, signedTx) if err != nil { diff --git a/integration/simulation/transaction_injector_tracker.go b/integration/simulation/transaction_injector_tracker.go index b1c36a1247..6e189ef84b 100644 --- a/integration/simulation/transaction_injector_tracker.go +++ b/integration/simulation/transaction_injector_tracker.go @@ -28,12 +28,13 @@ type GasBridgingRecord struct { func newCounter() *txInjectorTracker { return &txInjectorTracker{ - l1TransactionsLock: sync.RWMutex{}, - L1Transactions: []ethadapter.L1Transaction{}, - l2TransactionsLock: sync.RWMutex{}, - TransferL2Transactions: []*common.L2Tx{}, - WithdrawalL2Transactions: []*common.L2Tx{}, - GasBridgeTransactions: []GasBridgingRecord{}, + l1TransactionsLock: sync.RWMutex{}, + L1Transactions: []ethadapter.L1Transaction{}, + l2TransactionsLock: sync.RWMutex{}, + TransferL2Transactions: []*common.L2Tx{}, + WithdrawalL2Transactions: []*common.L2Tx{}, + NativeValueTransferL2Transactions: []*common.L2Tx{}, + GasBridgeTransactions: []GasBridgingRecord{}, } } From f39a41df40510bd6dd7371d5be5c24066a0ae90c Mon Sep 17 00:00:00 2001 From: StefanIliev545 Date: Thu, 21 Dec 2023 09:33:43 +0200 Subject: [PATCH 06/26] Fix for native transfers. --- go/enclave/nodetype/sequencer.go | 10 ++++++++++ integration/simulation/transaction_injector.go | 2 +- integration/simulation/validate_chain.go | 1 + 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/go/enclave/nodetype/sequencer.go b/go/enclave/nodetype/sequencer.go index 71fdec925e..7acb20043d 100644 --- a/go/enclave/nodetype/sequencer.go +++ b/go/enclave/nodetype/sequencer.go @@ -194,6 +194,14 @@ func (s *sequencer) createGenesisBatch(block *common.L1Block) error { return nil } +type SortableTransactions types.Transactions + +func (c SortableTransactions) Len() int { return len(c) } +func (c SortableTransactions) Swap(i, j int) { c[i], c[j] = c[j], c[i] } +func (c SortableTransactions) Less(i, j int) bool { + return c[i].Nonce() < c[j].Nonce() +} + func (s *sequencer) createNewHeadBatch(l1HeadBlock *common.L1Block, skipBatchIfEmpty bool) error { headBatchSeq := s.batchRegistry.HeadBatchSeq() if headBatchSeq == nil { @@ -234,6 +242,8 @@ func (s *sequencer) createNewHeadBatch(l1HeadBlock *common.L1Block, skipBatchIfE } } + sort.Sort(SortableTransactions(transactions)) + sequencerNo, err := s.storage.FetchCurrentSequencerNo() if err != nil { return err diff --git a/integration/simulation/transaction_injector.go b/integration/simulation/transaction_injector.go index 626d8a5d37..cdb07400de 100644 --- a/integration/simulation/transaction_injector.go +++ b/integration/simulation/transaction_injector.go @@ -182,7 +182,7 @@ func (ti *TransactionInjector) issueRandomValueTransfers() { txData := &types.LegacyTx{ Nonce: fromWallet.GetNonceAndIncrement(), Value: big.NewInt(int64(testcommon.RndBtw(1, 500))), - Gas: uint64(1_000_000), + Gas: uint64(1_000_000_000), GasPrice: gethcommon.Big1, To: &toWalletAddr, } diff --git a/integration/simulation/validate_chain.go b/integration/simulation/validate_chain.go index 3f5db642ea..51a252c38f 100644 --- a/integration/simulation/validate_chain.go +++ b/integration/simulation/validate_chain.go @@ -474,6 +474,7 @@ func getLoggedWithdrawals(minObscuroHeight uint64, obscuroClient *obsclient.ObsC // FindNotIncludedL2Txs returns the number of transfers and withdrawals that were injected but are not present in the L2 blockchain. func FindNotIncludedL2Txs(ctx context.Context, nodeIdx int, rpcHandles *network.RPCHandles, txInjector *TransactionInjector) (int, int, int) { transfers, withdrawals, nativeTransfers := txInjector.TxTracker.GetL2Transactions() + notFoundTransfers := 0 for _, tx := range transfers { sender := getSender(tx) From 0796abe4e3d963f84d3c979492a1f63e6286d85e Mon Sep 17 00:00:00 2001 From: StefanIliev545 Date: Mon, 25 Dec 2023 17:21:29 +0200 Subject: [PATCH 07/26] gas limit change. --- integration/simulation/transaction_injector.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/integration/simulation/transaction_injector.go b/integration/simulation/transaction_injector.go index cdb07400de..c85e115c6c 100644 --- a/integration/simulation/transaction_injector.go +++ b/integration/simulation/transaction_injector.go @@ -144,7 +144,7 @@ func (ti *TransactionInjector) Start() { /*wg.Go(func() error { ti.issueRandomTransfers() return nil - })*/ //todo - fix + })*/ wg.Go(func() error { ti.issueRandomValueTransfers() @@ -381,7 +381,7 @@ func (ti *TransactionInjector) newTx(data []byte, nonce uint64, ercType testcomm return &types.LegacyTx{ Nonce: nonce, Value: gethcommon.Big0, - Gas: uint64(1_000_000), + Gas: uint64(1_000_000_000), GasPrice: gethcommon.Big1, Data: data, To: ti.wallets.Tokens[ercType].L2ContractAddress, From 51830c733f7ebb7e72e3351dcae020a7b02446b5 Mon Sep 17 00:00:00 2001 From: StefanIliev545 Date: Thu, 28 Dec 2023 23:35:12 +0200 Subject: [PATCH 08/26] Something is working --- go/enclave/enclave.go | 10 +++++++++- go/enclave/evm/evm_facade.go | 2 +- go/enclave/l2chain/l2_chain.go | 2 +- go/host/rpc/clientapi/client_api_eth.go | 3 ++- go/obsclient/authclient.go | 20 +++++++++++++++++-- go/responses/types.go | 17 ++++++++-------- go/rpc/client.go | 1 + integration/common/constants.go | 7 ++++--- integration/common/utils.go | 6 ++++-- integration/simulation/simulation.go | 17 +++++++++------- .../simulation/transaction_injector.go | 8 ++++---- 11 files changed, 63 insertions(+), 30 deletions(-) diff --git a/go/enclave/enclave.go b/go/enclave/enclave.go index 6ce7e9d125..f0233596d6 100644 --- a/go/enclave/enclave.go +++ b/go/enclave/enclave.go @@ -1043,6 +1043,8 @@ func (e *enclaveImpl) EstimateGas(encryptedParams common.EncryptedParamsEstimate return responses.AsPlaintextError(fmt.Errorf("internal server error")), err } + // The message is ran through the l1 publishing cost estimation for the current + // known head block. l1Cost, err := e.gasOracle.EstimateL1CostForMsg(callMsg, block) if err != nil { return responses.AsPlaintextError(fmt.Errorf("internal server error")), err @@ -1053,8 +1055,14 @@ func (e *enclaveImpl) EstimateGas(encryptedParams common.EncryptedParamsEstimate return responses.AsPlaintextError(fmt.Errorf("internal server error")), err } + // We divide the total estimated l1 cost by the l2 fee per gas in order to convert + // the expected cost into l2 gas based on current pricing. + // todo @siliev - add overhead when the base fee becomes dynamic. publishingGas := big.NewInt(0).Div(l1Cost, batch.Header.BaseFee) - publishingGas.Add(publishingGas, big.NewInt(0).Mod(l1Cost, batch.Header.BaseFee)) + + // The one additional gas captures the modulo leftover in some edge cases + // where BaseFee is bigger than the l1cost. + publishingGas = big.NewInt(0).Add(publishingGas, gethcommon.Big1) executionGasEstimate, err := e.DoEstimateGas(callMsg, blockNumber, e.config.GasLocalExecutionCapFlag) if err != nil { diff --git a/go/enclave/evm/evm_facade.go b/go/enclave/evm/evm_facade.go index d731ab5b07..fd2cece071 100644 --- a/go/enclave/evm/evm_facade.go +++ b/go/enclave/evm/evm_facade.go @@ -130,7 +130,7 @@ func executeTransaction( if hasL1Cost { l1Gas.Div(l1cost, header.BaseFee) - l1Gas.Add(l1Gas, big.NewInt(0).Mod(l1cost, header.BaseFee)) + l1Gas.Add(l1Gas, big.NewInt(1)) //account for leftover if msg.GasLimit < l1Gas.Uint64() { return nil, fmt.Errorf("gas limit for tx too low. Want at least: %d have: %d", l1Gas, msg.GasLimit) diff --git a/go/enclave/l2chain/l2_chain.go b/go/enclave/l2chain/l2_chain.go index 7f56e0fde6..b7b68cf356 100644 --- a/go/enclave/l2chain/l2_chain.go +++ b/go/enclave/l2chain/l2_chain.go @@ -133,7 +133,7 @@ func (oc *obscuroChain) ObsCallAtBlock(apiArgs *gethapi.TransactionArgs, blockNu return nil, fmt.Errorf("unable to fetch head state batch. Cause: %w", err) } - callMsg, err := apiArgs.ToMessage(batch.Header.GasLimit, batch.Header.BaseFee) + callMsg, err := apiArgs.ToMessage(batch.Header.GasLimit-1, batch.Header.BaseFee) if err != nil { return nil, fmt.Errorf("unable to convert TransactionArgs to Message - %w", err) } diff --git a/go/host/rpc/clientapi/client_api_eth.go b/go/host/rpc/clientapi/client_api_eth.go index 672d1f7e39..1f5dd13146 100644 --- a/go/host/rpc/clientapi/client_api_eth.go +++ b/go/host/rpc/clientapi/client_api_eth.go @@ -7,6 +7,7 @@ import ( "math/big" "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rpc" "github.com/ten-protocol/go-ten/go/common" "github.com/ten-protocol/go-ten/go/common/host" @@ -73,7 +74,7 @@ func (api *EthereumAPI) GasPrice(context.Context) (*hexutil.Big, error) { } if header.BaseFee == nil || header.BaseFee.Cmp(gethcommon.Big0) == 0 { - return (*hexutil.Big)(big.NewInt(1)), nil + return (*hexutil.Big)(big.NewInt(params.InitialBaseFee)), nil } return (*hexutil.Big)(big.NewInt(0).Set(header.BaseFee)), nil diff --git a/go/obsclient/authclient.go b/go/obsclient/authclient.go index e1326903b2..a7ee70495c 100644 --- a/go/obsclient/authclient.go +++ b/go/obsclient/authclient.go @@ -60,7 +60,9 @@ func DialWithAuth(rpcurl string, wal wallet.Wallet, logger gethlog.Logger) (*Aut if err != nil { return nil, err } - return NewAuthObsClient(encClient), nil + + authClient := NewAuthObsClient(encClient) + return authClient, nil } // TransactionByHash returns transaction (if found), isPending (always false currently as we don't search the mempool), error @@ -74,6 +76,16 @@ func (ac *AuthObsClient) TransactionByHash(ctx context.Context, hash gethcommon. return &tx, false, nil } +func (ac *AuthObsClient) GasPrice(ctx context.Context) (*big.Int, error) { + var result responses.GasPriceType + err := ac.rpcClient.CallContext(ctx, &result, rpc.GasPrice) + if err != nil { + return nil, err + } + + return result.ToInt(), nil +} + func (ac *AuthObsClient) TransactionReceipt(ctx context.Context, txHash gethcommon.Hash) (*types.Receipt, error) { var result responses.ReceiptType err := ac.rpcClient.CallContext(ctx, &result, rpc.GetTransactionReceipt, txHash) @@ -165,7 +177,6 @@ func (ac *AuthObsClient) EstimateGas(ctx context.Context, msg *ethereum.CallMsg) func (ac *AuthObsClient) EstimateGasAndGasPrice(txData types.TxData) types.TxData { unEstimatedTx := types.NewTx(txData) - gasPrice := gethcommon.Big1 // constant gas price atm gasLimit, err := ac.EstimateGas(context.Background(), ðereum.CallMsg{ From: ac.Address(), @@ -177,6 +188,11 @@ func (ac *AuthObsClient) EstimateGasAndGasPrice(txData types.TxData) types.TxDat gasLimit = unEstimatedTx.Gas() } + gasPrice, err := ac.GasPrice(context.Background()) + if err != nil { + gasPrice = big.NewInt(1) + } + return &types.LegacyTx{ Nonce: unEstimatedTx.Nonce(), GasPrice: gasPrice, diff --git a/go/responses/types.go b/go/responses/types.go index 954f31165b..690e0ac5f4 100644 --- a/go/responses/types.go +++ b/go/responses/types.go @@ -43,12 +43,13 @@ type ( // Data Types type ( - BalanceType = hexutil.Big - CallType = string - ReceiptType = types.Receipt - RawTxType = common.Hash - TxType = types.Transaction - NonceType = string - GasType = hexutil.Uint64 - LogsType = []*types.Log + BalanceType = hexutil.Big + CallType = string + ReceiptType = types.Receipt + RawTxType = common.Hash + TxType = types.Transaction + NonceType = string + GasType = hexutil.Uint64 + LogsType = []*types.Log + GasPriceType = hexutil.Big ) diff --git a/go/rpc/client.go b/go/rpc/client.go index 768ffaa126..9a11e5b669 100644 --- a/go/rpc/client.go +++ b/go/rpc/client.go @@ -22,6 +22,7 @@ const ( EstimateGas = "eth_estimateGas" GetLogs = "eth_getLogs" GetStorageAt = "eth_getStorageAt" + GasPrice = "eth_gasPrice" Health = "obscuro_health" Config = "obscuro_config" diff --git a/integration/common/constants.go b/integration/common/constants.go index b46cbd51d4..03e7bf1f4c 100644 --- a/integration/common/constants.go +++ b/integration/common/constants.go @@ -4,6 +4,7 @@ import ( "math/big" "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/params" "github.com/ten-protocol/go-ten/go/common" "github.com/ten-protocol/go-ten/go/common/log" "github.com/ten-protocol/go-ten/go/config" @@ -82,8 +83,8 @@ func DefaultEnclaveConfig() *config.EnclaveConfig { MaxBatchSize: 1024 * 25, MaxRollupSize: 1024 * 64, GasPaymentAddress: gethcommon.HexToAddress("0xd6C9230053f45F873Cb66D8A02439380a37A4fbF"), - BaseFee: new(big.Int).SetUint64(1), - GasLocalExecutionCapFlag: 3_000_000, - GasBatchExecutionLimit: 3_000_000, + BaseFee: new(big.Int).SetUint64(params.InitialBaseFee), + GasLocalExecutionCapFlag: 300_000_000_000, + GasBatchExecutionLimit: 300_000_000_000, // Arbitrum gas limit for reference - 1,125,899,906,842,624 } } diff --git a/integration/common/utils.go b/integration/common/utils.go index dfd4f082b1..455930d2cc 100644 --- a/integration/common/utils.go +++ b/integration/common/utils.go @@ -112,7 +112,9 @@ func PrefundWallets(ctx context.Context, faucetWallet wallet.Wallet, faucetClien err = faucetClient.SendTransaction(ctx, signedTx) if err != nil { - panic(fmt.Sprintf("could not transfer from faucet. Cause: %s", err)) + var txJson []byte + txJson, _ = signedTx.MarshalJSON() + panic(fmt.Sprintf("could not transfer from faucet for tx %s. Cause: %s", string(txJson[:]), err)) } txHashes[idx] = signedTx.Hash() @@ -126,7 +128,7 @@ func PrefundWallets(ctx context.Context, faucetWallet wallet.Wallet, faucetClien defer wg.Done() err := AwaitReceipt(ctx, faucetClient, txHash, timeout) if err != nil { - panic(fmt.Sprintf("faucet transfer transaction unsuccessful. Cause: %s", err)) + panic(fmt.Sprintf("faucet transfer transaction %s unsuccessful. Cause: %s", txHash, err)) } }(txHash) } diff --git a/integration/simulation/simulation.go b/integration/simulation/simulation.go index 85688f91ea..654db7f82b 100644 --- a/integration/simulation/simulation.go +++ b/integration/simulation/simulation.go @@ -12,6 +12,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/eth/filters" + gethparams "github.com/ethereum/go-ethereum/params" "github.com/ten-protocol/go-ten/contracts/generated/MessageBus" "github.com/ten-protocol/go-ten/go/common" "github.com/ten-protocol/go-ten/go/common/errutil" @@ -22,6 +23,7 @@ import ( "github.com/ten-protocol/go-ten/integration/erc20contract" "github.com/ten-protocol/go-ten/integration/ethereummock" "github.com/ten-protocol/go-ten/integration/simulation/network" + "github.com/ten-protocol/go-ten/integration/simulation/params" "github.com/ten-protocol/go-ten/integration/simulation/stats" @@ -29,10 +31,6 @@ import ( testcommon "github.com/ten-protocol/go-ten/integration/common" ) -const ( - allocObsWallets = 750_000_000_000_000 // The amount the faucet allocates to each Obscuro wallet. -) - var initialBalance = common.ValueInWei(big.NewInt(5000)) // Simulation represents all the data required to inject transactions on a network @@ -57,7 +55,7 @@ func (s *Simulation) Start() { // Arbitrary sleep to wait for RPC clients to get up and running // and for all l2 nodes to receive the genesis l2 batch - time.Sleep(2 * time.Second) + time.Sleep(5 * time.Second) s.bridgeFundingToObscuro() s.trackLogs() // Create log subscriptions, to validate that they're working correctly later. @@ -207,9 +205,14 @@ func (s *Simulation) trackLogs() { // Prefunds the L2 wallets with `allocObsWallets` each. func (s *Simulation) prefundObscuroAccounts() { faucetWallet := s.Params.Wallets.L2FaucetWallet - faucetClient := s.RPCHandles.ObscuroWalletRndClient(faucetWallet) + faucetClient := s.RPCHandles.ObscuroWalletClient(faucetWallet.Address(), 0) // get sequencer, else errors on submission get swallowed nonce := NextNonce(s.ctx, s.RPCHandles, faucetWallet) - testcommon.PrefundWallets(s.ctx, faucetWallet, faucetClient, nonce, s.Params.Wallets.AllObsWallets(), big.NewInt(allocObsWallets), s.Params.ReceiptTimeout) + + // Give 100 ether per account - ether is 1e18 so best convert it by code + // as a lot of the hardcodes were giving way too little and choking the gas payments + allocObsWallets := big.NewInt(0).Mul(big.NewInt(100), big.NewInt(gethparams.Ether)) + + testcommon.PrefundWallets(s.ctx, faucetWallet, faucetClient, nonce, s.Params.Wallets.AllObsWallets(), allocObsWallets, s.Params.ReceiptTimeout) } // This deploys an ERC20 contract on Obscuro, which is used for token arithmetic. diff --git a/integration/simulation/transaction_injector.go b/integration/simulation/transaction_injector.go index c85e115c6c..cce12e68e0 100644 --- a/integration/simulation/transaction_injector.go +++ b/integration/simulation/transaction_injector.go @@ -141,10 +141,10 @@ func (ti *TransactionInjector) Start() { }) } - /*wg.Go(func() error { + wg.Go(func() error { ti.issueRandomTransfers() return nil - })*/ + }) wg.Go(func() error { ti.issueRandomValueTransfers() @@ -181,8 +181,8 @@ func (ti *TransactionInjector) issueRandomValueTransfers() { toWalletAddr := toWallet.Address() txData := &types.LegacyTx{ Nonce: fromWallet.GetNonceAndIncrement(), - Value: big.NewInt(int64(testcommon.RndBtw(1, 500))), - Gas: uint64(1_000_000_000), + Value: big.NewInt(int64(testcommon.RndBtw(1, 100))), + Gas: uint64(50_000), GasPrice: gethcommon.Big1, To: &toWalletAddr, } From 6aaa044ca593a70e6c6938f5f0ee674cf8e237d5 Mon Sep 17 00:00:00 2001 From: StefanIliev545 Date: Thu, 28 Dec 2023 23:56:45 +0200 Subject: [PATCH 09/26] Comments. --- integration/common/constants.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/integration/common/constants.go b/integration/common/constants.go index 03e7bf1f4c..b21cb138b9 100644 --- a/integration/common/constants.go +++ b/integration/common/constants.go @@ -84,7 +84,11 @@ func DefaultEnclaveConfig() *config.EnclaveConfig { MaxRollupSize: 1024 * 64, GasPaymentAddress: gethcommon.HexToAddress("0xd6C9230053f45F873Cb66D8A02439380a37A4fbF"), BaseFee: new(big.Int).SetUint64(params.InitialBaseFee), - GasLocalExecutionCapFlag: 300_000_000_000, - GasBatchExecutionLimit: 300_000_000_000, // Arbitrum gas limit for reference - 1,125,899,906,842,624 + + // Due to hiding L1 costs in the gas quantity, the gas limit needs to be huge + // Arbitrum with the same approach has gas limit of 1,125,899,906,842,624, + // whilst the usage is small. Should be ok since execution is paid for anyway. + GasLocalExecutionCapFlag: 300_000_000_000, + GasBatchExecutionLimit: 300_000_000_000, } } From d6859a064825e409c4a4cb9c6f5524fed5e8ef33 Mon Sep 17 00:00:00 2001 From: StefanIliev545 Date: Thu, 28 Dec 2023 23:57:53 +0200 Subject: [PATCH 10/26] Add somehow deleted favicon? --- tools/walletextension/api/static/favicon.ico | Bin 0 -> 996 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 tools/walletextension/api/static/favicon.ico diff --git a/tools/walletextension/api/static/favicon.ico b/tools/walletextension/api/static/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..1bb8f324a18a956628274ccbacffa64f1eeabc5f GIT binary patch literal 996 zcmVPx#1ZP1_K>z@;j|==^1poj532;bRa{vGf6951U69E94oEQKA19?eAK~!i%?U_#~ zJy8_L&-2LhzsUcxV_`wrVId1ik%*KXODVFjKv~Jw#!6W}DK?~}Y$R4F3Qmu&@xu#>QZ6Z4C|%4q#_z2cpp^bar+^I2`7v z-(!^1QdU${gfuWZ866!J#(r5>R~J4$K612|?d@$WC@2v2l{BH#Wl2d%I5aeb4-XGK z?0?3`$Ax_iYiw-9_xE>>^k;8x4V$FMS=?QS9vo;I0SyMr%ggMIPjz)QD}eR&byjXpPEO$R@{+II zePof^Mrp1By&%4dPkMSf(2m7d0LRD2th_kejF%h^Ykz!IR7m=!>6ZLMjs3=a>p0ysN6gWcU-Q&aH>R0u+SeLW;3#D7Hl zSQeR4I?#=_>Gz(v;vRtJZ02Ys1XUOe`rW z!KtY!Zn5a=>$AtC?+o@LPESwUejgJ$ZR_dj;akZuJ3DLlr4Juh-Q>r{#)e(UWoKuz z*W&K(&c2_>;{Ja!GBQ}nk(HIj3Set%3)6-(tuC7dN zaCCIUN=)1zIE>S=zrP=Hb933_kFonui40Wxv&SMQCkJ|adx5G=^Yilc_0_C_78e&` zWo5;4fK^sj!rDtj^(ZA5BMkk;eoq%d|0; Date: Fri, 29 Dec 2023 00:05:01 +0200 Subject: [PATCH 11/26] Fix for merge error. --- go/enclave/enclave.go | 1 + 1 file changed, 1 insertion(+) diff --git a/go/enclave/enclave.go b/go/enclave/enclave.go index db6d703ce0..f0233596d6 100644 --- a/go/enclave/enclave.go +++ b/go/enclave/enclave.go @@ -709,6 +709,7 @@ func (e *enclaveImpl) GetTransactionCount(encryptedParams common.EncryptedParams if err != nil { return nil, responses.ToInternalError(err) } + nonce = s.GetNonce(address) } encoded := hexutil.EncodeUint64(nonce) From 4fa9570e26b6458d8e033e07d1eb143adfff0d4a Mon Sep 17 00:00:00 2001 From: StefanIliev545 Date: Fri, 29 Dec 2023 00:08:33 +0200 Subject: [PATCH 12/26] Fix for build. --- go/host/rpc/clientapi/client_api_eth.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go/host/rpc/clientapi/client_api_eth.go b/go/host/rpc/clientapi/client_api_eth.go index 1f5dd13146..b333c9efcd 100644 --- a/go/host/rpc/clientapi/client_api_eth.go +++ b/go/host/rpc/clientapi/client_api_eth.go @@ -189,7 +189,7 @@ func (api *EthereumAPI) FeeHistory(context.Context, string, rpc.BlockNumber, []f // todo (#1621) - return a non-dummy fee history header, err := api.host.DB().GetHeadBatchHeader() if err != nil { - api.logger.Error(fmt.Sprintf("Unable to retrieve header for fee history. Cause: %w", err)) + api.logger.Error("Unable to retrieve header for fee history.", log.ErrKey, err) return nil, fmt.Errorf("unable to retrieve fee history") } From 1603add2305e02ed15dd1d0d9eb6c8749077f6bc Mon Sep 17 00:00:00 2001 From: StefanIliev545 Date: Fri, 29 Dec 2023 00:31:15 +0200 Subject: [PATCH 13/26] Disable test again. --- .../networktest/tests/helpful/spin_up_local_network_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/integration/networktest/tests/helpful/spin_up_local_network_test.go b/integration/networktest/tests/helpful/spin_up_local_network_test.go index 753076a87e..83a5f4888c 100644 --- a/integration/networktest/tests/helpful/spin_up_local_network_test.go +++ b/integration/networktest/tests/helpful/spin_up_local_network_test.go @@ -30,6 +30,7 @@ const ( ) func TestRunLocalNetwork(t *testing.T) { + networktest.TestOnlyRunsInIDE(t) networktest.EnsureTestLogsSetUp("local-geth-network") networkConnector, cleanUp, err := env.LocalDevNetwork().Prepare() if err != nil { From 8e3258f34e20814f7277851637add08319cae3bb Mon Sep 17 00:00:00 2001 From: StefanIliev545 Date: Sat, 30 Dec 2023 19:33:12 +0100 Subject: [PATCH 14/26] Changes to gateway. --- integration/obscurogateway/tengateway_test.go | 51 ++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/integration/obscurogateway/tengateway_test.go b/integration/obscurogateway/tengateway_test.go index 901241036e..e365ed86a4 100644 --- a/integration/obscurogateway/tengateway_test.go +++ b/integration/obscurogateway/tengateway_test.go @@ -15,6 +15,7 @@ import ( wecommon "github.com/ten-protocol/go-ten/tools/walletextension/common" gethcommon "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/log" @@ -158,6 +159,9 @@ func testMultipleAccountsSubscription(t *testing.T, httpURL, wsURL string, w wal Data: gethcommon.FromHex(eventsContractBytecode), } + err = getFeeAndGas(user0.HTTPClient, w, deployTx) + require.NoError(t, err) + signedTx, err := w.SignTransaction(deployTx) require.NoError(t, err) @@ -341,6 +345,9 @@ func testErrorsRevertedArePassed(t *testing.T, httpURL, wsURL string, w wallet.W Data: gethcommon.FromHex(errorsContractBytecode), } + err = getFeeAndGas(ethStdClient, w, deployTx) + require.NoError(t, err) + signedTx, err := w.SignTransaction(deployTx) require.NoError(t, err) @@ -401,11 +408,13 @@ func testUnsubscribe(t *testing.T, httpURL, wsURL string, w wallet.Wallet) { // deploy events contract deployTx := &types.LegacyTx{ Nonce: w.GetNonceAndIncrement(), - Gas: uint64(1_000_000), + Gas: uint64(10_000_000), GasPrice: gethcommon.Big1, Data: gethcommon.FromHex(eventsContractBytecode), } + require.NoError(t, getFeeAndGas(user.HTTPClient, w, deployTx)) + signedTx, err := w.SignTransaction(deployTx) require.NoError(t, err) @@ -456,6 +465,8 @@ func testClosingConnectionWhileSubscribed(t *testing.T, httpURL, wsURL string, w Data: gethcommon.FromHex(eventsContractBytecode), } + require.NoError(t, getFeeAndGas(user.HTTPClient, w, deployTx)) + signedTx, err := w.SignTransaction(deployTx) require.NoError(t, err) @@ -568,6 +579,38 @@ func waitServerIsReady(serverAddr string) error { return fmt.Errorf("timed out before server was ready") } +func getFeeAndGas(client *ethclient.Client, wallet wallet.Wallet, legacyTx *types.LegacyTx) error { + tx := types.NewTx(legacyTx) + + history, err := client.FeeHistory(context.Background(), 1, nil, []float64{}) + if err != nil || len(history.BaseFee) == 0 { + return err + } + + gasPrice := history.BaseFee[0] + + msg, err := core.TransactionToMessage(tx, types.NewCancunSigner(wallet.ChainID()), gasPrice) + if err != nil { + return err + } + + estimate, err := client.EstimateGas(context.Background(), ethereum.CallMsg{ + From: msg.From, + To: msg.To, + GasPrice: msg.GasPrice, + Value: msg.Value, + Data: msg.Data, + }) + if err != nil { + return err + } + + legacyTx.Gas = estimate + legacyTx.GasPrice = gasPrice + + return nil +} + func transferETHToAddress(client *ethclient.Client, wallet wallet.Wallet, toAddress gethcommon.Address, amount int64) (*types.Receipt, error) { //nolint:unparam transferTx1 := types.LegacyTx{ Nonce: wallet.GetNonceAndIncrement(), @@ -577,6 +620,12 @@ func transferETHToAddress(client *ethclient.Client, wallet wallet.Wallet, toAddr GasPrice: gethcommon.Big1, Data: nil, } + + err := getFeeAndGas(client, wallet, &transferTx1) + if err != nil { + return nil, err + } + signedTx, err := wallet.SignTransaction(&transferTx1) if err != nil { return nil, err From 6328ef175ffb6b324d6b89f8c9fbf7af53af6a69 Mon Sep 17 00:00:00 2001 From: StefanIliev545 Date: Tue, 9 Jan 2024 13:48:07 +0200 Subject: [PATCH 15/26] Fixes. --- integration/common/utils.go | 3 ++- integration/obscurogateway/tengateway_test.go | 20 ++++++------------- 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/integration/common/utils.go b/integration/common/utils.go index d7e5091d19..7af2238911 100644 --- a/integration/common/utils.go +++ b/integration/common/utils.go @@ -10,6 +10,7 @@ import ( "time" "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/ethclient" "github.com/ten-protocol/go-ten/go/common/errutil" @@ -145,7 +146,7 @@ func InteractWithSmartContract(client *ethclient.Client, wallet wallet.Wallet, c Nonce: wallet.GetNonceAndIncrement(), To: &contractAddress, Gas: uint64(1_000_000), - GasPrice: gethcommon.Big1, + GasPrice: big.NewInt(params.InitialBaseFee), Data: contractInteractionData, } signedTx, err := wallet.SignTransaction(&interactionTx) diff --git a/integration/obscurogateway/tengateway_test.go b/integration/obscurogateway/tengateway_test.go index e365ed86a4..d0d5d69f72 100644 --- a/integration/obscurogateway/tengateway_test.go +++ b/integration/obscurogateway/tengateway_test.go @@ -15,7 +15,7 @@ import ( wecommon "github.com/ten-protocol/go-ten/tools/walletextension/common" gethcommon "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/log" @@ -587,26 +587,18 @@ func getFeeAndGas(client *ethclient.Client, wallet wallet.Wallet, legacyTx *type return err } - gasPrice := history.BaseFee[0] - - msg, err := core.TransactionToMessage(tx, types.NewCancunSigner(wallet.ChainID()), gasPrice) - if err != nil { - return err - } - estimate, err := client.EstimateGas(context.Background(), ethereum.CallMsg{ - From: msg.From, - To: msg.To, - GasPrice: msg.GasPrice, - Value: msg.Value, - Data: msg.Data, + From: wallet.Address(), + To: tx.To(), + Value: tx.Value(), + Data: tx.Data(), }) if err != nil { return err } legacyTx.Gas = estimate - legacyTx.GasPrice = gasPrice + legacyTx.GasPrice = history.BaseFee[0] // big.NewInt(gethparams.InitialBaseFee) return nil } From 18f5af0574247d20b6622ac8e4957b6b5f98d954 Mon Sep 17 00:00:00 2001 From: StefanIliev545 Date: Tue, 9 Jan 2024 13:54:50 +0200 Subject: [PATCH 16/26] Fixes for linter. --- go/enclave/components/batch_executor.go | 29 +++---------------------- go/enclave/evm/evm_facade.go | 2 +- go/host/rpc/clientapi/client_api_eth.go | 2 +- 3 files changed, 5 insertions(+), 28 deletions(-) diff --git a/go/enclave/components/batch_executor.go b/go/enclave/components/batch_executor.go index ab80ed4aad..1dc4313280 100644 --- a/go/enclave/components/batch_executor.go +++ b/go/enclave/components/batch_executor.go @@ -67,10 +67,10 @@ func NewBatchExecutor( } } -// payL1Fees - this function modifies the state db according to the transactions contained within the batch context +// estimateL1Fees - this function modifies the state db according to the transactions contained within the batch context // in order to subtract gas fees from the balance. It returns a list of the transactions that have prepaid for their L1 // publishing costs. -func (executor *batchExecutor) payL1Fees(stateDB *state.StateDB, context *BatchExecutionContext) (common.L2PricedTransactions, common.L2PricedTransactions) { +func (executor *batchExecutor) estimateL1Fees(stateDB *state.StateDB, context *BatchExecutionContext) (common.L2PricedTransactions, common.L2PricedTransactions) { transactions := make(common.L2PricedTransactions, 0) freeTransactions := make(common.L2PricedTransactions, 0) block, _ := executor.storage.FetchBlock(context.BlockPtr) @@ -120,27 +120,6 @@ func (executor *batchExecutor) payL1Fees(stateDB *state.StateDB, context *BatchE return transactions, freeTransactions } -func (executor *batchExecutor) refundL1Fees(stateDB *state.StateDB, context *BatchExecutionContext, transactions []*common.L2Tx) { - block, _ := executor.storage.FetchBlock(context.BlockPtr) - for _, tx := range transactions { - cost, err := executor.gasOracle.EstimateL1StorageGasCost(tx, block) - if err != nil { - executor.logger.Warn("Unable to get gas cost for tx", log.TxKey, tx.Hash(), log.ErrKey, err) - continue - } - - sender, err := core.GetAuthenticatedSender(context.ChainConfig.ChainID.Int64(), tx) - if err != nil { - // todo @siliev - is this critical? Potential desync spot - executor.logger.Warn("Unable to extract sender for tx", log.TxKey, tx.Hash()) - continue - } - - stateDB.AddBalance(*sender, cost) - stateDB.SubBalance(context.Creator, cost) - } -} - func (executor *batchExecutor) ComputeBatch(context *BatchExecutionContext, failForEmptyBatch bool) (*ComputedBatch, error) { //nolint:gocognit defer core.LogMethodDuration(executor.logger, measure.NewStopwatch(), "Batch context processed") @@ -190,7 +169,7 @@ func (executor *batchExecutor) ComputeBatch(context *BatchExecutionContext, fail crossChainTransactions := executor.crossChainProcessors.Local.CreateSyntheticTransactions(messages, stateDB) executor.crossChainProcessors.Local.ExecuteValueTransfers(transfers, stateDB) - transactionsToProcess, freeTransactions := executor.payL1Fees(stateDB, context) + transactionsToProcess, freeTransactions := executor.estimateL1Fees(stateDB, context) xchainTxs := make(common.L2PricedTransactions, 0) for _, xTx := range crossChainTransactions { @@ -207,8 +186,6 @@ func (executor *batchExecutor) ComputeBatch(context *BatchExecutionContext, fail return nil, fmt.Errorf("could not process transactions. Cause: %w", err) } - //executor.refundL1Fees(stateDB, context, excludedTxs) - ccSuccessfulTxs, _, ccReceipts, err := executor.processTransactions(batch, len(successfulTxs), xchainTxs, stateDB, context.ChainConfig, true) if err != nil { return nil, err diff --git a/go/enclave/evm/evm_facade.go b/go/enclave/evm/evm_facade.go index fd2cece071..6bcd20358f 100644 --- a/go/enclave/evm/evm_facade.go +++ b/go/enclave/evm/evm_facade.go @@ -130,7 +130,7 @@ func executeTransaction( if hasL1Cost { l1Gas.Div(l1cost, header.BaseFee) - l1Gas.Add(l1Gas, big.NewInt(1)) //account for leftover + l1Gas.Add(l1Gas, big.NewInt(1)) // account for leftover if msg.GasLimit < l1Gas.Uint64() { return nil, fmt.Errorf("gas limit for tx too low. Want at least: %d have: %d", l1Gas, msg.GasLimit) diff --git a/go/host/rpc/clientapi/client_api_eth.go b/go/host/rpc/clientapi/client_api_eth.go index b333c9efcd..a3e3a4a0ea 100644 --- a/go/host/rpc/clientapi/client_api_eth.go +++ b/go/host/rpc/clientapi/client_api_eth.go @@ -204,7 +204,7 @@ func (api *EthereumAPI) FeeHistory(context.Context, string, rpc.BlockNumber, []f } for _, header := range batches { - feeHist.GasUsedRatio = append(feeHist.GasUsedRatio, 0.9) //todo @siliev - fix when baseFee is dynamic + feeHist.GasUsedRatio = append(feeHist.GasUsedRatio, 0.9) // todo @siliev - fix when baseFee is dynamic feeHist.BaseFee = append(feeHist.BaseFee, (*hexutil.Big)(header.BaseFee)) } return feeHist, nil From 4424153e712bdb28414534f2914a97756b22f1e8 Mon Sep 17 00:00:00 2001 From: StefanIliev545 Date: Tue, 9 Jan 2024 14:56:31 +0200 Subject: [PATCH 17/26] Test fixes. --- go/obsclient/authclient.go | 3 ++- tools/hardhatdeployer/contract_deployer.go | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/go/obsclient/authclient.go b/go/obsclient/authclient.go index a7ee70495c..46ab845e3f 100644 --- a/go/obsclient/authclient.go +++ b/go/obsclient/authclient.go @@ -8,6 +8,7 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/eth/filters" + "github.com/ethereum/go-ethereum/params" "github.com/ten-protocol/go-ten/go/common" "github.com/ten-protocol/go-ten/go/common/viewingkey" "github.com/ten-protocol/go-ten/go/responses" @@ -190,7 +191,7 @@ func (ac *AuthObsClient) EstimateGasAndGasPrice(txData types.TxData) types.TxDat gasPrice, err := ac.GasPrice(context.Background()) if err != nil { - gasPrice = big.NewInt(1) + gasPrice = big.NewInt(params.InitialBaseFee) } return &types.LegacyTx{ diff --git a/tools/hardhatdeployer/contract_deployer.go b/tools/hardhatdeployer/contract_deployer.go index bc5c9b921b..cbb56c78d3 100644 --- a/tools/hardhatdeployer/contract_deployer.go +++ b/tools/hardhatdeployer/contract_deployer.go @@ -10,6 +10,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/params" "github.com/ten-protocol/go-ten/go/common/constants" "github.com/ten-protocol/go-ten/go/common/retry" "github.com/ten-protocol/go-ten/go/wallet" @@ -91,8 +92,8 @@ func (cd *contractDeployer) run() (string, error) { deployContractTx := types.LegacyTx{ Nonce: cd.wallet.GetNonceAndIncrement(), - GasPrice: big.NewInt(1), - Gas: uint64(5_000_000), + GasPrice: big.NewInt(params.InitialBaseFee), + Gas: uint64(500_000_000), Data: cd.contractCode, } From a0f632c254272b31ef03f81d61ed880acc33c777 Mon Sep 17 00:00:00 2001 From: StefanIliev545 Date: Mon, 15 Jan 2024 13:21:49 +0200 Subject: [PATCH 18/26] Fix for xchain failures. --- go/enclave/components/batch_executor.go | 6 +++--- go/enclave/crosschain/message_bus_manager.go | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/go/enclave/components/batch_executor.go b/go/enclave/components/batch_executor.go index 1dc4313280..14f18ce464 100644 --- a/go/enclave/components/batch_executor.go +++ b/go/enclave/components/batch_executor.go @@ -191,7 +191,7 @@ func (executor *batchExecutor) ComputeBatch(context *BatchExecutionContext, fail return nil, err } - if err = executor.verifyInboundCrossChainTransactions(crossChainTransactions, ccSuccessfulTxs, ccReceipts); err != nil { + if err = executor.verifyInboundCrossChainTransactions(xchainTxs, ccSuccessfulTxs, ccReceipts); err != nil { return nil, fmt.Errorf("batch computation failed due to cross chain messages. Cause: %w", err) } @@ -378,8 +378,8 @@ func (executor *batchExecutor) populateHeader(batch *core.Batch, receipts types. } } -func (executor *batchExecutor) verifyInboundCrossChainTransactions(transactions types.Transactions, executedTxs types.Transactions, receipts types.Receipts) error { - if transactions.Len() != executedTxs.Len() { +func (executor *batchExecutor) verifyInboundCrossChainTransactions(transactions common.L2PricedTransactions, executedTxs types.Transactions, receipts types.Receipts) error { + if len(transactions) != executedTxs.Len() { return fmt.Errorf("some synthetic transactions have not been executed") } diff --git a/go/enclave/crosschain/message_bus_manager.go b/go/enclave/crosschain/message_bus_manager.go index 1731a10515..1a70bd7465 100644 --- a/go/enclave/crosschain/message_bus_manager.go +++ b/go/enclave/crosschain/message_bus_manager.go @@ -86,7 +86,7 @@ func (m *MessageBusManager) GenerateMessageBusDeployTx() (*common.L2Tx, error) { tx := &types.LegacyTx{ Nonce: 0, // The first transaction of the owner identity should always be deploying the contract Value: gethcommon.Big0, - Gas: 5_000_000, // It's quite the expensive contract. + Gas: 500_000_000, // It's quite the expensive contract. GasPrice: gethcommon.Big0, // Synthetic transactions are on the house. Or the house. Data: gethcommon.FromHex(MessageBus.MessageBusMetaData.Bin), To: nil, // Geth requires nil instead of gethcommon.Address{} which equates to zero address in order to return receipt. From b952cdf49eb2a5fe0561371eaa9318a709707a7e Mon Sep 17 00:00:00 2001 From: StefanIliev545 Date: Mon, 15 Jan 2024 16:02:46 +0200 Subject: [PATCH 19/26] Deployment fix. --- go/config/enclave_cli_flags.go | 3 ++- go/enclave/components/batch_executor.go | 4 ---- go/enclave/evm/evm_facade.go | 7 +++++-- go/obsclient/authclient.go | 3 +++ integration/common/constants.go | 2 +- 5 files changed, 11 insertions(+), 8 deletions(-) diff --git a/go/config/enclave_cli_flags.go b/go/config/enclave_cli_flags.go index 586a9e7c2a..1c1ffcdfb2 100644 --- a/go/config/enclave_cli_flags.go +++ b/go/config/enclave_cli_flags.go @@ -1,6 +1,7 @@ package config import ( + "github.com/ethereum/go-ethereum/params" "github.com/ten-protocol/go-ten/go/common" "github.com/ten-protocol/go-ten/go/common/flag" ) @@ -53,7 +54,7 @@ var EnclaveFlags = map[string]*flag.TenFlag{ SequencerIDFlag: flag.NewStringFlag(SequencerIDFlag, "", "The 20 bytes of the address of the sequencer for this network"), MaxBatchSizeFlag: flag.NewUint64Flag(MaxBatchSizeFlag, 1024*25, "The maximum size a batch is allowed to reach uncompressed"), MaxRollupSizeFlag: flag.NewUint64Flag(MaxRollupSizeFlag, 1024*64, "The maximum size a rollup is allowed to reach"), - L2BaseFeeFlag: flag.NewUint64Flag(L2BaseFeeFlag, 1, ""), + L2BaseFeeFlag: flag.NewUint64Flag(L2BaseFeeFlag, params.InitialBaseFee, ""), L2CoinbaseFlag: flag.NewStringFlag(L2CoinbaseFlag, "0xd6C9230053f45F873Cb66D8A02439380a37A4fbF", ""), GasBatchExecutionLimit: flag.NewUint64Flag(GasBatchExecutionLimit, 30_000_000, "Max gas that can be executed in a single batch"), ObscuroGenesisFlag: flag.NewStringFlag(ObscuroGenesisFlag, "", "The json string with the obscuro genesis"), diff --git a/go/enclave/components/batch_executor.go b/go/enclave/components/batch_executor.go index 14f18ce464..327bcd4cb7 100644 --- a/go/enclave/components/batch_executor.go +++ b/go/enclave/components/batch_executor.go @@ -108,10 +108,6 @@ func (executor *batchExecutor) estimateL1Fees(stateDB *state.StateDB, context *B continue } - /*stateDB.SubBalance(*sender, cost) - stateDB.AddBalance(context.Creator, cost)*/ - // todo - add refund logic. - transactions = append(transactions, common.L2PricedTransaction{ Tx: tx, PublishingCost: big.NewInt(0).Set(cost), diff --git a/go/enclave/evm/evm_facade.go b/go/enclave/evm/evm_facade.go index 6bcd20358f..fc04248bd8 100644 --- a/go/enclave/evm/evm_facade.go +++ b/go/enclave/evm/evm_facade.go @@ -4,6 +4,9 @@ import ( "errors" "fmt" "math/big" + + // unsafe package imported in order to link to a private function in go-ethereum. + // This allows us to customize the message generated from a signed transaction and inject custom gas logic. _ "unsafe" "github.com/ethereum/go-ethereum/accounts/abi" @@ -130,10 +133,10 @@ func executeTransaction( if hasL1Cost { l1Gas.Div(l1cost, header.BaseFee) - l1Gas.Add(l1Gas, big.NewInt(1)) // account for leftover + l1Gas.Add(l1Gas, big.NewInt(1)) if msg.GasLimit < l1Gas.Uint64() { - return nil, fmt.Errorf("gas limit for tx too low. Want at least: %d have: %d", l1Gas, msg.GasLimit) + return nil, fmt.Errorf("gas limit set by user is too low to pay for execution and l1 fees. Want at least: %d have: %d", l1Gas, msg.GasLimit) } msg.GasLimit -= l1Gas.Uint64() diff --git a/go/obsclient/authclient.go b/go/obsclient/authclient.go index 46ab845e3f..2db0151f61 100644 --- a/go/obsclient/authclient.go +++ b/go/obsclient/authclient.go @@ -191,6 +191,9 @@ func (ac *AuthObsClient) EstimateGasAndGasPrice(txData types.TxData) types.TxDat gasPrice, err := ac.GasPrice(context.Background()) if err != nil { + // params.InitialBaseFee should be the new standard gas price. + // If the gas price is too low, then the gas required to be put in a transaction + // becomes astronomical. gasPrice = big.NewInt(params.InitialBaseFee) } diff --git a/integration/common/constants.go b/integration/common/constants.go index b21cb138b9..ef510672c5 100644 --- a/integration/common/constants.go +++ b/integration/common/constants.go @@ -76,7 +76,7 @@ func DefaultEnclaveConfig() *config.EnclaveConfig { EdgelessDBHost: "", SqliteDBPath: "", ProfilerEnabled: false, - MinGasPrice: big.NewInt(1), + MinGasPrice: big.NewInt(params.InitialBaseFee), SequencerID: gethcommon.BytesToAddress([]byte("")), ObscuroGenesis: "", DebugNamespaceEnabled: false, From 32314bb757474a85b668842a4787360f47e3a25a Mon Sep 17 00:00:00 2001 From: StefanIliev545 Date: Mon, 15 Jan 2024 16:29:18 +0200 Subject: [PATCH 20/26] More deployment fixes. --- .../deployment_scripts/testnet/layer2/001_whitelist_tokens.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/deployment_scripts/testnet/layer2/001_whitelist_tokens.ts b/contracts/deployment_scripts/testnet/layer2/001_whitelist_tokens.ts index 371bea2a10..c2cf32d3c4 100644 --- a/contracts/deployment_scripts/testnet/layer2/001_whitelist_tokens.ts +++ b/contracts/deployment_scripts/testnet/layer2/001_whitelist_tokens.ts @@ -97,11 +97,11 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { setTimeout(fail, 30_000) const messageBusContract = (await hre.ethers.getContractAt('MessageBus', '0x526c84529b2b8c11f57d93d3f5537aca3aecef9b')); const gasLimit = await messageBusContract.estimateGas.verifyMessageFinalized(messages[1], { - maxFeePerGas: 2, + maxFeePerGas: 1000000001, }) try { while (await messageBusContract.callStatic.verifyMessageFinalized(messages[1], { - maxFeePerGas: 2, + maxFeePerGas: 1000000001, gasLimit: gasLimit.mul(2), from: l2Accounts.deployer }) != true) { From b9cb6e6714fb7bc11dd634450e8015cd10a02d40 Mon Sep 17 00:00:00 2001 From: StefanIliev545 Date: Mon, 15 Jan 2024 17:31:30 +0200 Subject: [PATCH 21/26] Maybe fix. --- .../deployment_scripts/testnet/layer2/001_whitelist_tokens.ts | 2 +- go/config/enclave_cli_flags.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/contracts/deployment_scripts/testnet/layer2/001_whitelist_tokens.ts b/contracts/deployment_scripts/testnet/layer2/001_whitelist_tokens.ts index c2cf32d3c4..c05bec6a2e 100644 --- a/contracts/deployment_scripts/testnet/layer2/001_whitelist_tokens.ts +++ b/contracts/deployment_scripts/testnet/layer2/001_whitelist_tokens.ts @@ -102,7 +102,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { try { while (await messageBusContract.callStatic.verifyMessageFinalized(messages[1], { maxFeePerGas: 1000000001, - gasLimit: gasLimit.mul(2), + gasLimit: gasLimit.add(gasLimit.div(2)), from: l2Accounts.deployer }) != true) { console.log(`Messages not stored on L2 yet, retrying...`); diff --git a/go/config/enclave_cli_flags.go b/go/config/enclave_cli_flags.go index 1c1ffcdfb2..f896085737 100644 --- a/go/config/enclave_cli_flags.go +++ b/go/config/enclave_cli_flags.go @@ -56,14 +56,14 @@ var EnclaveFlags = map[string]*flag.TenFlag{ MaxRollupSizeFlag: flag.NewUint64Flag(MaxRollupSizeFlag, 1024*64, "The maximum size a rollup is allowed to reach"), L2BaseFeeFlag: flag.NewUint64Flag(L2BaseFeeFlag, params.InitialBaseFee, ""), L2CoinbaseFlag: flag.NewStringFlag(L2CoinbaseFlag, "0xd6C9230053f45F873Cb66D8A02439380a37A4fbF", ""), - GasBatchExecutionLimit: flag.NewUint64Flag(GasBatchExecutionLimit, 30_000_000, "Max gas that can be executed in a single batch"), + GasBatchExecutionLimit: flag.NewUint64Flag(GasBatchExecutionLimit, 3_000_000_000, "Max gas that can be executed in a single batch"), ObscuroGenesisFlag: flag.NewStringFlag(ObscuroGenesisFlag, "", "The json string with the obscuro genesis"), L1ChainIDFlag: flag.NewInt64Flag(L1ChainIDFlag, 1337, "An integer representing the unique chain id of the Ethereum chain used as an L1 (default 1337)"), ObscuroChainIDFlag: flag.NewInt64Flag(ObscuroChainIDFlag, 443, "An integer representing the unique chain id of the Obscuro chain (default 443)"), UseInMemoryDBFlag: flag.NewBoolFlag(UseInMemoryDBFlag, true, "Whether the enclave will use an in-memory DB rather than persist data"), ProfilerEnabledFlag: flag.NewBoolFlag(ProfilerEnabledFlag, false, "Runs a profiler instance (Defaults to false)"), DebugNamespaceEnabledFlag: flag.NewBoolFlag(DebugNamespaceEnabledFlag, false, "Whether the debug namespace is enabled"), - GasLocalExecutionCapFlag: flag.NewUint64Flag(GasLocalExecutionCapFlag, 40_000_000, "Max gas usage when executing local transactions"), + GasLocalExecutionCapFlag: flag.NewUint64Flag(GasLocalExecutionCapFlag, 4_000_000_000, "Max gas usage when executing local transactions"), } // enclaveRestrictedFlags are the flags that the enclave can receive ONLY over the Ego signed enclave.json From d4dcd1c3386c31e6e82a58f97697501d5b462910 Mon Sep 17 00:00:00 2001 From: StefanIliev545 Date: Mon, 15 Jan 2024 19:09:41 +0200 Subject: [PATCH 22/26] Fix for faucet. --- tools/faucet/faucet/faucet.go | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/tools/faucet/faucet/faucet.go b/tools/faucet/faucet/faucet.go index 2da6f4205a..981fd4dd66 100644 --- a/tools/faucet/faucet/faucet.go +++ b/tools/faucet/faucet/faucet.go @@ -117,18 +117,16 @@ func (f *Faucet) fundNativeToken(address *common.Address, amount *big.Int) (*typ // this isn't great as the tx count might be incremented in between calls // but only after removing the pk from other apps can we use a proper counter - // todo remove hardcoded gas values - gas := uint64(21000) - tx := &types.LegacyTx{ Nonce: nonce, GasPrice: big.NewInt(225), - Gas: gas, To: address, Value: amount, } - signedTx, err := f.wallet.SignTransaction(tx) + estimatedTx := f.client.EstimateGasAndGasPrice(tx) + + signedTx, err := f.wallet.SignTransaction(estimatedTx) if err != nil { return nil, err } From c08dccc737356c4e62c84eedc9a294d7b3dda9ba Mon Sep 17 00:00:00 2001 From: StefanIliev545 Date: Tue, 16 Jan 2024 15:40:38 +0200 Subject: [PATCH 23/26] Added comments. --- go/enclave/components/batch_executor.go | 17 ++++++++--------- go/enclave/evm/evm_facade.go | 13 +++++++++++-- go/host/rpc/clientapi/client_api_eth.go | 4 +++- 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/go/enclave/components/batch_executor.go b/go/enclave/components/batch_executor.go index 327bcd4cb7..9e727f1ea5 100644 --- a/go/enclave/components/batch_executor.go +++ b/go/enclave/components/batch_executor.go @@ -67,10 +67,10 @@ func NewBatchExecutor( } } -// estimateL1Fees - this function modifies the state db according to the transactions contained within the batch context -// in order to subtract gas fees from the balance. It returns a list of the transactions that have prepaid for their L1 -// publishing costs. -func (executor *batchExecutor) estimateL1Fees(stateDB *state.StateDB, context *BatchExecutionContext) (common.L2PricedTransactions, common.L2PricedTransactions) { +// filterTransactionsWithSufficientFunds - this function estimates hte l1 fees for the transaction in a given batch execution context. It does so by taking the price of the +// pinned L1 block and using it as the cost per gas for the estimated gas of the calldata encoding of a transaction. It filters out any transactions that cannot afford to pay for their L1 +// publishing cost. +func (executor *batchExecutor) filterTransactionsWithSufficientFunds(stateDB *state.StateDB, context *BatchExecutionContext) (common.L2PricedTransactions, common.L2PricedTransactions) { transactions := make(common.L2PricedTransactions, 0) freeTransactions := make(common.L2PricedTransactions, 0) block, _ := executor.storage.FetchBlock(context.BlockPtr) @@ -165,7 +165,7 @@ func (executor *batchExecutor) ComputeBatch(context *BatchExecutionContext, fail crossChainTransactions := executor.crossChainProcessors.Local.CreateSyntheticTransactions(messages, stateDB) executor.crossChainProcessors.Local.ExecuteValueTransfers(transfers, stateDB) - transactionsToProcess, freeTransactions := executor.estimateL1Fees(stateDB, context) + transactionsToProcess, freeTransactions := executor.filterTransactionsWithSufficientFunds(stateDB, context) xchainTxs := make(common.L2PricedTransactions, 0) for _, xTx := range crossChainTransactions { @@ -175,19 +175,19 @@ func (executor *batchExecutor) ComputeBatch(context *BatchExecutionContext, fail }) } - xchainTxs = append(xchainTxs, freeTransactions...) + syntheticTransactions := append(xchainTxs, freeTransactions...) successfulTxs, excludedTxs, txReceipts, err := executor.processTransactions(batch, 0, transactionsToProcess, stateDB, context.ChainConfig, false) if err != nil { return nil, fmt.Errorf("could not process transactions. Cause: %w", err) } - ccSuccessfulTxs, _, ccReceipts, err := executor.processTransactions(batch, len(successfulTxs), xchainTxs, stateDB, context.ChainConfig, true) + ccSuccessfulTxs, _, ccReceipts, err := executor.processTransactions(batch, len(successfulTxs), syntheticTransactions, stateDB, context.ChainConfig, true) if err != nil { return nil, err } - if err = executor.verifyInboundCrossChainTransactions(xchainTxs, ccSuccessfulTxs, ccReceipts); err != nil { + if err = executor.verifyInboundCrossChainTransactions(syntheticTransactions, ccSuccessfulTxs, ccReceipts); err != nil { return nil, fmt.Errorf("batch computation failed due to cross chain messages. Cause: %w", err) } @@ -218,7 +218,6 @@ func (executor *batchExecutor) ComputeBatch(context *BatchExecutionContext, fail // the logs and receipts produced by the EVM have the wrong hash which must be adjusted for _, receipt := range allReceipts { - executor.logger.Info("New receipt! ", log.TxKey, receipt.TxHash) receipt.BlockHash = copyBatch.Hash() for _, l := range receipt.Logs { l.BlockHash = copyBatch.Hash() diff --git a/go/enclave/evm/evm_facade.go b/go/enclave/evm/evm_facade.go index fc04248bd8..d57886195a 100644 --- a/go/enclave/evm/evm_facade.go +++ b/go/enclave/evm/evm_facade.go @@ -132,14 +132,21 @@ func executeTransaction( hasL1Cost := l1cost.Cmp(big.NewInt(0)) != 0 if hasL1Cost { - l1Gas.Div(l1cost, header.BaseFee) - l1Gas.Add(l1Gas, big.NewInt(1)) + l1Gas.Div(l1cost, header.BaseFee) // TotalCost/CostPerGas = Gas + l1Gas.Add(l1Gas, big.NewInt(1)) // Cover from leftover from the division + // The gas limit of the transaction (evm message) should always be higher than the gas overhead + // used to cover the l1 cost if msg.GasLimit < l1Gas.Uint64() { return nil, fmt.Errorf("gas limit set by user is too low to pay for execution and l1 fees. Want at least: %d have: %d", l1Gas, msg.GasLimit) } + + // Remove the gas overhead for l1 publishing from the gas limit in order to define + // the actual gas limit for execution msg.GasLimit -= l1Gas.Uint64() + // Remove the l1 cost from the sender + // and pay it to the coinbase of the batch statedb.SubBalance(msg.From, l1cost) statedb.AddBalance(header.Coinbase, l1cost) @@ -150,6 +157,8 @@ func executeTransaction( vmenv := vm.NewEVM(blockContext, vm.TxContext{BlobHashes: tx.Tx.BlobHashes()}, statedb, config, cfg) receipt, err := applyTransaction(msg, config, gp, statedb, header.Number, header.Hash(), tx.Tx, usedGas, vmenv) if err != nil { + // If the transaction has l1 cost, then revert the funds exchange + // as it will not be published on error (no receipt condition) if hasL1Cost { statedb.SubBalance(header.Coinbase, l1cost) statedb.AddBalance(msg.From, l1cost) diff --git a/go/host/rpc/clientapi/client_api_eth.go b/go/host/rpc/clientapi/client_api_eth.go index a3e3a4a0ea..9c15154e07 100644 --- a/go/host/rpc/clientapi/client_api_eth.go +++ b/go/host/rpc/clientapi/client_api_eth.go @@ -204,7 +204,9 @@ func (api *EthereumAPI) FeeHistory(context.Context, string, rpc.BlockNumber, []f } for _, header := range batches { - feeHist.GasUsedRatio = append(feeHist.GasUsedRatio, 0.9) // todo @siliev - fix when baseFee is dynamic + // 0.9 - This number represents how full the block is. As we dont have a dynamic base fee, we tell whomever is requesting that + // we expect the baseFee to increase, rather than decrease in order to avoid underpriced transactions. + feeHist.GasUsedRatio = append(feeHist.GasUsedRatio, 0.9) feeHist.BaseFee = append(feeHist.BaseFee, (*hexutil.Big)(header.BaseFee)) } return feeHist, nil From 3949823200bddd71afc16e8b36d583f785e94d18 Mon Sep 17 00:00:00 2001 From: StefanIliev545 Date: Mon, 22 Jan 2024 13:23:49 +0200 Subject: [PATCH 24/26] Linter and other unpushed stuff. --- go/enclave/evm/evm_facade.go | 3 +-- go/enclave/gas/oracle.go | 3 +++ go/enclave/nodetype/sequencer.go | 10 ---------- integration/common/utils.go | 8 ++++---- 4 files changed, 8 insertions(+), 16 deletions(-) diff --git a/go/enclave/evm/evm_facade.go b/go/enclave/evm/evm_facade.go index d57886195a..d67a4879d8 100644 --- a/go/enclave/evm/evm_facade.go +++ b/go/enclave/evm/evm_facade.go @@ -131,6 +131,7 @@ func executeTransaction( l1Gas := big.NewInt(0) hasL1Cost := l1cost.Cmp(big.NewInt(0)) != 0 + // If a transaction has to be published on the l1, it will have an l1 cost if hasL1Cost { l1Gas.Div(l1cost, header.BaseFee) // TotalCost/CostPerGas = Gas l1Gas.Add(l1Gas, big.NewInt(1)) // Cover from leftover from the division @@ -149,7 +150,6 @@ func executeTransaction( // and pay it to the coinbase of the batch statedb.SubBalance(msg.From, l1cost) statedb.AddBalance(header.Coinbase, l1cost) - } // Create a new context to be used in the EVM environment @@ -163,7 +163,6 @@ func executeTransaction( statedb.SubBalance(header.Coinbase, l1cost) statedb.AddBalance(msg.From, l1cost) } - return receipt, err } diff --git a/go/enclave/gas/oracle.go b/go/enclave/gas/oracle.go index efa13c3ebe..8ab2cc8d24 100644 --- a/go/enclave/gas/oracle.go +++ b/go/enclave/gas/oracle.go @@ -59,6 +59,9 @@ func (o *oracle) EstimateL1CostForMsg(args *gethapi.TransactionArgs, block *type encoded = append(encoded, *args.Data...) } + // We get the non zero gas cost per byte of calldata, and multiply it by the fixed bytes + // of a transaction. Then we take the data of a transaction and calculate the l1 gas used for it. + // Both are added together and multiplied by the base fee to give us the final cost for the message. nonZeroGas := big.NewInt(int64(params.TxDataNonZeroGasEIP2028)) overhead := big.NewInt(0).Mul(big.NewInt(150), nonZeroGas) l1Gas := CalculateL1GasUsed(encoded, overhead) diff --git a/go/enclave/nodetype/sequencer.go b/go/enclave/nodetype/sequencer.go index 75d245f535..0fe421f1a3 100644 --- a/go/enclave/nodetype/sequencer.go +++ b/go/enclave/nodetype/sequencer.go @@ -196,14 +196,6 @@ func (s *sequencer) createGenesisBatch(block *common.L1Block) error { return nil } -type SortableTransactions types.Transactions - -func (c SortableTransactions) Len() int { return len(c) } -func (c SortableTransactions) Swap(i, j int) { c[i], c[j] = c[j], c[i] } -func (c SortableTransactions) Less(i, j int) bool { - return c[i].Nonce() < c[j].Nonce() -} - func (s *sequencer) createNewHeadBatch(l1HeadBlock *common.L1Block, skipBatchIfEmpty bool) error { headBatchSeq := s.batchRegistry.HeadBatchSeq() if headBatchSeq == nil { @@ -244,8 +236,6 @@ func (s *sequencer) createNewHeadBatch(l1HeadBlock *common.L1Block, skipBatchIfE } } - sort.Sort(SortableTransactions(transactions)) - sequencerNo, err := s.storage.FetchCurrentSequencerNo() if err != nil { return err diff --git a/integration/common/utils.go b/integration/common/utils.go index 7af2238911..327dc575a7 100644 --- a/integration/common/utils.go +++ b/integration/common/utils.go @@ -105,7 +105,7 @@ func PrefundWallets(ctx context.Context, faucetWallet wallet.Wallet, faucetClien To: &destAddr, } - tx := faucetClient.EstimateGasAndGasPrice(txData) + tx := faucetClient.EstimateGasAndGasPrice(txData) // nolint: contextcheck signedTx, err := faucetWallet.SignTransaction(tx) if err != nil { panic(err) @@ -113,9 +113,9 @@ func PrefundWallets(ctx context.Context, faucetWallet wallet.Wallet, faucetClien err = faucetClient.SendTransaction(ctx, signedTx) if err != nil { - var txJson []byte - txJson, _ = signedTx.MarshalJSON() - panic(fmt.Sprintf("could not transfer from faucet for tx %s. Cause: %s", string(txJson[:]), err)) + var txJSON []byte + txJSON, _ = signedTx.MarshalJSON() + panic(fmt.Sprintf("could not transfer from faucet for tx %s. Cause: %s", string(txJSON[:]), err)) } txHashes[idx] = signedTx.Hash() From 50bdd25d43e657eb465a80556cc9b7016e7219b7 Mon Sep 17 00:00:00 2001 From: StefanIliev545 Date: Mon, 22 Jan 2024 13:26:06 +0200 Subject: [PATCH 25/26] Stupid linter. --- integration/common/utils.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration/common/utils.go b/integration/common/utils.go index 327dc575a7..1b703d9382 100644 --- a/integration/common/utils.go +++ b/integration/common/utils.go @@ -105,7 +105,7 @@ func PrefundWallets(ctx context.Context, faucetWallet wallet.Wallet, faucetClien To: &destAddr, } - tx := faucetClient.EstimateGasAndGasPrice(txData) // nolint: contextcheck + tx := faucetClient.EstimateGasAndGasPrice(txData) //nolint: contextcheck signedTx, err := faucetWallet.SignTransaction(tx) if err != nil { panic(err) From 36c95bbe387bcb2bc025e3be639f19015512b431 Mon Sep 17 00:00:00 2001 From: StefanIliev545 Date: Mon, 22 Jan 2024 14:10:58 +0200 Subject: [PATCH 26/26] Fix for new test. --- integration/obscurogateway/tengateway_test.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/integration/obscurogateway/tengateway_test.go b/integration/obscurogateway/tengateway_test.go index 664d60dff3..bee7661d9c 100644 --- a/integration/obscurogateway/tengateway_test.go +++ b/integration/obscurogateway/tengateway_test.go @@ -283,6 +283,9 @@ func testSubscriptionTopics(t *testing.T, httpURL, wsURL string, w wallet.Wallet Data: gethcommon.FromHex(eventsContractBytecode), } + err = getFeeAndGas(user0.HTTPClient, w, deployTx) + require.NoError(t, err) + signedTx, err := w.SignTransaction(deployTx) require.NoError(t, err)