Releases: openmev/go-ethereum
Releases · openmev/go-ethereum
v1.10.9 eth_callBundle
Container
https://hub.docker.com/r/openmev/mev-geth
Build hash
$ git hash-object -t tree /dev/null
4b825dc642cb6eb9a060e54bf8d69288fbee4904
Changelog
- flashbots: count eth payments for txs whose nonce is in the mempool
#76
- Use object in eth_sendBundle params and add revertingTxHashes param
#40
#30
- Change pricing formula to ignore gas from txs in the txpool
#39
- Discard bundles with reverting txs
#30
- Add infra/CI and update README
f401f0c
- Update README.md
d141f05
- Add bundle merging with multiple workers
84ccf85
Additional changes
diff --git a/core/state_processor.go b/core/state_processor.go
index d4c77ae41042..c06aeab480d5 100644
--- a/core/state_processor.go
+++ b/core/state_processor.go
@@ -137,6 +137,51 @@ func applyTransaction(msg types.Message, config *params.ChainConfig, bc ChainCon
return receipt, err
}
+func applyTransactionWithResult(msg types.Message, config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, 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)
+
+ // Apply the transaction to the current state (included in the env).
+ result, err := ApplyMessage(evm, msg, gp)
+ if err != nil {
+ return nil, nil, err
+ }
+
+ // Update the state with pending changes.
+ var root []byte
+ if config.IsByzantium(header.Number) {
+ statedb.Finalise(true)
+ } 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: tx.Type(), PostState: root, CumulativeGasUsed: *usedGas}
+ if result.Failed() {
+ receipt.Status = types.ReceiptStatusFailed
+ } else {
+ receipt.Status = types.ReceiptStatusSuccessful
+ }
+ receipt.TxHash = tx.Hash()
+ receipt.GasUsed = result.UsedGas
+
+ // If the transaction created a contract, store the creation address in the receipt.
+ if msg.To() == nil {
+ receipt.ContractAddress = crypto.CreateAddress(evm.TxContext.Origin, tx.Nonce())
+ }
+
+ // Set the receipt logs and create the bloom filter.
+ receipt.Logs = statedb.GetLogs(tx.Hash())
+ receipt.Bloom = types.CreateBloom(types.Receipts{receipt})
+ receipt.BlockHash = statedb.BlockHash()
+ receipt.BlockNumber = header.Number
+ receipt.TransactionIndex = uint(statedb.TxIndex())
+ return receipt, result, err
+}
+
// ApplyTransaction attempts to apply a transaction to the given state database
// and uses the input parameters for its environment. It returns the receipt
// for the transaction, gas used and an error if the transaction failed,
@@ -151,3 +196,14 @@ func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *commo
vmenv := vm.NewEVM(blockContext, vm.TxContext{}, statedb, config, cfg)
return applyTransaction(msg, config, bc, author, gp, statedb, header.Number, header.Hash(), tx, usedGas, vmenv)
}
+
+func ApplyTransactionWithResult(config *params.ChainConfig, bc ChainContext, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *uint64, cfg vm.Config) (*types.Receipt, *ExecutionResult, error) {
+ msg, err := tx.AsMessage(types.MakeSigner(config, header.Number))
+ if err != nil {
+ return nil, nil, err
+ }
+ // 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)
+ return applyTransactionWithResult(msg, config, bc, author, gp, statedb, header, tx, usedGas, vmenv)
+}
diff --git a/core/types/transaction.go b/core/types/transaction.go
index 758e5e8730ad..f33469f56128 100644
--- a/core/types/transaction.go
+++ b/core/types/transaction.go
@@ -640,3 +640,11 @@ type MevBundle struct {
MaxTimestamp uint64
RevertingTxHashes []common.Hash
}
+
+type MevBundle struct {
+ Txs Transactions
+ BlockNumber *big.Int
+ MinTimestamp uint64
+ MaxTimestamp uint64
+ RevertingTxHashes []common.Hash
+}
diff --git a/eth/backend.go b/eth/backend.go
index 793d3b81f1b1..102ebe682d66 100644
--- a/eth/backend.go
+++ b/eth/backend.go
@@ -292,7 +292,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 6f5e5e00e7bb..08c6894f760d 100644
--- a/internal/ethapi/api.go
+++ b/internal/ethapi/api.go
@@ -18,6 +18,7 @@ package ethapi
import (
"context"
+ "encoding/hex"
"errors"
"fmt"
"math/big"
@@ -46,6 +47,7 @@ import (
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc"
"github.com/tyler-smith/go-bip39"
+ "golang.org/x/crypto/sha3"
)
// PublicEthereumAPI provides an API to access Ethereum related information.
@@ -2115,6 +2117,15 @@ type UnsignedMegabundle struct {
RevertingTxHashes []common.Hash
}
+// SendBundleArgs represents the arguments for a call.
+type SendBundleArgs struct {
+ Txs []hexutil.Bytes `json:"txs"`
+ BlockNumber rpc.BlockNumber `json:"blockNumber"`
+ MinTimestamp *uint64 `json:"minTimestamp"`
+ MaxTimestamp *uint64 `json:"maxTimestamp"`
+ RevertingTxHashes []common.Hash `json:"revertingTxHashes"`
+}
+
// SendBundle will add the signed transaction to the transaction pool.
// The sender is responsible for signing the transaction and using the correct nonce and ensuring validity
func (s *PrivateTxBundleAPI) SendBundle(ctx context.Context, args SendBundleArgs) error {
@@ -2145,6 +2156,282 @@ func (s *PrivateTxBundleAPI) SendBundle(ctx context.Context, args SendBundleArgs
return s.b.SendBundle(ctx, txs, args.BlockNumber, minTimestamp, maxTimestamp, args.RevertingTxHashes)
}
+// BundleAPI offers an API for accepting bundled transactions
+type BundleAPI struct {
+ b Backend
+}
+
+// NewBundleAPI creates a new Tx Bundle API instance.
+func NewBundleAPI(b Backend) *BundleAPI {
+ return &BundleAPI{b}
+}
+
+// CallBundle will simulate a bundle of transactions at the top of a given block
+// number with the state of another (or the same) block. This can be used to
+// simulate future blocks with the current state, or it can be used to simulate
+// a past block.
+// The sender is responsible for signing the transactions and using the correct
+// nonce and ensuring validity
+func (s *BundleAPI) CallBundle(ctx context.Context, encodedTxs []hexutil.Bytes, blockNr rpc.BlockNumber, stateBlockNumberOrHash rpc.BlockNumberOrHash, blockTimestamp *uint64, timeoutMilliSecondsPtr *int64) (map[string]interface{}, error) {
+ if len(encodedTxs) == 0 {
+ return nil, nil
+ }
+ var txs types.Transactions
+
+ for _, encodedTx := range encodedTxs {
+ tx := new(types.Transaction)
+ if err := rlp.DecodeBytes(encodedTx, tx); err != nil {
+ return nil, err
+ }
+ txs = append(txs, tx)
+ }
+ defer func(start time.Time) { log.Debug("Executing EVM call finished", "runtime", time.Since(start)) }(time.Now())
+
+ timeoutMilliSeconds := int64(5000)
+ if timeoutMilliSecondsPtr != nil {
+ timeoutMilliSeconds = *timeoutMilliSecondsPtr
+ }
+ timeout := time.Millisecond * time.Duration(timeoutMilliSeconds)
+ state, parent, err := s.b.StateAndHeaderByNumberOrHash(ctx, stateBlockNumberOrHash)
+ if state == nil || err != nil {
+ return nil, err
+ }
+ blockNumber := big.NewInt(int64(blockNr))
+
+ timestamp := parent.Time
+ if blockTimestamp != nil {
+ timestamp = *blockTimestamp
+ }
+ coinbase := parent.Coinbase
+ header := &types.Header{
+ ParentHash: parent.Hash(),
+ Number: blockNumber,
+ GasLimit: parent.GasLimit,
+ Time: timestamp,
+ Difficulty: parent.Difficulty,
+ Coinbase: coinbase,
+ }
+
+ // 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
+ signer := types.MakeSigner(s.b.ChainConfig(), blockNumber)
+ firstMsg, err := txs[0].AsMessage(signer)
+ if err != nil {
+ return nil, err
+ }
+ evm, vmError, err := s.b.GetEVM(ctx, firstMsg, state, header)
+ if err != nil {
+ return nil, err
+ }
+ // Wait for the ...