Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 15 additions & 15 deletions core/gen_genesis.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

62 changes: 62 additions & 0 deletions core/state_processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,68 @@ func ApplyTransaction(config *params.ChainConfig, bc ChainContext, author *commo
return applyTransaction(msg, config, 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 := TransactionToMessage(tx, types.MakeSigner(config, header.Number, header.Time), header.BaseFee)
if err != nil {
return nil, nil, err
}
// Create a new context to be used in the EVM environment
blockContext := NewEVMBlockContext(header, bc, author, config, statedb)
txContext := NewEVMTxContext(msg)
vmenv := vm.NewEVM(blockContext, txContext, statedb, config, cfg)
return applyTransactionWithResult(msg, config, gp, statedb, header.Number, header.Hash(), tx, usedGas, vmenv)
}

func applyTransactionWithResult(msg *Message, config *params.ChainConfig, gp *GasPool, statedb *state.StateDB, blockNumber *big.Int, blockHash common.Hash, 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(blockNumber) {
statedb.Finalise(true)
} else {
root = statedb.IntermediateRoot(config.IsEIP158(blockNumber)).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 tx.Type() == types.BlobTxType {
receipt.BlobGasUsed = uint64(len(tx.BlobHashes()) * params.BlobTxBlobGasPerBlob)
receipt.BlobGasPrice = evm.Context.BlobBaseFee
}

// 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(), blockNumber.Uint64(), blockHash)
receipt.Bloom = types.CreateBloom(types.Receipts{receipt})
receipt.BlockHash = blockHash
receipt.BlockNumber = blockNumber
receipt.TransactionIndex = uint(statedb.TxIndex())
return receipt, result, err
}

// ProcessBeaconBlockRoot applies the EIP-4788 system call to the beacon block root
// contract. This method is exported to be used in tests.
func ProcessBeaconBlockRoot(beaconRoot common.Hash, vmenv *vm.EVM, statedb *state.StateDB) {
Expand Down
3 changes: 3 additions & 0 deletions core/txpool/txpool.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ type TxPool struct {
term chan struct{} // Termination channel to detect a closed pool

sync chan chan error // Testing / simulator channel to block until internal reset is done

mevBundles []types.MevBundle
mu sync.RWMutex
}

// New creates a new transaction pool to gather, sort and filter inbound
Expand Down
19 changes: 19 additions & 0 deletions core/types/transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rlp"
"github.com/holiman/uint256"
)

var (
Expand Down Expand Up @@ -672,3 +673,21 @@ func copyAddressPtr(a *common.Address) *common.Address {
cpy := *a
return &cpy
}

type MevBundle struct {
Txs Transactions
BlockNumber *big.Int
MinTimestamp uint64
MaxTimestamp uint64
Hash common.Hash
}

type SimulatedBundle struct {
MevGasPrice *uint256.Int
TotalProfit *uint256.Int
TotalGasUsed uint64
Logs []*Log
Revert []byte
ExecError string
OriginalBundle MevBundle
}
31 changes: 31 additions & 0 deletions eth/api_backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import (
"github.com/ethereum/go-ethereum/miner"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
"golang.org/x/crypto/sha3"
)

// EthAPIBackend implements ethapi.Backend and tracers.Backend for full nodes
Expand Down Expand Up @@ -319,6 +320,36 @@ func (b *EthAPIBackend) SendTx(ctx context.Context, signedTx *types.Transaction)
return b.eth.txPool.Add([]*types.Transaction{signedTx}, true, false)[0]
}

func (b *EthAPIBackend) SendInteropBundle(ctx context.Context, txs types.Transactions, blockNumber rpc.BlockNumber, minTimestamp uint64, maxTimestamp uint64) (*types.SimulatedBundle, error) {
for _, tx := range txs {
if b.ChainConfig().IsOptimism() && tx.Type() == types.BlobTxType {
return nil, types.ErrTxTypeNotSupported
}
}

bundleHasher := sha3.NewLegacyKeccak256()
for _, tx := range txs {
_, err := bundleHasher.Write(tx.Hash().Bytes())
if err != nil {
return nil, err
}
}
bundleHash := common.BytesToHash(bundleHasher.Sum(nil))
if blockNumber == rpc.PendingBlockNumber {
bundle := types.MevBundle{
Txs: txs,
BlockNumber: big.NewInt(int64(b.eth.blockchain.CurrentBlock().Number.Uint64() + 2)),
MinTimestamp: minTimestamp,
MaxTimestamp: maxTimestamp,
Hash: bundleHash,
}

return b.eth.miner.SimulateBundle(bundle)
}

return nil, errors.New("only pending block is supported")
}

func (b *EthAPIBackend) GetPoolTransactions() (types.Transactions, error) {
pending := b.eth.txPool.Pending(txpool.PendingFilter{})
var txs types.Transactions
Expand Down
8 changes: 4 additions & 4 deletions eth/gasprice/optimism-gasprice_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,22 +112,22 @@ func TestSuggestOptimismPriorityFee(t *testing.T) {
}{
{
// block well under capacity, expect min priority fee suggestion
txdata: []testTxData{testTxData{params.GWei, 21000}},
txdata: []testTxData{{params.GWei, 21000}},
want: minSuggestion,
},
{
// 2 txs, still under capacity, expect min priority fee suggestion
txdata: []testTxData{testTxData{params.GWei, 21000}, testTxData{params.GWei, 21000}},
txdata: []testTxData{{params.GWei, 21000}, {params.GWei, 21000}},
want: minSuggestion,
},
{
// 2 txs w same priority fee (1 gwei), but second tx puts it right over capacity
txdata: []testTxData{testTxData{params.GWei, 21000}, testTxData{params.GWei, 21001}},
txdata: []testTxData{{params.GWei, 21000}, {params.GWei, 21001}},
want: big.NewInt(1100000000), // 10 percent over 1 gwei, the median
},
{
// 3 txs, full block. return 10% over the median tx (10 gwei * 10% == 11 gwei)
txdata: []testTxData{testTxData{10 * params.GWei, 21000}, testTxData{1 * params.GWei, 21000}, testTxData{100 * params.GWei, 21000}},
txdata: []testTxData{{10 * params.GWei, 21000}, {1 * params.GWei, 21000}, {100 * params.GWei, 21000}},
want: big.NewInt(11 * params.GWei),
},
}
Expand Down
2 changes: 1 addition & 1 deletion eth/protocols/snap/progress_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ func makeLegacyProgress() legacyProgress {
Next: common.Hash{},
Last: common.Hash{0x77},
SubTasks: map[common.Hash][]*legacyStorageTask{
common.Hash{0x1}: {
{0x1}: {
{
Next: common.Hash{},
Last: common.Hash{0xff},
Expand Down
55 changes: 55 additions & 0 deletions internal/ethapi/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -2204,6 +2204,61 @@ func (s *TransactionAPI) Resend(ctx context.Context, sendArgs TransactionArgs, g
return common.Hash{}, fmt.Errorf("transaction %#x not found", matchTx.Hash())
}

// SendInteropBundleArgs represents the arguments for a SendInteropBundle call.
type SendInteropBundleArgs struct {
Txs []hexutil.Bytes `json:"txs"`
BlockNumber rpc.BlockNumber `json:"blockNumber"`
MinTimestamp *uint64 `json:"minTimestamp"`
MaxTimestamp *uint64 `json:"maxTimestamp"`
}

type SendInteropBundleResponse struct {
BlockNumber uint64 `json:"blockNumber"`
Timestamp uint64 `json:"timestamp"`
Logs []*types.Log `json:"logs"`
BundleHash common.Hash `json:"bundleHash"`
}

// SendInteropBundle 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 *TransactionAPI) SendInteropBundle(ctx context.Context, args SendInteropBundleArgs) (*SendInteropBundleResponse, error) {
var txs types.Transactions
if len(args.Txs) == 0 {
return nil, errors.New("bundle missing txs")
}
if args.BlockNumber == 0 {
args.BlockNumber = rpc.PendingBlockNumber
}

for _, encodedTx := range args.Txs {
tx := new(types.Transaction)
if err := tx.UnmarshalBinary(encodedTx); err != nil {
return nil, err
}
txs = append(txs, tx)
}

var minTimestamp, maxTimestamp uint64
if args.MinTimestamp != nil {
minTimestamp = *args.MinTimestamp
}
if args.MaxTimestamp != nil {
maxTimestamp = *args.MaxTimestamp
}

bundle, err := s.b.SendInteropBundle(ctx, txs, args.BlockNumber, minTimestamp, maxTimestamp)
if err != nil {
return nil, err
}

return &SendInteropBundleResponse{
BlockNumber: s.b.CurrentHeader().Number.Uint64() + 1,
Timestamp: s.b.CurrentHeader().Time + 2, // assume l2 slot time is 2 seconds
BundleHash: bundle.OriginalBundle.Hash,
Logs: bundle.Logs,
}, nil
}

// DebugAPI is the collection of Ethereum APIs exposed over the debugging
// namespace.
type DebugAPI struct {
Expand Down
9 changes: 6 additions & 3 deletions internal/ethapi/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -744,6 +744,9 @@ func (b testBackend) SubscribeChainSideEvent(ch chan<- core.ChainSideEvent) even
func (b testBackend) SendTx(ctx context.Context, signedTx *types.Transaction) error {
panic("implement me")
}
func (b testBackend) SendInteropBundle(ctx context.Context, txs types.Transactions, blockNumber rpc.BlockNumber, minTimestamp uint64, maxTimestamp uint64) (*types.SimulatedBundle, error) {
panic("implement me")
}
func (b testBackend) GetTransaction(ctx context.Context, txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64, error) {
tx, blockHash, blockNumber, index := rawdb.ReadTransaction(b.db, txHash)
return true, tx, blockHash, blockNumber, index, nil
Expand Down Expand Up @@ -917,7 +920,7 @@ func TestEstimateGas(t *testing.T) {
From: &accounts[0].addr,
To: &accounts[1].addr,
Value: (*hexutil.Big)(big.NewInt(1)),
BlobHashes: []common.Hash{common.Hash{0x01, 0x22}},
BlobHashes: []common.Hash{{0x01, 0x22}},
BlobFeeCap: (*hexutil.Big)(big.NewInt(1)),
},
want: 21000,
Expand Down Expand Up @@ -1105,7 +1108,7 @@ func TestCall(t *testing.T) {
call: TransactionArgs{
From: &accounts[1].addr,
To: &randomAccounts[2].addr,
BlobHashes: []common.Hash{common.Hash{0x01, 0x22}},
BlobHashes: []common.Hash{{0x01, 0x22}},
BlobFeeCap: (*hexutil.Big)(big.NewInt(1)),
},
overrides: StateOverride{
Expand Down Expand Up @@ -1232,7 +1235,7 @@ func TestSendBlobTransaction(t *testing.T) {
From: &b.acc.Address,
To: &to,
Value: (*hexutil.Big)(big.NewInt(1)),
BlobHashes: []common.Hash{common.Hash{0x01, 0x22}},
BlobHashes: []common.Hash{{0x01, 0x22}},
})
if err != nil {
t.Fatalf("failed to fill tx defaults: %v\n", err)
Expand Down
1 change: 1 addition & 0 deletions internal/ethapi/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ type Backend interface {

// Transaction pool API
SendTx(ctx context.Context, signedTx *types.Transaction) error
SendInteropBundle(ctx context.Context, txs types.Transactions, blockNumber rpc.BlockNumber, minTimestamp uint64, maxTimestamp uint64) (*types.SimulatedBundle, error)
GetTransaction(ctx context.Context, txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64, error)
GetPoolTransactions() (types.Transactions, error)
GetPoolTransaction(txHash common.Hash) *types.Transaction
Expand Down
3 changes: 3 additions & 0 deletions internal/ethapi/transaction_args_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,9 @@ func (b *backendMock) SubscribeChainSideEvent(ch chan<- core.ChainSideEvent) eve
return nil
}
func (b *backendMock) SendTx(ctx context.Context, signedTx *types.Transaction) error { return nil }
func (b *backendMock) SendInteropBundle(ctx context.Context, txs types.Transactions, blockNumber rpc.BlockNumber, minTimestamp, maxTimestamp uint64) (*types.SimulatedBundle, error) {
return nil, nil
}
func (b *backendMock) GetTransaction(ctx context.Context, txHash common.Hash) (bool, *types.Transaction, common.Hash, uint64, uint64, error) {
return false, nil, [32]byte{}, 0, 0, nil
}
Expand Down
8 changes: 8 additions & 0 deletions miner/miner.go
Original file line number Diff line number Diff line change
Expand Up @@ -258,3 +258,11 @@ func (miner *Miner) SubscribePendingLogs(ch chan<- []*types.Log) event.Subscript
func (miner *Miner) BuildPayload(args *BuildPayloadArgs) (*Payload, error) {
return miner.worker.buildPayload(args)
}

func (miner *Miner) SimulateBundle(bundle types.MevBundle) (*types.SimulatedBundle, error) {
return miner.worker.simulateBundle(bundle)
}

func (mint *Miner) GetTopBundle() (*types.SimulatedBundle, error) {
return mint.worker.getTopBundle()
}
Loading