From 2c89a7f4f0fda66bdca39801b01d70478f1ba02b Mon Sep 17 00:00:00 2001 From: vahoo5 Date: Mon, 22 May 2023 01:09:25 +0200 Subject: [PATCH 01/28] F --- core/state_processor.go | 53 +++++ core/types/transaction_signing.go | 17 ++ eth/backend.go | 2 +- internal/ethapi/api.go | 316 ++++++++++++++++++++++++++++ internal/ethapi/backend.go | 7 +- internal/ethapi/transaction_args.go | 43 ++++ les/client.go | 2 +- 7 files changed, 437 insertions(+), 3 deletions(-) diff --git a/core/state_processor.go b/core/state_processor.go index 03de673e19..e0cafa1557 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -17,6 +17,7 @@ package core import ( + "encoding/json" "fmt" "math/big" @@ -159,3 +160,55 @@ func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *commo vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, config, cfg) return applyTransaction(msg, config, gp, statedb, header.Number, header.Hash(), tx, usedGas, vmenv) } + +func applyTransactionWithResult(msg *Message, config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, msgTx *Message, usedGas *uint64, evm *vm.EVM, tracer TracerResult) (*types.Receipt, *ExecutionResult, interface{}, error) { + // Create a new context to be used in the EVM environment. + txContext := NewEVMTxContext(msg) + evm.Reset(txContext, statedb) + + // Apply the transaction to the current state (included in the env). + result, err := ApplyMessage(evm, msg, gp) + if err != nil { + return nil, nil, nil, err + } + + traceResult, err := tracer.GetResult() + // Update the state with pending changes. + var root []byte + if config.IsByzantium(header.Number) { + // statedb.GetRefund() + + } else { + root = statedb.IntermediateRoot(config.IsEIP158(header.Number)).Bytes() + } + *usedGas += result.UsedGas + + // Create a new receipt for the transaction, storing the intermediate root and gas used + // by the tx. + receipt := &types.Receipt{Type: 0, PostState: root, CumulativeGasUsed: *usedGas} + if result.Failed() { + receipt.Status = types.ReceiptStatusFailed + } else { + receipt.Status = types.ReceiptStatusSuccessful + } + // receipt.TxHash = tx.Hash() + receipt.GasUsed = result.UsedGas + + // Set the receipt logs and create the bloom filter. + receipt.BlockHash = header.Hash() + receipt.BlockNumber = header.Number + receipt.TransactionIndex = uint(statedb.TxIndex()) + return receipt, result, traceResult, err +} + +func ApplyTransactionWithResult(config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, msg *Message, usedGas *uint64, cfg vm.Config) (*types.Receipt, *ExecutionResult, error) { + // Create a new context to be used in the EVM environment + blockContext := NewEVMBlockContext(header, bc, author) + vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, config, cfg) + receipt, result, _, err := applyTransactionWithResult(msg, config, bc, author, gp, statedb, header, msg, usedGas, vmenv, nil) + return receipt, result, err +} + +type TracerResult interface { + GetResult() (json.RawMessage, error) +} diff --git a/core/types/transaction_signing.go b/core/types/transaction_signing.go index 59dd2e76eb..5f4e6894ee 100644 --- a/core/types/transaction_signing.go +++ b/core/types/transaction_signing.go @@ -594,3 +594,20 @@ func deriveChainId(v *big.Int) *big.Int { v = new(big.Int).Sub(v, big.NewInt(35)) return v.Div(v, big.NewInt(2)) } + +func MakeSigner2(config *params.ChainConfig, blockNumber *big.Int) Signer { + var signer Signer + switch { + case config.IsLondon(blockNumber): + signer = NewLondonSigner(config.ChainID) + case config.IsBerlin(blockNumber): + signer = NewEIP2930Signer(config.ChainID) + case config.IsEIP155(blockNumber): + signer = NewEIP155Signer(config.ChainID) + case config.IsHomestead(blockNumber): + signer = HomesteadSigner{} + default: + signer = FrontierSigner{} + } + return signer +} diff --git a/eth/backend.go b/eth/backend.go index 4caab9bad6..f7f68611b0 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -282,7 +282,7 @@ func makeExtraData(extra []byte) []byte { // APIs return the collection of RPC services the ethereum package offers. // NOTE, some of these services probably need to be moved to somewhere else. func (s *Ethereum) APIs() []rpc.API { - apis := ethapi.GetAPIs(s.APIBackend) + apis := ethapi.GetAPIs(s.APIBackend, s.BlockChain()) // Append any APIs exposed explicitly by the consensus engine apis = append(apis, s.engine.APIs(s.BlockChain())...) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 9a821be0c1..e2a361f76d 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -22,6 +22,7 @@ import ( "errors" "fmt" "math/big" + "strconv" "strings" "time" @@ -54,6 +55,15 @@ type EthereumAPI struct { b Backend } +type BundleAPI struct { + b Backend + chain *core.BlockChain +} + +func NewBundleAPI(b Backend, chain *core.BlockChain) *BundleAPI { + return &BundleAPI{b, chain} +} + // NewEthereumAPI creates a new Ethereum protocol API. func NewEthereumAPI(b Backend) *EthereumAPI { return &EthereumAPI{b} @@ -1045,6 +1055,158 @@ func DoCall(ctx context.Context, b Backend, args TransactionArgs, blockNrOrHash return result, nil } +// func DoCallBundle(ctx context.Context, b Backend, args TransactionArgsBundle, blockNrOrHash rpc.BlockNumberOrHash, overrides *StateOverride, blockOverrides *BlockOverrides, timeout time.Duration, globalGasCap uint64) ([]map[string]interface{}, error) { +// defer func(start time.Time) { log.Debug("Executing EVM call finished", "runtime", time.Since(start)) }(time.Now()) + +// state, header, err := b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash) +// if state == nil || err != nil { +// return nil, err +// } +// if err := overrides.Apply(state); err != nil { +// return nil, err +// } +// // Setup context so it may be cancelled the call has completed +// // or, in case of unmetered gas, setup a context with a timeout. +// var cancel context.CancelFunc +// if timeout > 0 { +// ctx, cancel = context.WithTimeout(ctx, timeout) +// } else { +// ctx, cancel = context.WithCancel(ctx) +// } +// // Make sure the context is cancelled when the call has completed +// // this makes sure resources are cleaned up. +// defer cancel() + +// // Get a new instance of the EVM. +// results := []map[string]interface{}{} + +// // tx will be the first of the bundle +// blockCtx := core.NewEVMBlockContext(header, NewChainContext(ctx, b), nil) +// if blockOverrides != nil { +// blockOverrides.Apply(&blockCtx) +// } + +// gp := new(core.GasPool).AddGas(math.MaxUint64) +// for i, tx := range args.Transactions { +// msg, err := tx.ToMessage(globalGasCap, header.BaseFee) +// if err != nil { +// return nil, err +// } + +// result, err := core.ApplyTransaction(s.b.ChainConfig(), ) +// // print result +// fmt.Println(result) +// jsonResult := map[string]interface{}{ +// "gasUsed": result.UsedGas, +// } +// fmt.Println(i) +// if result.Err != nil { +// fmt.Println("error 1") +// jsonResult["error"] = result.Err.Error() +// revert := result.Revert() +// if len(revert) > 0 { +// jsonResult["revert"] = string(revert) +// } +// } else { +// fmt.Println("error 2") +// dst := make([]byte, hex.EncodedLen(len(result.Return()))) +// hex.Encode(dst, result.Return()) +// jsonResult["value"] = "0x" + string(dst) +// } +// results = append(results, jsonResult) +// } +// return results, nil +// } + +func DoCall2(ctx context.Context, b Backend, args TransactionArgs2, blockNrOrHash rpc.BlockNumberOrHash, overrides *StateOverride, blockOverrides *BlockOverrides, timeout time.Duration, globalGasCap uint64) (*core.ExecutionResult, error) { + defer func(start time.Time) { log.Debug("Executing EVM call finished", "runtime", time.Since(start)) }(time.Now()) + + state, header, err := b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash) + if state == nil || err != nil { + return nil, err + } + if err := overrides.Apply(state); err != nil { + return nil, err + } + // Setup context so it may be cancelled the call has completed + // or, in case of unmetered gas, setup a context with a timeout. + var cancel context.CancelFunc + if timeout > 0 { + ctx, cancel = context.WithTimeout(ctx, timeout) + } else { + ctx, cancel = context.WithCancel(ctx) + } + // Make sure the context is cancelled when the call has completed + // this makes sure resources are cleaned up. + defer cancel() + + args1 := TransactionArgs{ + From: args.From, + To: args.To, + Gas: args.Gas, + GasPrice: args.GasPrice, + MaxFeePerGas: args.MaxFeePerGas, + MaxPriorityFeePerGas: args.MaxPriorityFeePerGas, + Value: args.Value, + Nonce: args.Nonce, + Data: args.Data, + Input: args.Input, + AccessList: args.AccessList, + ChainID: args.ChainID, + } + + args2 := TransactionArgs{ + From: args.From1, + To: args.To1, + Gas: args.Gas1, + GasPrice: args.GasPrice1, + MaxFeePerGas: args.MaxFeePerGas1, + MaxPriorityFeePerGas: args.MaxPriorityFeePerGas1, + Value: args.Value1, + Nonce: args.Nonce1, + Data: args.Data1, + Input: args.Input1, + AccessList: args.AccessList1, + ChainID: args.ChainID1, + } + + // Get a new instance of the EVM. + msg1, err := args1.ToMessage(globalGasCap, header.BaseFee) + if err != nil { + return nil, err + } + msg2, err := args2.ToMessage(globalGasCap, header.BaseFee) + blockCtx := core.NewEVMBlockContext(header, NewChainContext(ctx, b), nil) + if blockOverrides != nil { + blockOverrides.Apply(&blockCtx) + } + evm, vmError := b.GetEVM(ctx, msg1, state, header, &vm.Config{NoBaseFee: true}, &blockCtx) + + // Wait for the context to be done and cancel the evm. Even if the + // EVM has finished, cancelling may be done (repeatedly) + go func() { + <-ctx.Done() + evm.Cancel() + }() + + // Execute the message. + gp := new(core.GasPool).AddGas(math.MaxUint64) + core.ApplyMessage(evm, msg1, gp) + result, err := core.ApplyMessage(evm, msg2, gp) + if err := vmError(); err != nil { + return nil, err + } + + // If the timer caused an abort, return an appropriate error message + if evm.Cancelled() { + return nil, fmt.Errorf("execution aborted (timeout = %v)", timeout) + } + if err != nil { + return result, fmt.Errorf("err: %w (supplied gas %d)", err, msg1.GasLimit) + } + return result, nil +} + func newRevertError(result *core.ExecutionResult) *revertError { reason, errUnpack := abi.UnpackRevert(result.Revert()) err := errors.New("execution reverted") @@ -1093,6 +1255,160 @@ func (s *BlockChainAPI) Call(ctx context.Context, args TransactionArgs, blockNrO return result.Return(), result.Err } +func (s *BlockChainAPI) BatchCall(ctx context.Context, args TransactionArgs2, blockNrOrHash rpc.BlockNumberOrHash, overrides *StateOverride, blockOverrides *BlockOverrides) (hexutil.Bytes, error) { + result, err := DoCall2(ctx, s.b, args, blockNrOrHash, overrides, blockOverrides, s.b.RPCEVMTimeout(), s.b.RPCGasCap()) + if err != nil { + return nil, err + } + // If the result contains a revert reason, try to unpack and return it. + if len(result.Revert()) > 0 { + return nil, newRevertError(result) + } + return result.Return(), result.Err +} + +// func (s *BundleAPI) BundleCall(ctx context.Context, args TransactionArgsBundle, blockNrOrHash rpc.BlockNumberOrHash, overrides *StateOverride, blockOverrides *BlockOverrides) ([]map[string]interface{}, error) { +// result, _ := DoCallBundle(ctx, s.b, args, blockNrOrHash, overrides, blockOverrides, s.b.RPCEVMTimeout(), s.b.RPCGasCap()) + +// return result, nil +// } + +func (s *BundleAPI) CallBundle(ctx context.Context, args CallBundleArgs) (map[string]interface{}, error) { + if len(args.Transactions) == 0 { + return nil, errors.New("bundle missing txs") + } + if args.BlockNumber == 0 { + return nil, errors.New("bundle missing blockNumber") + } + + defer func(start time.Time) { log.Debug("Executing EVM call finished", "runtime", time.Since(start)) }(time.Now()) + + timeoutMilliSeconds := int64(5000) + if args.Timeout != nil { + timeoutMilliSeconds = *args.Timeout + } + timeout := time.Millisecond * time.Duration(timeoutMilliSeconds) + fmt.Println("state", args.StateBlockNumberOrHash) + state, parent, err := s.b.StateAndHeaderByNumberOrHash(ctx, args.StateBlockNumberOrHash) + if state == nil || err != nil { + return nil, err + } + blockNumber := big.NewInt(int64(args.BlockNumber)) + fmt.Println("blockNumber", blockNumber) + timestamp := parent.Time + 1 + if args.Timestamp != nil { + timestamp = *args.Timestamp + } + coinbase := parent.Coinbase + if args.Coinbase != nil { + coinbase = common.HexToAddress(*args.Coinbase) + } + difficulty := parent.Difficulty + if args.Difficulty != nil { + difficulty = args.Difficulty + } + gasLimit := parent.GasLimit + if args.GasLimit != nil { + gasLimit = *args.GasLimit + } + var baseFee *big.Int + if args.BaseFee != nil { + baseFee = args.BaseFee + } else if s.b.ChainConfig().IsLondon(big.NewInt(args.BlockNumber.Int64())) { + baseFee = misc.CalcBaseFee(s.b.ChainConfig(), parent) + } + header := &types.Header{ + ParentHash: parent.Hash(), + Number: blockNumber, + GasLimit: gasLimit, + Time: timestamp, + Difficulty: difficulty, + Coinbase: coinbase, + BaseFee: baseFee, + } + + // Setup context so it may be cancelled the call has completed + // or, in case of unmetered gas, setup a context with a timeout. + var cancel context.CancelFunc + if timeout > 0 { + ctx, cancel = context.WithTimeout(ctx, timeout) + } else { + ctx, cancel = context.WithCancel(ctx) + } + // Make sure the context is cancelled when the call has completed + // this makes sure resources are cleaned up. + defer cancel() + + vmconfig := vm.Config{} + + // Setup the gas pool (also for unmetered requests) + // and apply the message. + gp := new(core.GasPool).AddGas(math.MaxUint64) + + results := []map[string]interface{}{} + coinbaseBalanceBefore := state.GetBalance(coinbase) + + var totalGasUsed uint64 + gasFees := new(big.Int) + uint64MaxValue := uint64(math.MaxUint64) + for i, tx := range args.Transactions { + fmt.Println("tx", tx) + msg, err := tx.ToMessage(uint64MaxValue, header.BaseFee) + if err != nil { + return nil, err + } + coinbaseBalanceBeforeTx := state.GetBalance(coinbase) + randomHash := common.HexToHash("0x" + strconv.Itoa(i)) + state.SetTxContext(randomHash, i) + + receipt, result, err := core.ApplyTransactionWithResult(s.b.ChainConfig(), s.chain, &coinbase, gp, state, header, msg, &header.GasUsed, vmconfig) + if err != nil { + return nil, fmt.Errorf("err: %w; txhash %s", err, randomHash) + } + + txHash := randomHash.String() + if err != nil { + return nil, fmt.Errorf("err: %w; txhash %s", err, randomHash) + } + to := "0x" + + jsonResult := map[string]interface{}{ + "txHash": txHash, + "gasUsed": receipt.GasUsed, + "toAddress": to, + } + totalGasUsed += receipt.GasUsed + if result.Err != nil { + jsonResult["error"] = result.Err.Error() + revert := result.Revert() + if len(revert) > 0 { + jsonResult["revert"] = string(revert) + } + } else { + dst := make([]byte, hex.EncodedLen(len(result.Return()))) + hex.Encode(dst, result.Return()) + jsonResult["value"] = "0x" + string(dst) + } + coinbaseDiffTx := new(big.Int).Sub(state.GetBalance(coinbase), coinbaseBalanceBeforeTx) + jsonResult["coinbaseDiff"] = coinbaseDiffTx.String() + jsonResult["gasPrice"] = new(big.Int).Div(coinbaseDiffTx, big.NewInt(int64(receipt.GasUsed))).String() + jsonResult["gasUsed"] = receipt.GasUsed + results = append(results, jsonResult) + } + + ret := map[string]interface{}{} + ret["results"] = results + coinbaseDiff := new(big.Int).Sub(state.GetBalance(coinbase), coinbaseBalanceBefore) + ret["coinbaseDiff"] = coinbaseDiff.String() + ret["gasFees"] = gasFees.String() + ret["ethSentToCoinbase"] = new(big.Int).Sub(coinbaseDiff, gasFees).String() + ret["bundleGasPrice"] = new(big.Int).Div(coinbaseDiff, big.NewInt(int64(totalGasUsed))).String() + ret["totalGasUsed"] = totalGasUsed + ret["stateBlockNumber"] = parent.Number.Int64() + + return ret, nil +} + func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, gasCap uint64) (hexutil.Uint64, error) { // Binary search the gas requirement, as it may be higher than the amount used var ( diff --git a/internal/ethapi/backend.go b/internal/ethapi/backend.go index 918b3b6309..8b5b02d813 100644 --- a/internal/ethapi/backend.go +++ b/internal/ethapi/backend.go @@ -99,7 +99,7 @@ type Backend interface { ServiceFilter(ctx context.Context, session *bloombits.MatcherSession) } -func GetAPIs(apiBackend Backend) []rpc.API { +func GetAPIs(apiBackend Backend, chain *core.BlockChain) []rpc.API { nonceLock := new(AddrLocker) return []rpc.API{ { @@ -123,6 +123,11 @@ func GetAPIs(apiBackend Backend) []rpc.API { }, { Namespace: "personal", Service: NewPersonalAccountAPI(apiBackend, nonceLock), + }, { + Namespace: "eth", + Version: "1.0", + Service: NewBundleAPI(apiBackend, chain), + Public: true, }, } } diff --git a/internal/ethapi/transaction_args.go b/internal/ethapi/transaction_args.go index c74f540b76..092e926aeb 100644 --- a/internal/ethapi/transaction_args.go +++ b/internal/ethapi/transaction_args.go @@ -55,6 +55,49 @@ type TransactionArgs struct { ChainID *hexutil.Big `json:"chainId,omitempty"` } +type TransactionArgsBundle struct { + Transactions []TransactionArgs `json:"transactions"` +} + +type CallBundleArgs struct { + Transactions []TransactionArgs `json:"transactions"` + BlockNumber rpc.BlockNumber `json:"blockNumber"` + StateBlockNumberOrHash rpc.BlockNumberOrHash `json:"stateBlockNumber"` + Coinbase *string `json:"coinbase"` + Timestamp *uint64 `json:"timestamp"` + Timeout *int64 `json:"timeout"` + GasLimit *uint64 `json:"gasLimit"` + Difficulty *big.Int `json:"difficulty"` + BaseFee *big.Int `json:"baseFee"` +} + +type TransactionArgs2 struct { + From *common.Address `json:"from"` + To *common.Address `json:"to"` + Gas *hexutil.Uint64 `json:"gas"` + GasPrice *hexutil.Big `json:"gasPrice"` + MaxFeePerGas *hexutil.Big `json:"maxFeePerGas"` + MaxPriorityFeePerGas *hexutil.Big `json:"maxPriorityFeePerGas"` + Value *hexutil.Big `json:"value"` + Nonce *hexutil.Uint64 `json:"nonce"` + Data *hexutil.Bytes `json:"data"` + Input *hexutil.Bytes `json:"input"` + AccessList *types.AccessList `json:"accessList,omitempty"` + ChainID *hexutil.Big `json:"chainId,omitempty"` + From1 *common.Address `json:"from1"` + To1 *common.Address `json:"to1"` + Gas1 *hexutil.Uint64 `json:"gas1"` + GasPrice1 *hexutil.Big `json:"gasPrice1"` + MaxFeePerGas1 *hexutil.Big `json:"maxFeePerGas1"` + MaxPriorityFeePerGas1 *hexutil.Big `json:"maxPriorityFeePerGas1"` + Value1 *hexutil.Big `json:"value1"` + Nonce1 *hexutil.Uint64 `json:"nonce1"` + Data1 *hexutil.Bytes `json:"data1"` + Input1 *hexutil.Bytes `json:"input1"` + AccessList1 *types.AccessList `json:"accessList1,omitempty"` + ChainID1 *hexutil.Big `json:"chainId1,omitempty"` +} + // from retrieves the transaction sender address. func (args *TransactionArgs) from() common.Address { if args.From == nil { diff --git a/les/client.go b/les/client.go index 9561ba777e..75277a0ca7 100644 --- a/les/client.go +++ b/les/client.go @@ -289,7 +289,7 @@ func (s *LightDummyAPI) Mining() bool { // APIs returns the collection of RPC services the ethereum package offers. // NOTE, some of these services probably need to be moved to somewhere else. func (s *LightEthereum) APIs() []rpc.API { - apis := ethapi.GetAPIs(s.ApiBackend) + apis := ethapi.GetAPIs(s.ApiBackend, nil) apis = append(apis, s.engine.APIs(s.BlockChain().HeaderChain())...) return append(apis, []rpc.API{ { From 27a7aa25dc29cf5887e5d0d6e432f66a98b5be14 Mon Sep 17 00:00:00 2001 From: vahoo5 Date: Mon, 22 May 2023 02:00:29 +0200 Subject: [PATCH 02/28] F --- internal/ethapi/api.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index e2a361f76d..8ae40ed390 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1340,7 +1340,7 @@ func (s *BundleAPI) CallBundle(ctx context.Context, args CallBundleArgs) (map[st defer cancel() vmconfig := vm.Config{} - + vmconfig.NoBaseFee = true // Setup the gas pool (also for unmetered requests) // and apply the message. gp := new(core.GasPool).AddGas(math.MaxUint64) From 68af999c35ba44bc519134ace54273241da5e93a Mon Sep 17 00:00:00 2001 From: vahoo5 Date: Mon, 22 May 2023 12:01:32 +0200 Subject: [PATCH 03/28] F --- core/state_processor.go | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/core/state_processor.go b/core/state_processor.go index e0cafa1557..68996fa946 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -161,7 +161,7 @@ func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *commo return applyTransaction(msg, config, gp, statedb, header.Number, header.Hash(), tx, usedGas, vmenv) } -func applyTransactionWithResult(msg *Message, config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, msgTx *Message, usedGas *uint64, evm *vm.EVM, tracer TracerResult) (*types.Receipt, *ExecutionResult, interface{}, error) { +func applyTransactionWithResult(msg *Message, config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, msgTx *Message, usedGas *uint64, evm *vm.EVM) (*types.Receipt, *ExecutionResult, error) { // Create a new context to be used in the EVM environment. txContext := NewEVMTxContext(msg) evm.Reset(txContext, statedb) @@ -169,10 +169,9 @@ func applyTransactionWithResult(msg *Message, config *params.ChainConfig, bc Cha // Apply the transaction to the current state (included in the env). result, err := ApplyMessage(evm, msg, gp) if err != nil { - return nil, nil, nil, err + return nil, nil, err } - traceResult, err := tracer.GetResult() // Update the state with pending changes. var root []byte if config.IsByzantium(header.Number) { @@ -198,14 +197,14 @@ func applyTransactionWithResult(msg *Message, config *params.ChainConfig, bc Cha receipt.BlockHash = header.Hash() receipt.BlockNumber = header.Number receipt.TransactionIndex = uint(statedb.TxIndex()) - return receipt, result, traceResult, err + return receipt, result, err } func ApplyTransactionWithResult(config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, msg *Message, usedGas *uint64, cfg vm.Config) (*types.Receipt, *ExecutionResult, error) { // Create a new context to be used in the EVM environment blockContext := NewEVMBlockContext(header, bc, author) vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, config, cfg) - receipt, result, _, err := applyTransactionWithResult(msg, config, bc, author, gp, statedb, header, msg, usedGas, vmenv, nil) + receipt, result, err := applyTransactionWithResult(msg, config, bc, author, gp, statedb, header, msg, usedGas, vmenv) return receipt, result, err } From c2fb703b761ad154987172064ce1671ba8d072d7 Mon Sep 17 00:00:00 2001 From: vahoo5 Date: Mon, 22 May 2023 12:35:03 +0200 Subject: [PATCH 04/28] F --- internal/ethapi/api.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 8ae40ed390..08280a1a05 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1350,10 +1350,10 @@ func (s *BundleAPI) CallBundle(ctx context.Context, args CallBundleArgs) (map[st var totalGasUsed uint64 gasFees := new(big.Int) - uint64MaxValue := uint64(math.MaxUint64) for i, tx := range args.Transactions { fmt.Println("tx", tx) - msg, err := tx.ToMessage(uint64MaxValue, header.BaseFee) + msg, err := tx.ToMessage(0, header.BaseFee) + fmt.Println("msg", msg) if err != nil { return nil, err } From cc7ae16365bb56cb795dbad23079ff12657feb0e Mon Sep 17 00:00:00 2001 From: vahoo5 Date: Mon, 22 May 2023 13:26:47 +0200 Subject: [PATCH 05/28] F --- internal/ethapi/api.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 08280a1a05..3b42f748e0 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1371,11 +1371,15 @@ func (s *BundleAPI) CallBundle(ctx context.Context, args CallBundleArgs) (map[st return nil, fmt.Errorf("err: %w; txhash %s", err, randomHash) } to := "0x" - + logs := receipt.Logs + if logs == nil { + logs = []*types.Log{} + } jsonResult := map[string]interface{}{ "txHash": txHash, "gasUsed": receipt.GasUsed, "toAddress": to, + "logs": logs, } totalGasUsed += receipt.GasUsed if result.Err != nil { From f73d6984692fceeec00211663373c300a3e9ac3b Mon Sep 17 00:00:00 2001 From: vahoo5 Date: Mon, 22 May 2023 16:42:24 +0200 Subject: [PATCH 06/28] F --- core/state_processor.go | 7 ++++--- internal/ethapi/api.go | 12 ++++-------- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/core/state_processor.go b/core/state_processor.go index 68996fa946..f57c6ebec7 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -161,7 +161,7 @@ func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *commo return applyTransaction(msg, config, gp, statedb, header.Number, header.Hash(), tx, usedGas, vmenv) } -func applyTransactionWithResult(msg *Message, config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, msgTx *Message, usedGas *uint64, evm *vm.EVM) (*types.Receipt, *ExecutionResult, error) { +func applyTransactionWithResult(msg *Message, config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, msgTx *Message, usedGas *uint64, evm *vm.EVM, txHash common.Hash) (*types.Receipt, *ExecutionResult, error) { // Create a new context to be used in the EVM environment. txContext := NewEVMTxContext(msg) evm.Reset(txContext, statedb) @@ -197,14 +197,15 @@ func applyTransactionWithResult(msg *Message, config *params.ChainConfig, bc Cha receipt.BlockHash = header.Hash() receipt.BlockNumber = header.Number receipt.TransactionIndex = uint(statedb.TxIndex()) + receipt.Logs = statedb.GetLogs(txHash, header.Number.Uint64(), header.Hash()) return receipt, result, err } -func ApplyTransactionWithResult(config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, msg *Message, usedGas *uint64, cfg vm.Config) (*types.Receipt, *ExecutionResult, error) { +func ApplyTransactionWithResult(config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, msg *Message, usedGas *uint64, cfg vm.Config, txHash common.Hash) (*types.Receipt, *ExecutionResult, error) { // Create a new context to be used in the EVM environment blockContext := NewEVMBlockContext(header, bc, author) vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, config, cfg) - receipt, result, err := applyTransactionWithResult(msg, config, bc, author, gp, statedb, header, msg, usedGas, vmenv) + receipt, result, err := applyTransactionWithResult(msg, config, bc, author, gp, statedb, header, msg, usedGas, vmenv, txHash) return receipt, result, err } diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 3b42f748e0..3475588206 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1351,9 +1351,7 @@ func (s *BundleAPI) CallBundle(ctx context.Context, args CallBundleArgs) (map[st var totalGasUsed uint64 gasFees := new(big.Int) for i, tx := range args.Transactions { - fmt.Println("tx", tx) msg, err := tx.ToMessage(0, header.BaseFee) - fmt.Println("msg", msg) if err != nil { return nil, err } @@ -1361,7 +1359,7 @@ func (s *BundleAPI) CallBundle(ctx context.Context, args CallBundleArgs) (map[st randomHash := common.HexToHash("0x" + strconv.Itoa(i)) state.SetTxContext(randomHash, i) - receipt, result, err := core.ApplyTransactionWithResult(s.b.ChainConfig(), s.chain, &coinbase, gp, state, header, msg, &header.GasUsed, vmconfig) + receipt, result, err := core.ApplyTransactionWithResult(s.b.ChainConfig(), s.chain, &coinbase, gp, state, header, msg, &header.GasUsed, vmconfig, randomHash) if err != nil { return nil, fmt.Errorf("err: %w; txhash %s", err, randomHash) } @@ -1370,16 +1368,14 @@ func (s *BundleAPI) CallBundle(ctx context.Context, args CallBundleArgs) (map[st if err != nil { return nil, fmt.Errorf("err: %w; txhash %s", err, randomHash) } - to := "0x" logs := receipt.Logs if logs == nil { logs = []*types.Log{} } jsonResult := map[string]interface{}{ - "txHash": txHash, - "gasUsed": receipt.GasUsed, - "toAddress": to, - "logs": logs, + "txHash": txHash, + "gasUsed": receipt.GasUsed, + "logs": logs, } totalGasUsed += receipt.GasUsed if result.Err != nil { From 601827895a3c9c05c22bb3cdff8e5dd0b09b7376 Mon Sep 17 00:00:00 2001 From: vahoo5 Date: Mon, 22 May 2023 16:54:57 +0200 Subject: [PATCH 07/28] F2 --- internal/ethapi/api.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 3475588206..62d3e11e52 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1376,6 +1376,7 @@ func (s *BundleAPI) CallBundle(ctx context.Context, args CallBundleArgs) (map[st "txHash": txHash, "gasUsed": receipt.GasUsed, "logs": logs, + "status": receipt.Status, } totalGasUsed += receipt.GasUsed if result.Err != nil { From 85a7b34b79b54874f85fcc4621d461ce4b8100c5 Mon Sep 17 00:00:00 2001 From: vahoo5 Date: Mon, 22 May 2023 16:56:10 +0200 Subject: [PATCH 08/28] F --- internal/ethapi/api.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 62d3e11e52..7bae80141d 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1379,6 +1379,7 @@ func (s *BundleAPI) CallBundle(ctx context.Context, args CallBundleArgs) (map[st "status": receipt.Status, } totalGasUsed += receipt.GasUsed + fmt.Println("result", result) if result.Err != nil { jsonResult["error"] = result.Err.Error() revert := result.Revert() From 050894856997e6771985194e2c6a3c1e771da525 Mon Sep 17 00:00:00 2001 From: vahoo5 Date: Wed, 24 May 2023 16:32:58 +0200 Subject: [PATCH 09/28] F --- internal/ethapi/api.go | 192 ++++++++++++++++------------ internal/ethapi/transaction_args.go | 7 +- 2 files changed, 118 insertions(+), 81 deletions(-) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 7bae80141d..777f30ddc6 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1055,68 +1055,104 @@ func DoCall(ctx context.Context, b Backend, args TransactionArgs, blockNrOrHash return result, nil } -// func DoCallBundle(ctx context.Context, b Backend, args TransactionArgsBundle, blockNrOrHash rpc.BlockNumberOrHash, overrides *StateOverride, blockOverrides *BlockOverrides, timeout time.Duration, globalGasCap uint64) ([]map[string]interface{}, error) { -// defer func(start time.Time) { log.Debug("Executing EVM call finished", "runtime", time.Since(start)) }(time.Now()) +func DoCallBundle(ctx context.Context, b Backend, args TransactionArgsBundle, blockNrOrHash rpc.BlockNumberOrHash, overrides *StateOverride, blockOverrides *BlockOverrides, timeout time.Duration, globalGasCap uint64) (map[string]interface{}, error) { + defer func(start time.Time) { log.Debug("Executing EVM call finished", "runtime", time.Since(start)) }(time.Now()) -// state, header, err := b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash) -// if state == nil || err != nil { -// return nil, err -// } -// if err := overrides.Apply(state); err != nil { -// return nil, err -// } -// // Setup context so it may be cancelled the call has completed -// // or, in case of unmetered gas, setup a context with a timeout. -// var cancel context.CancelFunc -// if timeout > 0 { -// ctx, cancel = context.WithTimeout(ctx, timeout) -// } else { -// ctx, cancel = context.WithCancel(ctx) -// } -// // Make sure the context is cancelled when the call has completed -// // this makes sure resources are cleaned up. -// defer cancel() + state, header, err := b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash) + if state == nil || err != nil { + return nil, err + } + if err := overrides.Apply(state); err != nil { + return nil, err + } + // Setup context so it may be cancelled the call has completed + // or, in case of unmetered gas, setup a context with a timeout. + var cancel context.CancelFunc + if timeout > 0 { + ctx, cancel = context.WithTimeout(ctx, timeout) + } else { + ctx, cancel = context.WithCancel(ctx) + } + // Make sure the context is cancelled when the call has completed + // this makes sure resources are cleaned up. + defer cancel() -// // Get a new instance of the EVM. -// results := []map[string]interface{}{} + transactions1 := args.Transactions1 + transactions2 := args.Transactions2 -// // tx will be the first of the bundle -// blockCtx := core.NewEVMBlockContext(header, NewChainContext(ctx, b), nil) -// if blockOverrides != nil { -// blockOverrides.Apply(&blockCtx) -// } + // Get a new instance of the EVM. + msg, err := transactions1[0].ToMessage(globalGasCap, header.BaseFee) + if err != nil { + return nil, err + } + blockCtx := core.NewEVMBlockContext(header, NewChainContext(ctx, b), nil) + if blockOverrides != nil { + blockOverrides.Apply(&blockCtx) + } -// gp := new(core.GasPool).AddGas(math.MaxUint64) -// for i, tx := range args.Transactions { -// msg, err := tx.ToMessage(globalGasCap, header.BaseFee) -// if err != nil { -// return nil, err -// } + results1 := []map[string]interface{}{} + results2 := []map[string]interface{}{} + // Execute the message. + gp := new(core.GasPool).AddGas(math.MaxUint64) + ret := map[string]interface{}{} + for i, tx2 := range transactions2 { + evm, vmError := b.GetEVM(ctx, msg, state, header, &vm.Config{NoBaseFee: true}, &blockCtx) + for j, tx := range transactions1 { -// result, err := core.ApplyTransaction(s.b.ChainConfig(), ) -// // print result -// fmt.Println(result) -// jsonResult := map[string]interface{}{ -// "gasUsed": result.UsedGas, -// } -// fmt.Println(i) -// if result.Err != nil { -// fmt.Println("error 1") -// jsonResult["error"] = result.Err.Error() -// revert := result.Revert() -// if len(revert) > 0 { -// jsonResult["revert"] = string(revert) -// } -// } else { -// fmt.Println("error 2") -// dst := make([]byte, hex.EncodedLen(len(result.Return()))) -// hex.Encode(dst, result.Return()) -// jsonResult["value"] = "0x" + string(dst) -// } -// results = append(results, jsonResult) -// } -// return results, nil -// } + msg, err = tx.ToMessage(globalGasCap, header.BaseFee) + if err != nil { + return nil, err + } + blockNumber := args.BlockNumbers1[j] + blockCtx.BlockNumber = big.NewInt(int64(blockNumber)) + result, _ := core.ApplyMessage(evm, msg, gp) + if err := vmError(); err != nil { + return nil, err + } + jsonResult := map[string]interface{}{} + if result.Err != nil { + jsonResult["error"] = result.Err.Error() + revert := result.Revert() + if len(revert) > 0 { + jsonResult["revert"] = string(revert) + } + } else { + dst := make([]byte, hex.EncodedLen(len(result.Return()))) + hex.Encode(dst, result.Return()) + jsonResult["value"] = "0x" + string(dst) + } + results1 = append(results1, jsonResult) + } + msg, err = tx2.ToMessage(globalGasCap, header.BaseFee) + if err != nil { + return nil, err + } + blockNumber := args.BlockNumbers2[i] + blockCtx.BlockNumber = big.NewInt(int64(blockNumber)) + result, _ := core.ApplyMessage(evm, msg, gp) + if err := vmError(); err != nil { + return nil, err + } + + jsonResult := map[string]interface{}{} + if result.Err != nil { + jsonResult["error"] = result.Err.Error() + revert := result.Revert() + if len(revert) > 0 { + jsonResult["revert"] = string(revert) + } + } else { + dst := make([]byte, hex.EncodedLen(len(result.Return()))) + hex.Encode(dst, result.Return()) + jsonResult["value"] = "0x" + string(dst) + } + results2 = append(results2, jsonResult) + } + + ret["results1"] = results1 + ret["results2"] = results2 + return ret, nil +} func DoCall2(ctx context.Context, b Backend, args TransactionArgs2, blockNrOrHash rpc.BlockNumberOrHash, overrides *StateOverride, blockOverrides *BlockOverrides, timeout time.Duration, globalGasCap uint64) (*core.ExecutionResult, error) { defer func(start time.Time) { log.Debug("Executing EVM call finished", "runtime", time.Since(start)) }(time.Now()) @@ -1255,6 +1291,15 @@ func (s *BlockChainAPI) Call(ctx context.Context, args TransactionArgs, blockNrO return result.Return(), result.Err } +func (s *BlockChainAPI) Call2(ctx context.Context, args TransactionArgsBundle, blockNrOrHash rpc.BlockNumberOrHash, overrides *StateOverride, blockOverrides *BlockOverrides) (map[string]interface{}, error) { + result, err := DoCallBundle(ctx, s.b, args, blockNrOrHash, overrides, blockOverrides, s.b.RPCEVMTimeout(), s.b.RPCGasCap()) + if err != nil { + return nil, err + } + + return result, nil +} + func (s *BlockChainAPI) BatchCall(ctx context.Context, args TransactionArgs2, blockNrOrHash rpc.BlockNumberOrHash, overrides *StateOverride, blockOverrides *BlockOverrides) (hexutil.Bytes, error) { result, err := DoCall2(ctx, s.b, args, blockNrOrHash, overrides, blockOverrides, s.b.RPCEVMTimeout(), s.b.RPCGasCap()) if err != nil { @@ -1267,19 +1312,10 @@ func (s *BlockChainAPI) BatchCall(ctx context.Context, args TransactionArgs2, bl return result.Return(), result.Err } -// func (s *BundleAPI) BundleCall(ctx context.Context, args TransactionArgsBundle, blockNrOrHash rpc.BlockNumberOrHash, overrides *StateOverride, blockOverrides *BlockOverrides) ([]map[string]interface{}, error) { -// result, _ := DoCallBundle(ctx, s.b, args, blockNrOrHash, overrides, blockOverrides, s.b.RPCEVMTimeout(), s.b.RPCGasCap()) - -// return result, nil -// } - func (s *BundleAPI) CallBundle(ctx context.Context, args CallBundleArgs) (map[string]interface{}, error) { if len(args.Transactions) == 0 { return nil, errors.New("bundle missing txs") } - if args.BlockNumber == 0 { - return nil, errors.New("bundle missing blockNumber") - } defer func(start time.Time) { log.Debug("Executing EVM call finished", "runtime", time.Since(start)) }(time.Now()) @@ -1288,13 +1324,11 @@ func (s *BundleAPI) CallBundle(ctx context.Context, args CallBundleArgs) (map[st timeoutMilliSeconds = *args.Timeout } timeout := time.Millisecond * time.Duration(timeoutMilliSeconds) - fmt.Println("state", args.StateBlockNumberOrHash) state, parent, err := s.b.StateAndHeaderByNumberOrHash(ctx, args.StateBlockNumberOrHash) if state == nil || err != nil { return nil, err } - blockNumber := big.NewInt(int64(args.BlockNumber)) - fmt.Println("blockNumber", blockNumber) + timestamp := parent.Time + 1 if args.Timestamp != nil { timestamp = *args.Timestamp @@ -1314,18 +1348,9 @@ func (s *BundleAPI) CallBundle(ctx context.Context, args CallBundleArgs) (map[st var baseFee *big.Int if args.BaseFee != nil { baseFee = args.BaseFee - } else if s.b.ChainConfig().IsLondon(big.NewInt(args.BlockNumber.Int64())) { + } else if s.b.ChainConfig().IsLondon(big.NewInt(args.BlockNumbers[0].Int64())) { baseFee = misc.CalcBaseFee(s.b.ChainConfig(), parent) } - header := &types.Header{ - ParentHash: parent.Hash(), - Number: blockNumber, - GasLimit: gasLimit, - Time: timestamp, - Difficulty: difficulty, - Coinbase: coinbase, - BaseFee: baseFee, - } // Setup context so it may be cancelled the call has completed // or, in case of unmetered gas, setup a context with a timeout. @@ -1351,6 +1376,15 @@ func (s *BundleAPI) CallBundle(ctx context.Context, args CallBundleArgs) (map[st var totalGasUsed uint64 gasFees := new(big.Int) for i, tx := range args.Transactions { + header := &types.Header{ + ParentHash: parent.Hash(), + Number: big.NewInt(int64(args.BlockNumbers[i])), + GasLimit: gasLimit, + Time: timestamp, + Difficulty: difficulty, + Coinbase: coinbase, + BaseFee: baseFee, + } msg, err := tx.ToMessage(0, header.BaseFee) if err != nil { return nil, err diff --git a/internal/ethapi/transaction_args.go b/internal/ethapi/transaction_args.go index 092e926aeb..c7e5f37cfa 100644 --- a/internal/ethapi/transaction_args.go +++ b/internal/ethapi/transaction_args.go @@ -56,12 +56,15 @@ type TransactionArgs struct { } type TransactionArgsBundle struct { - Transactions []TransactionArgs `json:"transactions"` + Transactions1 []TransactionArgs `json:"transactions1"` + Transactions2 []TransactionArgs `json:"transactions2"` + BlockNumbers1 []rpc.BlockNumber `json:"blockNumbers"` + BlockNumbers2 []rpc.BlockNumber `json:"blockNumbers2"` } type CallBundleArgs struct { Transactions []TransactionArgs `json:"transactions"` - BlockNumber rpc.BlockNumber `json:"blockNumber"` + BlockNumbers []rpc.BlockNumber `json:"blockNumbers"` StateBlockNumberOrHash rpc.BlockNumberOrHash `json:"stateBlockNumber"` Coinbase *string `json:"coinbase"` Timestamp *uint64 `json:"timestamp"` From e4417770f3c16dfc08d1c60fd9868a93ec4e93a5 Mon Sep 17 00:00:00 2001 From: vahoo5 Date: Wed, 24 May 2023 17:37:40 +0200 Subject: [PATCH 10/28] callnew --- internal/ethapi/api.go | 14 ++++++++++++-- internal/ethapi/transaction_args.go | 2 +- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 777f30ddc6..956e6f765b 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1058,6 +1058,13 @@ func DoCall(ctx context.Context, b Backend, args TransactionArgs, blockNrOrHash func DoCallBundle(ctx context.Context, b Backend, args TransactionArgsBundle, blockNrOrHash rpc.BlockNumberOrHash, overrides *StateOverride, blockOverrides *BlockOverrides, timeout time.Duration, globalGasCap uint64) (map[string]interface{}, error) { defer func(start time.Time) { log.Debug("Executing EVM call finished", "runtime", time.Since(start)) }(time.Now()) + if len(args.BlockNumbers1) != len(args.Transactions1) || len(args.BlockNumbers1) == 0 { + return nil, errors.New("block numbers1 and transactions1 must have the same length or empty") + } + if len(args.BlockNumbers2) != len(args.Transactions2) || len(args.BlockNumbers2) == 0 { + return nil, errors.New("block numbers2 and transactions2 must have the same length or empty") + } + state, header, err := b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash) if state == nil || err != nil { return nil, err @@ -1105,7 +1112,10 @@ func DoCallBundle(ctx context.Context, b Backend, args TransactionArgsBundle, bl } blockNumber := args.BlockNumbers1[j] blockCtx.BlockNumber = big.NewInt(int64(blockNumber)) - result, _ := core.ApplyMessage(evm, msg, gp) + result, err := core.ApplyMessage(evm, msg, gp) + if err != nil { + return nil, fmt.Errorf("err: %w (supplied gas %d)", err, msg.GasLimit) + } if err := vmError(); err != nil { return nil, err } @@ -1291,7 +1301,7 @@ func (s *BlockChainAPI) Call(ctx context.Context, args TransactionArgs, blockNrO return result.Return(), result.Err } -func (s *BlockChainAPI) Call2(ctx context.Context, args TransactionArgsBundle, blockNrOrHash rpc.BlockNumberOrHash, overrides *StateOverride, blockOverrides *BlockOverrides) (map[string]interface{}, error) { +func (s *BlockChainAPI) CallNew(ctx context.Context, args TransactionArgsBundle, blockNrOrHash rpc.BlockNumberOrHash, overrides *StateOverride, blockOverrides *BlockOverrides) (map[string]interface{}, error) { result, err := DoCallBundle(ctx, s.b, args, blockNrOrHash, overrides, blockOverrides, s.b.RPCEVMTimeout(), s.b.RPCGasCap()) if err != nil { return nil, err diff --git a/internal/ethapi/transaction_args.go b/internal/ethapi/transaction_args.go index c7e5f37cfa..243c9b4c0f 100644 --- a/internal/ethapi/transaction_args.go +++ b/internal/ethapi/transaction_args.go @@ -58,7 +58,7 @@ type TransactionArgs struct { type TransactionArgsBundle struct { Transactions1 []TransactionArgs `json:"transactions1"` Transactions2 []TransactionArgs `json:"transactions2"` - BlockNumbers1 []rpc.BlockNumber `json:"blockNumbers"` + BlockNumbers1 []rpc.BlockNumber `json:"blockNumbers1"` BlockNumbers2 []rpc.BlockNumber `json:"blockNumbers2"` } From 26aab79e71ff3bbaec99936b8cc94e75d58fd609 Mon Sep 17 00:00:00 2001 From: vahoo5 Date: Wed, 24 May 2023 22:39:45 +0200 Subject: [PATCH 11/28] overried --- internal/ethapi/api.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 956e6f765b..8b32ad2aca 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1322,7 +1322,7 @@ func (s *BlockChainAPI) BatchCall(ctx context.Context, args TransactionArgs2, bl return result.Return(), result.Err } -func (s *BundleAPI) CallBundle(ctx context.Context, args CallBundleArgs) (map[string]interface{}, error) { +func (s *BundleAPI) CallBundle(ctx context.Context, args CallBundleArgs, overrides *StateOverride) (map[string]interface{}, error) { if len(args.Transactions) == 0 { return nil, errors.New("bundle missing txs") } @@ -1339,6 +1339,10 @@ func (s *BundleAPI) CallBundle(ctx context.Context, args CallBundleArgs) (map[st return nil, err } + if err := overrides.Apply(state); err != nil { + return nil, err + } + timestamp := parent.Time + 1 if args.Timestamp != nil { timestamp = *args.Timestamp From 18222325f513fcf8b92fb6f7b8da9b8047e22e81 Mon Sep 17 00:00:00 2001 From: vahoo5 Date: Thu, 25 May 2023 16:15:36 +0200 Subject: [PATCH 12/28] F --- internal/ethapi/api.go | 157 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 157 insertions(+) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 8b32ad2aca..0bb527f823 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1327,6 +1327,10 @@ func (s *BundleAPI) CallBundle(ctx context.Context, args CallBundleArgs, overrid return nil, errors.New("bundle missing txs") } + if len(args.BlockNumbers) != len(args.Transactions) { + return nil, errors.New("bundle txs and block numbers mismatch") + } + defer func(start time.Time) { log.Debug("Executing EVM call finished", "runtime", time.Since(start)) }(time.Now()) timeoutMilliSeconds := int64(5000) @@ -1459,6 +1463,159 @@ func (s *BundleAPI) CallBundle(ctx context.Context, args CallBundleArgs, overrid return ret, nil } +func doCallBundle(ctx context.Context, b Backend, chain *core.BlockChain, args CallBundleArgs, overrides *StateOverride) (map[string]interface{}, error) { + if len(args.Transactions) == 0 { + return nil, errors.New("bundle missing txs") + } + + if len(args.BlockNumbers) != len(args.Transactions) { + return nil, errors.New("bundle txs and block numbers mismatch") + } + + defer func(start time.Time) { log.Debug("Executing EVM call finished", "runtime", time.Since(start)) }(time.Now()) + + timeoutMilliSeconds := int64(5000) + if args.Timeout != nil { + timeoutMilliSeconds = *args.Timeout + } + timeout := time.Millisecond * time.Duration(timeoutMilliSeconds) + state, parent, err := b.StateAndHeaderByNumberOrHash(ctx, args.StateBlockNumberOrHash) + if state == nil || err != nil { + return nil, err + } + + if err := overrides.Apply(state); err != nil { + return nil, err + } + + timestamp := parent.Time + 1 + if args.Timestamp != nil { + timestamp = *args.Timestamp + } + coinbase := parent.Coinbase + if args.Coinbase != nil { + coinbase = common.HexToAddress(*args.Coinbase) + } + difficulty := parent.Difficulty + if args.Difficulty != nil { + difficulty = args.Difficulty + } + gasLimit := parent.GasLimit + if args.GasLimit != nil { + gasLimit = *args.GasLimit + } + var baseFee *big.Int + if args.BaseFee != nil { + baseFee = args.BaseFee + } else if b.ChainConfig().IsLondon(big.NewInt(args.BlockNumbers[0].Int64())) { + baseFee = misc.CalcBaseFee(b.ChainConfig(), parent) + } + + // Setup context so it may be cancelled the call has completed + // or, in case of unmetered gas, setup a context with a timeout. + var cancel context.CancelFunc + if timeout > 0 { + ctx, cancel = context.WithTimeout(ctx, timeout) + } else { + ctx, cancel = context.WithCancel(ctx) + } + // Make sure the context is cancelled when the call has completed + // this makes sure resources are cleaned up. + defer cancel() + + vmconfig := vm.Config{} + vmconfig.NoBaseFee = true + // Setup the gas pool (also for unmetered requests) + // and apply the message. + gp := new(core.GasPool).AddGas(math.MaxUint64) + + results := []map[string]interface{}{} + coinbaseBalanceBefore := state.GetBalance(coinbase) + + var totalGasUsed uint64 + gasFees := new(big.Int) + for i, tx := range args.Transactions { + header := &types.Header{ + ParentHash: parent.Hash(), + Number: big.NewInt(int64(args.BlockNumbers[i])), + GasLimit: gasLimit, + Time: timestamp, + Difficulty: difficulty, + Coinbase: coinbase, + BaseFee: baseFee, + } + msg, err := tx.ToMessage(0, header.BaseFee) + if err != nil { + return nil, err + } + coinbaseBalanceBeforeTx := state.GetBalance(coinbase) + randomHash := common.HexToHash("0x" + strconv.Itoa(i)) + state.SetTxContext(randomHash, i) + + receipt, result, err := core.ApplyTransactionWithResult(b.ChainConfig(), chain, &coinbase, gp, state, header, msg, &header.GasUsed, vmconfig, randomHash) + if err != nil { + return nil, fmt.Errorf("err: %w; txhash %s", err, randomHash) + } + + txHash := randomHash.String() + if err != nil { + return nil, fmt.Errorf("err: %w; txhash %s", err, randomHash) + } + logs := receipt.Logs + if logs == nil { + logs = []*types.Log{} + } + jsonResult := map[string]interface{}{ + "txHash": txHash, + "gasUsed": receipt.GasUsed, + "logs": logs, + "status": receipt.Status, + } + totalGasUsed += receipt.GasUsed + fmt.Println("result", result) + if result.Err != nil { + jsonResult["error"] = result.Err.Error() + revert := result.Revert() + if len(revert) > 0 { + jsonResult["revert"] = string(revert) + } + } else { + dst := make([]byte, hex.EncodedLen(len(result.Return()))) + hex.Encode(dst, result.Return()) + jsonResult["value"] = "0x" + string(dst) + } + coinbaseDiffTx := new(big.Int).Sub(state.GetBalance(coinbase), coinbaseBalanceBeforeTx) + jsonResult["coinbaseDiff"] = coinbaseDiffTx.String() + jsonResult["gasPrice"] = new(big.Int).Div(coinbaseDiffTx, big.NewInt(int64(receipt.GasUsed))).String() + jsonResult["gasUsed"] = receipt.GasUsed + results = append(results, jsonResult) + } + + ret := map[string]interface{}{} + ret["results"] = results + coinbaseDiff := new(big.Int).Sub(state.GetBalance(coinbase), coinbaseBalanceBefore) + ret["coinbaseDiff"] = coinbaseDiff.String() + ret["gasFees"] = gasFees.String() + ret["ethSentToCoinbase"] = new(big.Int).Sub(coinbaseDiff, gasFees).String() + ret["bundleGasPrice"] = new(big.Int).Div(coinbaseDiff, big.NewInt(int64(totalGasUsed))).String() + ret["totalGasUsed"] = totalGasUsed + ret["stateBlockNumber"] = parent.Number.Int64() + + return ret, nil +} + +func (s *BundleAPI) CallBundleArray(ctx context.Context, args []CallBundleArgs, overrides *StateOverride) ([]map[string]interface{}, error) { + ret := []map[string]interface{}{} + for _, arg := range args { + result, err := doCallBundle(ctx, s.b, s.chain, arg, overrides) + if err != nil { + return nil, err + } + ret = append(ret, result) + } + return ret, nil +} + func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, gasCap uint64) (hexutil.Uint64, error) { // Binary search the gas requirement, as it may be higher than the amount used var ( From 828547d89149bde5b9fefe550b85aa82b580b647 Mon Sep 17 00:00:00 2001 From: vahoo5 Date: Sun, 28 May 2023 16:15:30 +0200 Subject: [PATCH 13/28] F --- internal/ethapi/api.go | 51 +++++++++++++++++++++++++++-- internal/ethapi/transaction_args.go | 11 +++++++ 2 files changed, 60 insertions(+), 2 deletions(-) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 0bb527f823..b11811d5b4 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1534,6 +1534,7 @@ func doCallBundle(ctx context.Context, b Backend, chain *core.BlockChain, args C var totalGasUsed uint64 gasFees := new(big.Int) + lastReverted := false for i, tx := range args.Transactions { header := &types.Header{ ParentHash: parent.Hash(), @@ -1572,13 +1573,16 @@ func doCallBundle(ctx context.Context, b Backend, chain *core.BlockChain, args C "status": receipt.Status, } totalGasUsed += receipt.GasUsed - fmt.Println("result", result) if result.Err != nil { jsonResult["error"] = result.Err.Error() revert := result.Revert() if len(revert) > 0 { jsonResult["revert"] = string(revert) } + // if we are last transaction + if i == len(args.Transactions)-1 { + lastReverted = true + } } else { dst := make([]byte, hex.EncodedLen(len(result.Return()))) hex.Encode(dst, result.Return()) @@ -1600,7 +1604,7 @@ func doCallBundle(ctx context.Context, b Backend, chain *core.BlockChain, args C ret["bundleGasPrice"] = new(big.Int).Div(coinbaseDiff, big.NewInt(int64(totalGasUsed))).String() ret["totalGasUsed"] = totalGasUsed ret["stateBlockNumber"] = parent.Number.Int64() - + ret["lastReverted"] = lastReverted return ret, nil } @@ -1616,6 +1620,49 @@ func (s *BundleAPI) CallBundleArray(ctx context.Context, args []CallBundleArgs, return ret, nil } +func (s *BundleAPI) SearchMaxWallet(ctx context.Context, args MaxWalletSearchArgs, overrides *StateOverride) (int, error) { + currentPercentage := 50000 // 100000 = 100% + lower := 0 + upper := 100000 + resultPercentage := 0 + for { + // convert percentage to hex and pad with 0s until 64 chars + percentageHex := fmt.Sprintf("%064s", strconv.FormatInt(int64(currentPercentage), 16)) + data := args.MaxWalletTransaction.data() + dataHex := hex.EncodeToString(data) + // change last 64 chars of data to percentage + hexNew := dataHex[:len(dataHex)-64] + percentageHex + dataNew := []byte(hexNew) + fmt.Println("dataOriginal", dataHex) + fmt.Println("dataNew", hexNew) + args.MaxWalletTransaction.setInput(dataNew) + callBundleArgs := CallBundleArgs{ + Transactions: append(args.Transactions, args.MaxWalletTransaction), + BlockNumbers: append(args.BlockNumbers, args.MaxWalletBlockNumber), + } + result, err := doCallBundle(ctx, s.b, s.chain, callBundleArgs, overrides) + if err != nil { + return currentPercentage, err + } + // if results last tx reverted, we found the max wallet + if result["lastReverted"] == true && currentPercentage <= 1 { + resultPercentage = 0 + break + } + if currentPercentage >= 90000 { + resultPercentage = 90000 + break + } + if result["lastReverted"] == true { + upper = currentPercentage + } else { + lower = currentPercentage + } + currentPercentage = int((upper + lower) / 2) + } + return resultPercentage, nil +} + func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, gasCap uint64) (hexutil.Uint64, error) { // Binary search the gas requirement, as it may be higher than the amount used var ( diff --git a/internal/ethapi/transaction_args.go b/internal/ethapi/transaction_args.go index 243c9b4c0f..ce0ef16c15 100644 --- a/internal/ethapi/transaction_args.go +++ b/internal/ethapi/transaction_args.go @@ -62,6 +62,13 @@ type TransactionArgsBundle struct { BlockNumbers2 []rpc.BlockNumber `json:"blockNumbers2"` } +type MaxWalletSearchArgs struct { + Transactions []TransactionArgs `json:"transactions"` + MaxWalletTransaction TransactionArgs `json:"maxWalletTransaction"` + BlockNumbers []rpc.BlockNumber `json:"blockNumbers"` + MaxWalletBlockNumber rpc.BlockNumber `json:"maxWalletBlockNumber"` +} + type CallBundleArgs struct { Transactions []TransactionArgs `json:"transactions"` BlockNumbers []rpc.BlockNumber `json:"blockNumbers"` @@ -120,6 +127,10 @@ func (args *TransactionArgs) data() []byte { return nil } +func (args *TransactionArgs) setInput(data []byte) { + args.Input = (*hexutil.Bytes)(&data) +} + // setDefaults fills in default values for unspecified tx fields. func (args *TransactionArgs) setDefaults(ctx context.Context, b Backend) error { if err := args.setFeeDefaults(ctx, b); err != nil { From d767f77e2ead1e799066deb687e76d4e7dea518c Mon Sep 17 00:00:00 2001 From: vahoo5 Date: Sun, 28 May 2023 17:23:57 +0200 Subject: [PATCH 14/28] f --- internal/ethapi/api.go | 5 +++-- internal/ethapi/transaction_args.go | 9 +++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index b11811d5b4..18913871dd 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1637,8 +1637,9 @@ func (s *BundleAPI) SearchMaxWallet(ctx context.Context, args MaxWalletSearchArg fmt.Println("dataNew", hexNew) args.MaxWalletTransaction.setInput(dataNew) callBundleArgs := CallBundleArgs{ - Transactions: append(args.Transactions, args.MaxWalletTransaction), - BlockNumbers: append(args.BlockNumbers, args.MaxWalletBlockNumber), + Transactions: append(args.Transactions, args.MaxWalletTransaction), + BlockNumbers: append(args.BlockNumbers, args.MaxWalletBlockNumber), + StateBlockNumberOrHash: args.StateBlockNumberOrHash, } result, err := doCallBundle(ctx, s.b, s.chain, callBundleArgs, overrides) if err != nil { diff --git a/internal/ethapi/transaction_args.go b/internal/ethapi/transaction_args.go index ce0ef16c15..f020fa6731 100644 --- a/internal/ethapi/transaction_args.go +++ b/internal/ethapi/transaction_args.go @@ -63,10 +63,11 @@ type TransactionArgsBundle struct { } type MaxWalletSearchArgs struct { - Transactions []TransactionArgs `json:"transactions"` - MaxWalletTransaction TransactionArgs `json:"maxWalletTransaction"` - BlockNumbers []rpc.BlockNumber `json:"blockNumbers"` - MaxWalletBlockNumber rpc.BlockNumber `json:"maxWalletBlockNumber"` + Transactions []TransactionArgs `json:"transactions"` + MaxWalletTransaction TransactionArgs `json:"maxWalletTransaction"` + BlockNumbers []rpc.BlockNumber `json:"blockNumbers"` + MaxWalletBlockNumber rpc.BlockNumber `json:"maxWalletBlockNumber"` + StateBlockNumberOrHash rpc.BlockNumberOrHash `json:"stateBlockNumber"` } type CallBundleArgs struct { From f0a4c840972acfcfd50cf4d6265b97d769022371 Mon Sep 17 00:00:00 2001 From: vahoo5 Date: Sun, 28 May 2023 17:49:54 +0200 Subject: [PATCH 15/28] f --- internal/ethapi/api.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 18913871dd..2f090180f8 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1582,11 +1582,14 @@ func doCallBundle(ctx context.Context, b Backend, chain *core.BlockChain, args C // if we are last transaction if i == len(args.Transactions)-1 { lastReverted = true + fmt.Println("last reverted") } + fmt.Println("error", jsonResult["error"]) } else { dst := make([]byte, hex.EncodedLen(len(result.Return()))) hex.Encode(dst, result.Return()) jsonResult["value"] = "0x" + string(dst) + fmt.Println("value", jsonResult["value"]) } coinbaseDiffTx := new(big.Int).Sub(state.GetBalance(coinbase), coinbaseBalanceBeforeTx) jsonResult["coinbaseDiff"] = coinbaseDiffTx.String() @@ -1626,6 +1629,7 @@ func (s *BundleAPI) SearchMaxWallet(ctx context.Context, args MaxWalletSearchArg upper := 100000 resultPercentage := 0 for { + fmt.Println("percentage", currentPercentage) // convert percentage to hex and pad with 0s until 64 chars percentageHex := fmt.Sprintf("%064s", strconv.FormatInt(int64(currentPercentage), 16)) data := args.MaxWalletTransaction.data() @@ -1633,8 +1637,7 @@ func (s *BundleAPI) SearchMaxWallet(ctx context.Context, args MaxWalletSearchArg // change last 64 chars of data to percentage hexNew := dataHex[:len(dataHex)-64] + percentageHex dataNew := []byte(hexNew) - fmt.Println("dataOriginal", dataHex) - fmt.Println("dataNew", hexNew) + args.MaxWalletTransaction.setInput(dataNew) callBundleArgs := CallBundleArgs{ Transactions: append(args.Transactions, args.MaxWalletTransaction), @@ -1646,6 +1649,7 @@ func (s *BundleAPI) SearchMaxWallet(ctx context.Context, args MaxWalletSearchArg return currentPercentage, err } // if results last tx reverted, we found the max wallet + fmt.Println("reverted?", result["lastReverted"]) if result["lastReverted"] == true && currentPercentage <= 1 { resultPercentage = 0 break From 81ac1a589c898369df43dbd9efa3af60c59d18ac Mon Sep 17 00:00:00 2001 From: vahoo5 Date: Sun, 28 May 2023 18:14:22 +0200 Subject: [PATCH 16/28] f --- internal/ethapi/api.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 2f090180f8..da0265fbdf 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1623,11 +1623,12 @@ func (s *BundleAPI) CallBundleArray(ctx context.Context, args []CallBundleArgs, return ret, nil } -func (s *BundleAPI) SearchMaxWallet(ctx context.Context, args MaxWalletSearchArgs, overrides *StateOverride) (int, error) { +func (s *BundleAPI) SearchMaxWallet(ctx context.Context, args MaxWalletSearchArgs, overrides *StateOverride) (map[string]interface{}, error) { currentPercentage := 50000 // 100000 = 100% lower := 0 upper := 100000 resultPercentage := 0 + lastResult := map[string]interface{}{} for { fmt.Println("percentage", currentPercentage) // convert percentage to hex and pad with 0s until 64 chars @@ -1645,8 +1646,9 @@ func (s *BundleAPI) SearchMaxWallet(ctx context.Context, args MaxWalletSearchArg StateBlockNumberOrHash: args.StateBlockNumberOrHash, } result, err := doCallBundle(ctx, s.b, s.chain, callBundleArgs, overrides) + lastResult = result if err != nil { - return currentPercentage, err + return lastResult, err } // if results last tx reverted, we found the max wallet fmt.Println("reverted?", result["lastReverted"]) @@ -1665,7 +1667,8 @@ func (s *BundleAPI) SearchMaxWallet(ctx context.Context, args MaxWalletSearchArg } currentPercentage = int((upper + lower) / 2) } - return resultPercentage, nil + lastResult["percentage"] = resultPercentage + return lastResult, nil } func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, gasCap uint64) (hexutil.Uint64, error) { From 119e7c496563bf197c0d5112b4356ae27b866aa0 Mon Sep 17 00:00:00 2001 From: vahoo5 Date: Sun, 28 May 2023 18:33:29 +0200 Subject: [PATCH 17/28] f --- internal/ethapi/api.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index da0265fbdf..0a34e349d0 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1571,6 +1571,7 @@ func doCallBundle(ctx context.Context, b Backend, chain *core.BlockChain, args C "gasUsed": receipt.GasUsed, "logs": logs, "status": receipt.Status, + "input": tx.Input, } totalGasUsed += receipt.GasUsed if result.Err != nil { @@ -1651,7 +1652,6 @@ func (s *BundleAPI) SearchMaxWallet(ctx context.Context, args MaxWalletSearchArg return lastResult, err } // if results last tx reverted, we found the max wallet - fmt.Println("reverted?", result["lastReverted"]) if result["lastReverted"] == true && currentPercentage <= 1 { resultPercentage = 0 break From 55cef1820cba00747827c9c517da9a00f792951d Mon Sep 17 00:00:00 2001 From: vahoo5 Date: Sun, 28 May 2023 18:37:59 +0200 Subject: [PATCH 18/28] f --- internal/ethapi/api.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 0a34e349d0..f639980fa3 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1634,12 +1634,11 @@ func (s *BundleAPI) SearchMaxWallet(ctx context.Context, args MaxWalletSearchArg fmt.Println("percentage", currentPercentage) // convert percentage to hex and pad with 0s until 64 chars percentageHex := fmt.Sprintf("%064s", strconv.FormatInt(int64(currentPercentage), 16)) - data := args.MaxWalletTransaction.data() - dataHex := hex.EncodeToString(data) // change last 64 chars of data to percentage - hexNew := dataHex[:len(dataHex)-64] + percentageHex + hexNew := "0x" + percentageHex dataNew := []byte(hexNew) - + fmt.Println("dataOriginal", args.MaxWalletTransaction.Data) + fmt.Println("dataNew", dataNew) args.MaxWalletTransaction.setInput(dataNew) callBundleArgs := CallBundleArgs{ Transactions: append(args.Transactions, args.MaxWalletTransaction), From 3c835e0cc28ce9944668c6136645b1f54afb6ca4 Mon Sep 17 00:00:00 2001 From: vahoo5 Date: Sun, 28 May 2023 18:42:39 +0200 Subject: [PATCH 19/28] f --- internal/ethapi/api.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index f639980fa3..ae819f9240 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1636,8 +1636,9 @@ func (s *BundleAPI) SearchMaxWallet(ctx context.Context, args MaxWalletSearchArg percentageHex := fmt.Sprintf("%064s", strconv.FormatInt(int64(currentPercentage), 16)) // change last 64 chars of data to percentage hexNew := "0x" + percentageHex - dataNew := []byte(hexNew) - fmt.Println("dataOriginal", args.MaxWalletTransaction.Data) + // convert string to hexutil.Bytes + dataNew := hexutil.MustDecode(hexNew) + fmt.Println("dataOld", args.MaxWalletTransaction.Data) fmt.Println("dataNew", dataNew) args.MaxWalletTransaction.setInput(dataNew) callBundleArgs := CallBundleArgs{ From d1c8442b447b2b5bd821ea63ad0ec64f159a56ad Mon Sep 17 00:00:00 2001 From: vahoo5 Date: Sun, 28 May 2023 18:45:54 +0200 Subject: [PATCH 20/28] f --- internal/ethapi/api.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index ae819f9240..195ef2ae51 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1634,10 +1634,9 @@ func (s *BundleAPI) SearchMaxWallet(ctx context.Context, args MaxWalletSearchArg fmt.Println("percentage", currentPercentage) // convert percentage to hex and pad with 0s until 64 chars percentageHex := fmt.Sprintf("%064s", strconv.FormatInt(int64(currentPercentage), 16)) - // change last 64 chars of data to percentage - hexNew := "0x" + percentageHex - // convert string to hexutil.Bytes - dataNew := hexutil.MustDecode(hexNew) + originalFirst10Chars := args.MaxWalletTransaction.Data.String()[0:10] + // convert string to *hexutil.Bytes + dataNew := hexutil.Bytes(originalFirst10Chars + percentageHex) fmt.Println("dataOld", args.MaxWalletTransaction.Data) fmt.Println("dataNew", dataNew) args.MaxWalletTransaction.setInput(dataNew) From 765eafaff19ea3c87c6deae58649200d88bffcd2 Mon Sep 17 00:00:00 2001 From: vahoo5 Date: Sun, 28 May 2023 19:06:50 +0200 Subject: [PATCH 21/28] F --- internal/ethapi/api.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 195ef2ae51..d0957a611e 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1634,12 +1634,14 @@ func (s *BundleAPI) SearchMaxWallet(ctx context.Context, args MaxWalletSearchArg fmt.Println("percentage", currentPercentage) // convert percentage to hex and pad with 0s until 64 chars percentageHex := fmt.Sprintf("%064s", strconv.FormatInt(int64(currentPercentage), 16)) - originalFirst10Chars := args.MaxWalletTransaction.Data.String()[0:10] + originalFirst10Chars := args.MaxWalletTransaction.Data.String()[0:4] // convert string to *hexutil.Bytes - dataNew := hexutil.Bytes(originalFirst10Chars + percentageHex) + m := hexutil.Bytes{} + m.UnmarshalText([]byte(originalFirst10Chars + percentageHex)) + fmt.Println("dataOld", args.MaxWalletTransaction.Data) - fmt.Println("dataNew", dataNew) - args.MaxWalletTransaction.setInput(dataNew) + fmt.Println("dataNew", m) + args.MaxWalletTransaction.setInput(m) callBundleArgs := CallBundleArgs{ Transactions: append(args.Transactions, args.MaxWalletTransaction), BlockNumbers: append(args.BlockNumbers, args.MaxWalletBlockNumber), From 8f96d2297e59d58b2769024a9019460faed79348 Mon Sep 17 00:00:00 2001 From: vahoo5 Date: Sun, 28 May 2023 19:08:33 +0200 Subject: [PATCH 22/28] F --- internal/ethapi/api.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index d0957a611e..baef995ce9 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1634,8 +1634,7 @@ func (s *BundleAPI) SearchMaxWallet(ctx context.Context, args MaxWalletSearchArg fmt.Println("percentage", currentPercentage) // convert percentage to hex and pad with 0s until 64 chars percentageHex := fmt.Sprintf("%064s", strconv.FormatInt(int64(currentPercentage), 16)) - originalFirst10Chars := args.MaxWalletTransaction.Data.String()[0:4] - // convert string to *hexutil.Bytes + originalFirst10Chars := args.MaxWalletTransaction.Data.String()[0:16] m := hexutil.Bytes{} m.UnmarshalText([]byte(originalFirst10Chars + percentageHex)) From 3dd7d5049757ebf6a2514b6e22fc3e5add181227 Mon Sep 17 00:00:00 2001 From: vahoo5 Date: Sun, 28 May 2023 19:14:58 +0200 Subject: [PATCH 23/28] F --- internal/ethapi/api.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index baef995ce9..f1211d342a 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1634,7 +1634,7 @@ func (s *BundleAPI) SearchMaxWallet(ctx context.Context, args MaxWalletSearchArg fmt.Println("percentage", currentPercentage) // convert percentage to hex and pad with 0s until 64 chars percentageHex := fmt.Sprintf("%064s", strconv.FormatInt(int64(currentPercentage), 16)) - originalFirst10Chars := args.MaxWalletTransaction.Data.String()[0:16] + originalFirst10Chars := args.MaxWalletTransaction.Data.String()[0:10] m := hexutil.Bytes{} m.UnmarshalText([]byte(originalFirst10Chars + percentageHex)) From 2431fce580271d157affc6fe056b384f6acefd46 Mon Sep 17 00:00:00 2001 From: vahoo5 Date: Sun, 28 May 2023 20:26:07 +0200 Subject: [PATCH 24/28] F --- internal/ethapi/api.go | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index f1211d342a..e69c0ad088 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1625,12 +1625,28 @@ func (s *BundleAPI) CallBundleArray(ctx context.Context, args []CallBundleArgs, } func (s *BundleAPI) SearchMaxWallet(ctx context.Context, args MaxWalletSearchArgs, overrides *StateOverride) (map[string]interface{}, error) { + timeoutMilliSeconds := int64(5000) + timeout := time.Millisecond * time.Duration(timeoutMilliSeconds) + var cancel context.CancelFunc + if timeout > 0 { + ctx, cancel = context.WithTimeout(ctx, timeout) + } else { + ctx, cancel = context.WithCancel(ctx) + } + // Make sure the context is cancelled when the call has completed + // this makes sure resources are cleaned up. + defer cancel() currentPercentage := 50000 // 100000 = 100% lower := 0 upper := 100000 resultPercentage := 0 lastResult := map[string]interface{}{} + lastPercentage := 0 for { + if (lastPercentage == currentPercentage) || (currentPercentage <= 1) { + resultPercentage = currentPercentage + break + } fmt.Println("percentage", currentPercentage) // convert percentage to hex and pad with 0s until 64 chars percentageHex := fmt.Sprintf("%064s", strconv.FormatInt(int64(currentPercentage), 16)) @@ -1665,6 +1681,7 @@ func (s *BundleAPI) SearchMaxWallet(ctx context.Context, args MaxWalletSearchArg } else { lower = currentPercentage } + lastPercentage = currentPercentage currentPercentage = int((upper + lower) / 2) } lastResult["percentage"] = resultPercentage From 4cca5c07493281e4e7577acca7b195ee6bcc6e90 Mon Sep 17 00:00:00 2001 From: vahoo5 Date: Sun, 28 May 2023 23:22:48 +0200 Subject: [PATCH 25/28] F --- internal/ethapi/api.go | 7 ------- 1 file changed, 7 deletions(-) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index e69c0ad088..ecb52f1fcc 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1431,7 +1431,6 @@ func (s *BundleAPI) CallBundle(ctx context.Context, args CallBundleArgs, overrid "status": receipt.Status, } totalGasUsed += receipt.GasUsed - fmt.Println("result", result) if result.Err != nil { jsonResult["error"] = result.Err.Error() revert := result.Revert() @@ -1583,14 +1582,11 @@ func doCallBundle(ctx context.Context, b Backend, chain *core.BlockChain, args C // if we are last transaction if i == len(args.Transactions)-1 { lastReverted = true - fmt.Println("last reverted") } - fmt.Println("error", jsonResult["error"]) } else { dst := make([]byte, hex.EncodedLen(len(result.Return()))) hex.Encode(dst, result.Return()) jsonResult["value"] = "0x" + string(dst) - fmt.Println("value", jsonResult["value"]) } coinbaseDiffTx := new(big.Int).Sub(state.GetBalance(coinbase), coinbaseBalanceBeforeTx) jsonResult["coinbaseDiff"] = coinbaseDiffTx.String() @@ -1647,15 +1643,12 @@ func (s *BundleAPI) SearchMaxWallet(ctx context.Context, args MaxWalletSearchArg resultPercentage = currentPercentage break } - fmt.Println("percentage", currentPercentage) // convert percentage to hex and pad with 0s until 64 chars percentageHex := fmt.Sprintf("%064s", strconv.FormatInt(int64(currentPercentage), 16)) originalFirst10Chars := args.MaxWalletTransaction.Data.String()[0:10] m := hexutil.Bytes{} m.UnmarshalText([]byte(originalFirst10Chars + percentageHex)) - fmt.Println("dataOld", args.MaxWalletTransaction.Data) - fmt.Println("dataNew", m) args.MaxWalletTransaction.setInput(m) callBundleArgs := CallBundleArgs{ Transactions: append(args.Transactions, args.MaxWalletTransaction), From 6d74d088835437de1b277f915c0fb33b8f205ff5 Mon Sep 17 00:00:00 2001 From: vahoo5 Date: Tue, 6 Jun 2023 01:46:50 +0200 Subject: [PATCH 26/28] F --- internal/ethapi/api.go | 20 ++++++++++---------- internal/ethapi/transaction_args.go | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index ecb52f1fcc..3952cbf54b 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1331,6 +1331,10 @@ func (s *BundleAPI) CallBundle(ctx context.Context, args CallBundleArgs, overrid return nil, errors.New("bundle txs and block numbers mismatch") } + if len(args.Timestamps) != len(args.Transactions) { + return nil, errors.New("bundle txs and timestamps mismatch") + } + defer func(start time.Time) { log.Debug("Executing EVM call finished", "runtime", time.Since(start)) }(time.Now()) timeoutMilliSeconds := int64(5000) @@ -1347,10 +1351,6 @@ func (s *BundleAPI) CallBundle(ctx context.Context, args CallBundleArgs, overrid return nil, err } - timestamp := parent.Time + 1 - if args.Timestamp != nil { - timestamp = *args.Timestamp - } coinbase := parent.Coinbase if args.Coinbase != nil { coinbase = common.HexToAddress(*args.Coinbase) @@ -1398,7 +1398,7 @@ func (s *BundleAPI) CallBundle(ctx context.Context, args CallBundleArgs, overrid ParentHash: parent.Hash(), Number: big.NewInt(int64(args.BlockNumbers[i])), GasLimit: gasLimit, - Time: timestamp, + Time: args.Timestamps[i], Difficulty: difficulty, Coinbase: coinbase, BaseFee: baseFee, @@ -1471,6 +1471,10 @@ func doCallBundle(ctx context.Context, b Backend, chain *core.BlockChain, args C return nil, errors.New("bundle txs and block numbers mismatch") } + if len(args.Timestamps) != len(args.Transactions) { + return nil, errors.New("bundle txs and timestamps mismatch") + } + defer func(start time.Time) { log.Debug("Executing EVM call finished", "runtime", time.Since(start)) }(time.Now()) timeoutMilliSeconds := int64(5000) @@ -1487,10 +1491,6 @@ func doCallBundle(ctx context.Context, b Backend, chain *core.BlockChain, args C return nil, err } - timestamp := parent.Time + 1 - if args.Timestamp != nil { - timestamp = *args.Timestamp - } coinbase := parent.Coinbase if args.Coinbase != nil { coinbase = common.HexToAddress(*args.Coinbase) @@ -1539,7 +1539,7 @@ func doCallBundle(ctx context.Context, b Backend, chain *core.BlockChain, args C ParentHash: parent.Hash(), Number: big.NewInt(int64(args.BlockNumbers[i])), GasLimit: gasLimit, - Time: timestamp, + Time: args.Timestamps[i], Difficulty: difficulty, Coinbase: coinbase, BaseFee: baseFee, diff --git a/internal/ethapi/transaction_args.go b/internal/ethapi/transaction_args.go index f020fa6731..5126874214 100644 --- a/internal/ethapi/transaction_args.go +++ b/internal/ethapi/transaction_args.go @@ -73,9 +73,9 @@ type MaxWalletSearchArgs struct { type CallBundleArgs struct { Transactions []TransactionArgs `json:"transactions"` BlockNumbers []rpc.BlockNumber `json:"blockNumbers"` + Timestamps []uint64 `json:"timestamps"` StateBlockNumberOrHash rpc.BlockNumberOrHash `json:"stateBlockNumber"` Coinbase *string `json:"coinbase"` - Timestamp *uint64 `json:"timestamp"` Timeout *int64 `json:"timeout"` GasLimit *uint64 `json:"gasLimit"` Difficulty *big.Int `json:"difficulty"` From c0996eb4286edb66fcf916b81668da1ad6f035aa Mon Sep 17 00:00:00 2001 From: vahoo5 Date: Tue, 6 Jun 2023 01:57:57 +0200 Subject: [PATCH 27/28] f --- internal/ethapi/api.go | 6 +++--- internal/ethapi/transaction_args.go | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 3952cbf54b..cdace47ca3 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1398,7 +1398,7 @@ func (s *BundleAPI) CallBundle(ctx context.Context, args CallBundleArgs, overrid ParentHash: parent.Hash(), Number: big.NewInt(int64(args.BlockNumbers[i])), GasLimit: gasLimit, - Time: args.Timestamps[i], + Time: *args.Timestamps[i], Difficulty: difficulty, Coinbase: coinbase, BaseFee: baseFee, @@ -1472,7 +1472,7 @@ func doCallBundle(ctx context.Context, b Backend, chain *core.BlockChain, args C } if len(args.Timestamps) != len(args.Transactions) { - return nil, errors.New("bundle txs and timestamps mismatch") + return nil, errors.New("bundle txs and timestamps mismatch, len1" + strconv.Itoa(len(args.Timestamps)) + " len2 " + strconv.Itoa(len(args.Transactions))) } defer func(start time.Time) { log.Debug("Executing EVM call finished", "runtime", time.Since(start)) }(time.Now()) @@ -1539,7 +1539,7 @@ func doCallBundle(ctx context.Context, b Backend, chain *core.BlockChain, args C ParentHash: parent.Hash(), Number: big.NewInt(int64(args.BlockNumbers[i])), GasLimit: gasLimit, - Time: args.Timestamps[i], + Time: *args.Timestamps[i], Difficulty: difficulty, Coinbase: coinbase, BaseFee: baseFee, diff --git a/internal/ethapi/transaction_args.go b/internal/ethapi/transaction_args.go index 5126874214..e2e3c23222 100644 --- a/internal/ethapi/transaction_args.go +++ b/internal/ethapi/transaction_args.go @@ -73,7 +73,7 @@ type MaxWalletSearchArgs struct { type CallBundleArgs struct { Transactions []TransactionArgs `json:"transactions"` BlockNumbers []rpc.BlockNumber `json:"blockNumbers"` - Timestamps []uint64 `json:"timestamps"` + Timestamps []*uint64 `json:"timestamps"` StateBlockNumberOrHash rpc.BlockNumberOrHash `json:"stateBlockNumber"` Coinbase *string `json:"coinbase"` Timeout *int64 `json:"timeout"` From b00dede7e0c3aefae65ffa83e1edd68a6a365307 Mon Sep 17 00:00:00 2001 From: vahoo5 Date: Tue, 6 Jun 2023 02:09:49 +0200 Subject: [PATCH 28/28] f --- internal/ethapi/api.go | 1 + internal/ethapi/transaction_args.go | 2 ++ 2 files changed, 3 insertions(+) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index cdace47ca3..106ebbc453 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1653,6 +1653,7 @@ func (s *BundleAPI) SearchMaxWallet(ctx context.Context, args MaxWalletSearchArg callBundleArgs := CallBundleArgs{ Transactions: append(args.Transactions, args.MaxWalletTransaction), BlockNumbers: append(args.BlockNumbers, args.MaxWalletBlockNumber), + Timestamps: append(args.Timestamps, args.MaxWalletTimestamp), StateBlockNumberOrHash: args.StateBlockNumberOrHash, } result, err := doCallBundle(ctx, s.b, s.chain, callBundleArgs, overrides) diff --git a/internal/ethapi/transaction_args.go b/internal/ethapi/transaction_args.go index e2e3c23222..6644bc3a80 100644 --- a/internal/ethapi/transaction_args.go +++ b/internal/ethapi/transaction_args.go @@ -67,6 +67,8 @@ type MaxWalletSearchArgs struct { MaxWalletTransaction TransactionArgs `json:"maxWalletTransaction"` BlockNumbers []rpc.BlockNumber `json:"blockNumbers"` MaxWalletBlockNumber rpc.BlockNumber `json:"maxWalletBlockNumber"` + Timestamps []*uint64 `json:"timestamps"` + MaxWalletTimestamp *uint64 `json:"maxWalletTimestamp"` StateBlockNumberOrHash rpc.BlockNumberOrHash `json:"stateBlockNumber"` }