Skip to content

Commit

Permalink
Add custom Eth module that exposes additional OP related fields (#7096)
Browse files Browse the repository at this point in the history
Co-authored-by: Nikita Mescheryakov <root@nikitam.io>
  • Loading branch information
flcl42 and deffrian authored Jun 5, 2024
1 parent 6aab680 commit f91e27e
Show file tree
Hide file tree
Showing 28 changed files with 764 additions and 420 deletions.
28 changes: 22 additions & 6 deletions src/Nethermind/Chains/base-mainnet.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"params": {
"regolithTimestamp": "0x0",
"bedrockBlockNumber": "0x0",
"ecotoneTimestamp": "0x65F23E01",
"canyonTimestamp": "0x65a01e91",
"ecotoneTimestamp": "0x65f23e01",
"l1FeeRecipient": "0x420000000000000000000000000000000000001A",
"l1BlockAddress": "0x4200000000000000000000000000000000000015"
}
Expand Down Expand Up @@ -48,11 +49,16 @@
"eip3529Transition": "0x0",
"eip3541Transition": "0x0",

"eip1153TransitionTimestamp": "0x65F23E01",
"eip4788TransitionTimestamp": "0x65F23E01",
"eip4844TransitionTimestamp": "0x65F23E01",
"eip5656TransitionTimestamp": "0x65F23E01",
"eip6780TransitionTimestamp": "0x65F23E01",
"eip4895TransitionTimestamp": "0x65a01e91",
"eip3651TransitionTimestamp": "0x65a01e91",
"eip3855TransitionTimestamp": "0x65a01e91",
"eip3860TransitionTimestamp": "0x65a01e91",

"eip1153TransitionTimestamp": "0x65f23e01",
"eip4788TransitionTimestamp": "0x65f23e01",
"eip4844TransitionTimestamp": "0x65f23e01",
"eip5656TransitionTimestamp": "0x65f23e01",
"eip6780TransitionTimestamp": "0x65f23e01",

"terminalTotalDifficulty": "0"
},
Expand All @@ -72,6 +78,16 @@
"baseFeePerGas": "0x3b9aca00",
"gasLimit": "0x1c9c380"
},
"nodes": [
"enode://ca2774c3c401325850b2477fd7d0f27911efbf79b1e8b335066516e2bd8c4c9e0ba9696a94b1cb030a88eac582305ff55e905e64fb77fe0edcd70a4e5296d3ec@34.65.175.185:30305",
"enode://dd751a9ef8912be1bfa7a5e34e2c3785cc5253110bd929f385e07ba7ac19929fb0e0c5d93f77827291f4da02b2232240fbc47ea7ce04c46e333e452f8656b667@34.65.107.0:30305",
"enode://c5d289b56a77b6a2342ca29956dfd07aadf45364dde8ab20d1dc4efd4d1bc6b4655d902501daea308f4d8950737a4e93a4dfedd17b49cd5760ffd127837ca965@34.65.202.239:30305",
"enode://87a32fd13bd596b2ffca97020e31aef4ddcc1bbd4b95bb633d16c1329f654f34049ed240a36b449fda5e5225d70fe40bc667f53c304b71f8e68fc9d448690b51@3.231.138.188:30301",
"enode://ca21ea8f176adb2e229ce2d700830c844af0ea941a1d8152a9513b966fe525e809c3a6c73a2c18a12b74ed6ec4380edf91662778fe0b79f6a591236e49e176f9@184.72.129.189:30301",
"enode://acf4507a211ba7c1e52cdf4eef62cdc3c32e7c9c47998954f7ba024026f9a6b2150cd3f0b734d9c78e507ab70d59ba61dfe5c45e1078c7ad0775fb251d7735a2@3.220.145.177:30301",
"enode://8a5a5006159bf079d06a04e5eceab2a1ce6e0f721875b2a9c96905336219dbe14203d38f70f3754686a6324f786c2f9852d8c0dd3adac2d080f4db35efc678c5@3.231.11.52:30301",
"enode://cdadbe835308ad3557f9a1de8db411da1a260a98f8421d62da90e71da66e55e98aaa8e90aa7ce01b408a54e4bd2253d701218081ded3dbe5efbbc7b41d7cef79@54.198.153.150:30301"
],
"accounts": {
"0000000000000000000000000000000000000001": {
"builtin": {
Expand Down
9 changes: 8 additions & 1 deletion src/Nethermind/Chains/base-sepolia.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"regolithTimestamp": "0x0",
"bedrockBlockNumber": "0x0",
"canyonTimestamp": "0x6553a790",
"ecotoneTimestamp": "0x65D62C10",
"ecotoneTimestamp": "0x65d62c10",
"l1FeeRecipient": "0x420000000000000000000000000000000000001A",
"l1BlockAddress": "0x4200000000000000000000000000000000000015",
"canyonBaseFeeChangeDenominator": "250",
Expand Down Expand Up @@ -81,6 +81,13 @@
"baseFeePerGas": "0x3b9aca00",
"gasLimit": "0x17d7840"
},
"nodes": [
"enode://2bd2e657bb3c8efffb8ff6db9071d9eb7be70d7c6d7d980ff80fc93b2629675c5f750bc0a5ef27cd788c2e491b8795a7e9a4a6e72178c14acc6753c0e5d77ae4@34.65.205.244:30305",
"enode://db8e1cab24624cc62fc35dbb9e481b88a9ef0116114cd6e41034c55b5b4f18755983819252333509bd8e25f6b12aadd6465710cd2e956558faf17672cce7551f@34.65.173.88:30305",
"enode://bfda2e0110cfd0f4c9f7aa5bf5ec66e6bd18f71a2db028d36b8bf8b0d6fdb03125c1606a6017b31311d96a36f5ef7e1ad11604d7a166745e6075a715dfa67f8a@34.65.229.245:30305",
"enode://548f715f3fc388a7c917ba644a2f16270f1ede48a5d88a4d14ea287cc916068363f3092e39936f1a3e7885198bef0e5af951f1d7b1041ce8ba4010917777e71f@18.210.176.114:30301",
"enode://6f10052847a966a725c9f4adf6716f9141155b99a0fb487fea3f51498f4c2a2cb8d534e680ee678f9447db85b93ff7c74562762c3714783a7233ac448603b25f@107.21.251.55:30301"
],
"accounts": {
"0000000000000000000000000000000000000001": {
"balance": "0x1",
Expand Down
18 changes: 12 additions & 6 deletions src/Nethermind/Chains/op-mainnet.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"params": {
"regolithTimestamp": "0x0",
"bedrockBlockNumber": "0x645C277",
"ecotoneTimestamp": "0x65F23E01",
"canyonTimestamp": "0x65a01e91",
"ecotoneTimestamp": "0x65f23e01",
"l1FeeRecipient": "0x420000000000000000000000000000000000001A",
"l1BlockAddress": "0x4200000000000000000000000000000000000015"
}
Expand Down Expand Up @@ -53,11 +54,16 @@
"eip3529Transition": "0x645C277",
"eip3541Transition": "0x645C277",

"eip1153TransitionTimestamp": "0x65F23E01",
"eip4788TransitionTimestamp": "0x65F23E01",
"eip4844TransitionTimestamp": "0x65F23E01",
"eip5656TransitionTimestamp": "0x65F23E01",
"eip6780TransitionTimestamp": "0x65F23E01",
"eip4895TransitionTimestamp": "0x65a01e91",
"eip3651TransitionTimestamp": "0x65a01e91",
"eip3855TransitionTimestamp": "0x65a01e91",
"eip3860TransitionTimestamp": "0x65a01e91",

"eip1153TransitionTimestamp": "0x65f23e01",
"eip4788TransitionTimestamp": "0x65f23e01",
"eip4844TransitionTimestamp": "0x65f23e01",
"eip5656TransitionTimestamp": "0x65f23e01",
"eip6780TransitionTimestamp": "0x65f23e01",

"terminalTotalDifficulty": "0"
},
Expand Down
9 changes: 3 additions & 6 deletions src/Nethermind/Chains/op-sepolia.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,18 +51,15 @@
"eip3198Transition": "0x0",
"eip3529Transition": "0x0",
"eip3541Transition": "0x0",

"eip4895TransitionTimestamp": "0x6553a790",
"eip3651TransitionTimestamp": "0x6553a790",
"eip3855TransitionTimestamp": "0x6553a790",
"eip3860TransitionTimestamp": "0x6553a790",

"eip1153TransitionTimestamp": "0x65D62C10",
"eip4788TransitionTimestamp": "0x65D62C10",
"eip4844TransitionTimestamp": "0x65D62C10",
"eip5656TransitionTimestamp": "0x65D62C10",
"eip6780TransitionTimestamp": "0x65D62C10",

"terminalTotalDifficulty": "0"
},
"genesis": {
Expand All @@ -83,8 +80,8 @@
},
"nodes": [
"enode://2bd2e657bb3c8efffb8ff6db9071d9eb7be70d7c6d7d980ff80fc93b2629675c5f750bc0a5ef27cd788c2e491b8795a7e9a4a6e72178c14acc6753c0e5d77ae4@34.65.205.244:30305",
"enode://db8e1cab24624cc62fc35dbb9e481b88a9ef0116114cd6e41034c55b5b4f18755983819252333509bd8e25f6b12aadd6465710cd2e956558faf17672cce7551f@34.65.173.88:30305",
"enode://bfda2e0110cfd0f4c9f7aa5bf5ec66e6bd18f71a2db028d36b8bf8b0d6fdb03125c1606a6017b31311d96a36f5ef7e1ad11604d7a166745e6075a715dfa67f8a@34.65.229.245:30305",
"enode://db8e1cab24624cc62fc35dbb9e481b88a9ef0116114cd6e41034c55b5b4f18755983819252333509bd8e25f6b12aadd6465710cd2e956558faf17672cce7551f@34.65.173.88:30305",
"enode://bfda2e0110cfd0f4c9f7aa5bf5ec66e6bd18f71a2db028d36b8bf8b0d6fdb03125c1606a6017b31311d96a36f5ef7e1ad11604d7a166745e6075a715dfa67f8a@34.65.229.245:30305",
"enode://548f715f3fc388a7c917ba644a2f16270f1ede48a5d88a4d14ea287cc916068363f3092e39936f1a3e7885198bef0e5af951f1d7b1041ce8ba4010917777e71f@18.210.176.114:30301",
"enode://6f10052847a966a725c9f4adf6716f9141155b99a0fb487fea3f51498f4c2a2cb8d534e680ee678f9447db85b93ff7c74562762c3714783a7233ac448603b25f@107.21.251.55:30301"
],
Expand Down Expand Up @@ -12575,4 +12572,4 @@
"balance": "0x0"
}
}
}
}
15 changes: 11 additions & 4 deletions src/Nethermind/Nethermind.Init/Steps/RegisterRpcModules.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,9 @@ public virtual async Task Execute(CancellationToken cancellationToken)
StepDependencyException.ThrowIfNull(_api.GasPriceOracle);
StepDependencyException.ThrowIfNull(_api.EthSyncingInfo);

ModuleFactoryBase<IEthRpcModule> ethModuleFactory = CreateEthModuleFactory();

RpcLimits.Init(_jsonRpcConfig.RequestQueueLimit);
rpcModuleProvider.RegisterBounded(ethModuleFactory, _jsonRpcConfig.EthModuleConcurrentInstances ?? Environment.ProcessorCount, _jsonRpcConfig.Timeout);
RegisterEthRpcModule(rpcModuleProvider);


StepDependencyException.ThrowIfNull(_api.DbProvider);
StepDependencyException.ThrowIfNull(_api.BlockPreprocessor);
Expand Down Expand Up @@ -213,7 +212,7 @@ public virtual async Task Execute(CancellationToken cancellationToken)
await Task.CompletedTask;
}

protected virtual ModuleFactoryBase<IEthRpcModule> CreateEthModuleFactory()
protected ModuleFactoryBase<IEthRpcModule> CreateEthModuleFactory()
{
StepDependencyException.ThrowIfNull(_api.BlockTree);
StepDependencyException.ThrowIfNull(_api.ReceiptStorage);
Expand Down Expand Up @@ -242,4 +241,12 @@ protected virtual ModuleFactoryBase<IEthRpcModule> CreateEthModuleFactory()
_api.EthSyncingInfo,
feeHistoryOracle);
}

protected virtual void RegisterEthRpcModule(IRpcModuleProvider rpcModuleProvider)
{
ModuleFactoryBase<IEthRpcModule> ethModuleFactory = CreateEthModuleFactory();

rpcModuleProvider.RegisterBounded(ethModuleFactory,
_jsonRpcConfig.EthModuleConcurrentInstances ?? Environment.ProcessorCount, _jsonRpcConfig.Timeout);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,12 @@
using Nethermind.Core.Specs;
using Nethermind.Facade;
using Nethermind.Facade.Eth;
using Nethermind.JsonRpc.Data;
using Nethermind.JsonRpc.Modules.Eth.GasPrice;
using Nethermind.JsonRpc.Modules.Eth.FeeHistory;
using Nethermind.Logging;
using Nethermind.State;
using Nethermind.TxPool;
using Nethermind.Wallet;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace Nethermind.JsonRpc.Modules.Eth
{
Expand Down
118 changes: 51 additions & 67 deletions src/Nethermind/Nethermind.JsonRpc/Modules/Eth/EthRpcModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,58 +38,41 @@

namespace Nethermind.JsonRpc.Modules.Eth;

public partial class EthRpcModule : IEthRpcModule
public partial class EthRpcModule(
IJsonRpcConfig rpcConfig,
IBlockchainBridge blockchainBridge,
IBlockFinder blockFinder,
IReceiptFinder receiptFinder,
IStateReader stateReader,
ITxPool txPool,
ITxSender txSender,
IWallet wallet,
ILogManager logManager,
ISpecProvider specProvider,
IGasPriceOracle gasPriceOracle,
IEthSyncingInfo ethSyncingInfo,
IFeeHistoryOracle feeHistoryOracle) : IEthRpcModule
{
private readonly Encoding _messageEncoding = Encoding.UTF8;
private readonly IJsonRpcConfig _rpcConfig;
private readonly IBlockchainBridge _blockchainBridge;
private readonly IBlockFinder _blockFinder;
private readonly IReceiptFinder _receiptFinder;
private readonly IStateReader _stateReader;
private readonly ITxPool _txPoolBridge;
private readonly ITxSender _txSender;
private readonly IWallet _wallet;
private readonly ISpecProvider _specProvider;
private readonly ILogger _logger;
private readonly IGasPriceOracle _gasPriceOracle;
private readonly IEthSyncingInfo _ethSyncingInfo;

private readonly IFeeHistoryOracle _feeHistoryOracle;
protected readonly Encoding _messageEncoding = Encoding.UTF8;
protected readonly IJsonRpcConfig _rpcConfig = rpcConfig ?? throw new ArgumentNullException(nameof(rpcConfig));
protected readonly IBlockchainBridge _blockchainBridge = blockchainBridge ?? throw new ArgumentNullException(nameof(blockchainBridge));
protected readonly IBlockFinder _blockFinder = blockFinder ?? throw new ArgumentNullException(nameof(blockFinder));
protected readonly IReceiptFinder _receiptFinder = receiptFinder ?? throw new ArgumentNullException(nameof(receiptFinder));
protected readonly IStateReader _stateReader = stateReader ?? throw new ArgumentNullException(nameof(stateReader));
protected readonly ITxPool _txPoolBridge = txPool ?? throw new ArgumentNullException(nameof(txPool));
protected readonly ITxSender _txSender = txSender ?? throw new ArgumentNullException(nameof(txSender));
protected readonly IWallet _wallet = wallet ?? throw new ArgumentNullException(nameof(wallet));
protected readonly ISpecProvider _specProvider = specProvider ?? throw new ArgumentNullException(nameof(specProvider));
protected readonly ILogger _logger = logManager.GetClassLogger();
protected readonly IGasPriceOracle _gasPriceOracle = gasPriceOracle ?? throw new ArgumentNullException(nameof(gasPriceOracle));
protected readonly IEthSyncingInfo _ethSyncingInfo = ethSyncingInfo ?? throw new ArgumentNullException(nameof(ethSyncingInfo));
protected readonly IFeeHistoryOracle _feeHistoryOracle = feeHistoryOracle ?? throw new ArgumentNullException(nameof(feeHistoryOracle));

private static bool HasStateForBlock(IBlockchainBridge blockchainBridge, BlockHeader header)
{
return blockchainBridge.HasStateForRoot(header.StateRoot!);
}

public EthRpcModule(
IJsonRpcConfig rpcConfig,
IBlockchainBridge blockchainBridge,
IBlockFinder blockFinder,
IReceiptFinder receiptFinder,
IStateReader stateReader,
ITxPool txPool,
ITxSender txSender,
IWallet wallet,
ILogManager logManager,
ISpecProvider specProvider,
IGasPriceOracle gasPriceOracle,
IEthSyncingInfo ethSyncingInfo,
IFeeHistoryOracle feeHistoryOracle)
{
_logger = logManager.GetClassLogger();
_rpcConfig = rpcConfig ?? throw new ArgumentNullException(nameof(rpcConfig));
_blockchainBridge = blockchainBridge ?? throw new ArgumentNullException(nameof(blockchainBridge));
_blockFinder = blockFinder ?? throw new ArgumentNullException(nameof(blockFinder));
_receiptFinder = receiptFinder ?? throw new ArgumentNullException(nameof(receiptFinder));
_stateReader = stateReader ?? throw new ArgumentNullException(nameof(stateReader));
_txPoolBridge = txPool ?? throw new ArgumentNullException(nameof(txPool));
_txSender = txSender ?? throw new ArgumentNullException(nameof(txSender));
_wallet = wallet ?? throw new ArgumentNullException(nameof(wallet));
_specProvider = specProvider ?? throw new ArgumentNullException(nameof(specProvider));
_gasPriceOracle = gasPriceOracle ?? throw new ArgumentNullException(nameof(gasPriceOracle));
_ethSyncingInfo = ethSyncingInfo ?? throw new ArgumentNullException(nameof(ethSyncingInfo));
_feeHistoryOracle = feeHistoryOracle ?? throw new ArgumentNullException(nameof(feeHistoryOracle));
}

public ResultWrapper<string> eth_protocolVersion()
{
int highestVersion = P2PProtocolInfoProvider.GetHighestVersionOfEthProtocol();
Expand Down Expand Up @@ -193,7 +176,7 @@ public ResultWrapper<byte[]> eth_getStorageAt(Address address, UInt256 positionI
return ResultWrapper<byte[]>.Success(storage.IsEmpty ? Bytes32.Zero.Unwrap() : storage!.PadLeft(32));
}

public Task<ResultWrapper<UInt256>> eth_getTransactionCount(Address address, BlockParameter blockParameter)
public Task<ResultWrapper<UInt256>> eth_getTransactionCount(Address address, BlockParameter? blockParameter)
{
if (blockParameter == BlockParameter.Pending)
{
Expand Down Expand Up @@ -233,11 +216,6 @@ public Task<ResultWrapper<UInt256>> eth_getTransactionCount(Address address, Blo
: ResultWrapper<UInt256?>.Success((UInt256)searchResult.Object!.Transactions.Length);
}

public ResultWrapper<ReceiptForRpc[]> eth_getBlockReceipts(BlockParameter blockParameter)
{
return _receiptFinder.GetBlockReceipts(blockParameter, _blockFinder, _specProvider);
}

public ResultWrapper<UInt256?> eth_getUncleCountByBlockHash(Hash256 blockHash)
{
SearchResult<Block> searchResult = _blockFinder.SearchForBlock(new BlockParameter(blockHash));
Expand Down Expand Up @@ -295,14 +273,14 @@ public ResultWrapper<byte[]> eth_sign(Address addressData, byte[] message)
return ResultWrapper<byte[]>.Success(sig.Bytes);
}

public Task<ResultWrapper<Hash256>> eth_sendTransaction(TransactionForRpc rpcTx)
public virtual Task<ResultWrapper<Hash256>> eth_sendTransaction(TransactionForRpc rpcTx)
{
Transaction tx = rpcTx.ToTransactionWithDefaults(_blockchainBridge.GetChainId());
TxHandlingOptions options = rpcTx.Nonce is null ? TxHandlingOptions.ManagedNonce : TxHandlingOptions.None;
return SendTx(tx, options);
}

public async Task<ResultWrapper<Hash256>> eth_sendRawTransaction(byte[] transaction)
public virtual async Task<ResultWrapper<Hash256>> eth_sendRawTransaction(byte[] transaction)
{
try
{
Expand Down Expand Up @@ -343,7 +321,7 @@ public ResultWrapper<string> eth_call(TransactionForRpc transactionCall, BlockPa
new CallTxExecutor(_blockchainBridge, _blockFinder, _rpcConfig)
.ExecuteTx(transactionCall, blockParameter);

public ResultWrapper<UInt256?> eth_estimateGas(TransactionForRpc transactionCall, BlockParameter blockParameter) =>
public ResultWrapper<UInt256?> eth_estimateGas(TransactionForRpc transactionCall, BlockParameter? blockParameter) =>
new EstimateGasTxExecutor(_blockchainBridge, _blockFinder, _rpcConfig)
.ExecuteTx(transactionCall, blockParameter);

Expand Down Expand Up @@ -468,18 +446,6 @@ public ResultWrapper<TransactionForRpc> eth_getTransactionByBlockNumberAndIndex(
return ResultWrapper<TransactionForRpc>.Success(transactionModel);
}

public Task<ResultWrapper<ReceiptForRpc>> eth_getTransactionReceipt(Hash256 txHash)
{
(TxReceipt? receipt, TxGasInfo? gasInfo, int logIndexStart) = _blockchainBridge.GetReceiptAndGasInfo(txHash);
if (receipt is null || gasInfo is null)
{
return Task.FromResult(ResultWrapper<ReceiptForRpc>.Success(null));
}

if (_logger.IsTrace) _logger.Trace($"eth_getTransactionReceipt request {txHash}, result: {txHash}");
return Task.FromResult(ResultWrapper<ReceiptForRpc>.Success(new(txHash, receipt, gasInfo.Value, logIndexStart)));
}

public ResultWrapper<BlockForRpc> eth_getUncleByBlockHashAndIndex(Hash256 blockHash, UInt256 positionIndex)
{
return GetUncle(new BlockParameter(blockHash), positionIndex);
Expand Down Expand Up @@ -730,4 +696,22 @@ private static ResultWrapper<TResult> GetFailureResult<TResult>(ResourceNotFound

private ResultWrapper<TResult> GetStateFailureResult<TResult>(BlockHeader header) =>
ResultWrapper<TResult>.Fail($"No state available for block {header.ToString(BlockHeader.Format.FullHashAndNumber)}", ErrorCodes.ResourceUnavailable, _ethSyncingInfo.SyncMode.HaveNotSyncedStateYet());

public ResultWrapper<ReceiptForRpc?> eth_getTransactionReceipt(Hash256 txHash)
{
(TxReceipt? receipt, TxGasInfo? gasInfo, int logIndexStart) = _blockchainBridge.GetReceiptAndGasInfo(txHash);
if (receipt is null || gasInfo is null)
{
return ResultWrapper<ReceiptForRpc>.Success(null);
}

if (_logger.IsTrace) _logger.Trace($"eth_getTransactionReceipt request {txHash}, result: {txHash}");
return ResultWrapper<ReceiptForRpc>.Success(new(txHash, receipt, gasInfo.Value, logIndexStart));
}


public ResultWrapper<ReceiptForRpc[]?> eth_getBlockReceipts(BlockParameter blockParameter)
{
return _receiptFinder.GetBlockReceipts(blockParameter, _blockFinder, _specProvider);
}
}
Loading

0 comments on commit f91e27e

Please sign in to comment.