Commit 39586441 authored by Mark Tyneway's avatar Mark Tyneway Committed by GitHub

l2 geth: feat `debug_ingestTransactions` (#853)

* l2geth: debug_ingestTransactions endpoint

* chore: add changeset

* l2geth: remove dead type

* chore: update changeset
Co-authored-by: default avatarGeorgios Konstantopoulos <me@gakonst.com>
parent 3b3d947e
---
'@eth-optimism/l2geth': patch
---
Adds the `debug_ingestTransactions` endpoint that takes a list of RPC transactions and applies each of them to the state sequentially. This is useful for testing purposes
......@@ -130,6 +130,16 @@ func (b *EthAPIBackend) SetHead(number uint64) {
b.eth.syncService.SetLatestL1BlockNumber(blockNumber.Uint64())
}
func (b *EthAPIBackend) IngestTransactions(txs []*types.Transaction) error {
for _, tx := range txs {
err := b.eth.syncService.IngestTransaction(tx)
if err != nil {
return err
}
}
return nil
}
func (b *EthAPIBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) {
// Pending block is only known by the miner
if number == rpc.PendingBlockNumber {
......
......@@ -2116,6 +2116,53 @@ func (api *PrivateDebugAPI) SetHead(number hexutil.Uint64) {
api.b.SetHead(uint64(number))
}
func (api *PrivateDebugAPI) IngestTransactions(txs []*RPCTransaction) error {
transactions := make([]*types.Transaction, len(txs))
for i, tx := range txs {
nonce := uint64(tx.Nonce)
value := tx.Value.ToInt()
gasLimit := uint64(tx.Gas)
gasPrice := tx.GasPrice.ToInt()
data := tx.Input
l1BlockNumber := tx.L1BlockNumber.ToInt()
l1Timestamp := uint64(tx.L1Timestamp)
rawTransaction := tx.RawTransaction
sighashType := types.SighashEIP155
var queueOrigin types.QueueOrigin
switch tx.QueueOrigin {
case "sequencer":
queueOrigin = types.QueueOriginSequencer
case "l1":
queueOrigin = types.QueueOriginL1ToL2
default:
return fmt.Errorf("Transaction with unknown queue origin: %s", tx.TxType)
}
var transaction *types.Transaction
if tx.To == nil {
transaction = types.NewContractCreation(nonce, value, gasLimit, gasPrice, data)
} else {
transaction = types.NewTransaction(nonce, *tx.To, value, gasLimit, gasPrice, data)
}
meta := types.TransactionMeta{
L1BlockNumber: l1BlockNumber,
L1Timestamp: l1Timestamp,
L1MessageSender: tx.L1TxOrigin,
SignatureHashType: sighashType,
QueueOrigin: big.NewInt(int64(queueOrigin)),
Index: (*uint64)(tx.Index),
QueueIndex: (*uint64)(tx.QueueIndex),
RawTransaction: rawTransaction,
}
transaction.SetTransactionMeta(&meta)
transactions[i] = transaction
}
return api.b.IngestTransactions(transactions)
}
// PublicNetAPI offers network related RPC methods
type PublicNetAPI struct {
net *p2p.Server
......
......@@ -98,6 +98,7 @@ type Backend interface {
SetDataPrice(context.Context, *big.Int)
SuggestExecutionPrice(context.Context) (*big.Int, error)
SetExecutionPrice(context.Context, *big.Int)
IngestTransactions([]*types.Transaction) error
}
func GetAPIs(apiBackend Backend) []rpc.API {
......
......@@ -87,6 +87,10 @@ func (b *LesApiBackend) SetHead(number uint64) {
b.eth.blockchain.SetHead(number)
}
func (b *LesApiBackend) IngestTransactions([]*types.Transaction) error {
panic("not implemented")
}
func (b *LesApiBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) {
if number == rpc.LatestBlockNumber || number == rpc.PendingBlockNumber {
return b.eth.blockchain.CurrentHeader(), nil
......
......@@ -744,3 +744,9 @@ func (s *SyncService) ApplyTransaction(tx *types.Transaction) error {
}
return s.applyTransaction(tx)
}
// IngestTransaction should only be called by trusted parties as it skips all
// validation and applies the transaction
func (s *SyncService) IngestTransaction(tx *types.Transaction) error {
return s.applyTransaction(tx)
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment