Skip to content

Commit

Permalink
Use Nethermind as Optimism Sequencer (#7287)
Browse files Browse the repository at this point in the history
  • Loading branch information
emlautarom1 authored Jul 31, 2024
1 parent ba3045d commit 1605dd7
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 21 deletions.
42 changes: 25 additions & 17 deletions src/Nethermind/Nethermind.JsonRpc.Test/Modules/TestRpcBlockchain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -105,12 +105,36 @@ public Builder<T> WithConfig(IJsonRpcConfig config)
return this;
}

public Builder<T> WithEthRpcModule(Func<TestRpcBlockchain, IEthRpcModule> builder)
{
_blockchain._ethRpcModuleBuilder = builder;
return this;
}

public async Task<T> Build(
ISpecProvider? specProvider = null,
UInt256? initialValues = null) =>
(T)(await _blockchain.Build(specProvider, initialValues, true));
}

private Func<TestRpcBlockchain, IEthRpcModule> _ethRpcModuleBuilder = @this => new EthRpcModule(
@this.RpcConfig,
@this.Bridge,
@this.BlockFinder,
@this.ReceiptFinder,
@this.StateReader,
@this.TxPool,
@this.TxSender,
@this.TestWallet,
LimboLogs.Instance,
@this.SpecProvider,
@this.GasPriceOracle,
new EthSyncingInfo(@this.BlockTree, @this.ReceiptStorage, new SyncConfig(),
new StaticSelector(SyncMode.All), Substitute.For<ISyncProgressResolver>(), @this.LogManager),
@this.FeeHistoryOracle ??
new FeeHistoryOracle(@this.BlockTree, @this.ReceiptStorage, @this.SpecProvider),
new BlocksConfig().SecondsPerSlot);

protected override async Task<TestBlockchain> Build(
ISpecProvider? specProvider = null,
UInt256? initialValues = null,
Expand Down Expand Up @@ -145,23 +169,7 @@ protected override async Task<TestBlockchain> Build(
TxSender ??= new TxPoolSender(TxPool, TxSealer, NonceManager, EthereumEcdsa ?? new EthereumEcdsa(specProvider.ChainId, LogManager));
GasPriceOracle ??= new GasPriceOracle(BlockFinder, SpecProvider, LogManager);
FeeHistoryOracle ??= new FeeHistoryOracle(BlockTree, ReceiptStorage, SpecProvider);
ISyncConfig syncConfig = new SyncConfig();
EthRpcModule = new EthRpcModule(
RpcConfig,
Bridge,
BlockFinder,
ReceiptFinder,
StateReader,
TxPool,
TxSender,
TestWallet,
LimboLogs.Instance,
SpecProvider,
GasPriceOracle,
new EthSyncingInfo(BlockTree, ReceiptStorage, syncConfig,
new StaticSelector(SyncMode.All), Substitute.For<ISyncProgressResolver>(), LogManager),
FeeHistoryOracle,
blocksConfig.SecondsPerSlot);
EthRpcModule = _ethRpcModuleBuilder(this);

return this;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
<PackageReference Include="RichardSzalay.MockHttp" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Nethermind.JsonRpc.Test\Nethermind.JsonRpc.Test.csproj" />
<ProjectReference Include="..\Nethermind.Optimism\Nethermind.Optimism.csproj" />
</ItemGroup>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// SPDX-FileCopyrightText: 2024 Demerzel Solutions Limited
// SPDX-License-Identifier: LGPL-3.0-only

using System.Threading.Tasks;
using Nethermind.Blockchain.Synchronization;
using Nethermind.Config;
using Nethermind.Core;
using Nethermind.Core.Extensions;
using Nethermind.Core.Test.Builders;
using Nethermind.Crypto;
using Nethermind.Facade;
using Nethermind.Facade.Eth;
using Nethermind.JsonRpc.Client;
using Nethermind.JsonRpc.Modules.Eth.FeeHistory;
using Nethermind.JsonRpc.Test.Modules;
using Nethermind.Logging;
using Nethermind.Optimism.Rpc;
using Nethermind.Serialization.Rlp;
using Nethermind.Synchronization.ParallelSync;
using Nethermind.TxPool;
using NSubstitute;
using NUnit.Framework;

namespace Nethermind.Optimism.Test.Rpc;

public class OptimismEthRpcModuleTest
{
[Test]
public async Task Sequencer_send_transaction_with_signature_will_not_try_to_sign()
{
IBlockchainBridge bridge = Substitute.For<IBlockchainBridge>();
ITxSender txSender = Substitute.For<ITxSender>();
txSender.SendTransaction(tx: Arg.Any<Transaction>(), txHandlingOptions: TxHandlingOptions.PersistentBroadcast)
.Returns(returnThis: (TestItem.KeccakA, AcceptTxResult.Accepted));

EthereumEcdsa ethereumEcdsa = new EthereumEcdsa(chainId: TestBlockchainIds.ChainId, logManager: LimboLogs.Instance);
TestRpcBlockchain rpcBlockchain = await TestRpcBlockchain
.ForTest(sealEngineType: SealEngineType.Optimism)
.WithBlockchainBridge(bridge)
.WithTxSender(txSender)
.WithOptimismEthRpcModule(
sequencerRpcClient: null /* explicitly using null to behave as Sequencer */,
accountStateProvider: Substitute.For<IAccountStateProvider>(),
ecdsa: new OptimismEthereumEcdsa(ethereumEcdsa),
sealer: Substitute.For<ITxSealer>(),
opSpecHelper: Substitute.For<IOptimismSpecHelper>())
.Build();

Transaction tx = Build.A.Transaction
.Signed(ecdsa: ethereumEcdsa, privateKey: TestItem.PrivateKeyA)
.TestObject;
string serialized = await rpcBlockchain.TestEthRpc("eth_sendRawTransaction", Rlp.Encode(item: tx, behaviors: RlpBehaviors.None).Bytes.ToHexString());

await txSender.Received().SendTransaction(tx: Arg.Any<Transaction>(), txHandlingOptions: TxHandlingOptions.PersistentBroadcast);
Assert.That(actual: serialized, expression: Is.EqualTo(expected: $$"""{"jsonrpc":"2.0","result":"{{TestItem.KeccakA.Bytes.ToHexString(withZeroX: true)}}","id":67}"""));
}
}

internal static class TestRpcBlockchainExt
{
public static TestRpcBlockchain.Builder<TestRpcBlockchain> WithOptimismEthRpcModule(
this TestRpcBlockchain.Builder<TestRpcBlockchain> @this,
IJsonRpcClient? sequencerRpcClient,
IAccountStateProvider accountStateProvider,
IEthereumEcdsa ecdsa,
ITxSealer sealer,
IOptimismSpecHelper opSpecHelper)
{
return @this.WithEthRpcModule(blockchain => new OptimismEthRpcModule(
blockchain.RpcConfig,
blockchain.Bridge,
blockchain.BlockFinder,
blockchain.ReceiptFinder,
blockchain.StateReader,
blockchain.TxPool,
blockchain.TxSender,
blockchain.TestWallet,
LimboLogs.Instance,
blockchain.SpecProvider,
blockchain.GasPriceOracle,
new EthSyncingInfo(blockchain.BlockTree, blockchain.ReceiptStorage, new SyncConfig(),
new StaticSelector(SyncMode.All), Substitute.For<ISyncProgressResolver>(), blockchain.LogManager),
blockchain.FeeHistoryOracle ??
new FeeHistoryOracle(blockchain.BlockTree, blockchain.ReceiptStorage, blockchain.SpecProvider),
new BlocksConfig().SecondsPerSlot,
sequencerRpcClient, accountStateProvider, ecdsa, sealer, opSpecHelper
));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ IOptimismSpecHelper opSpecHelper
private readonly IGasPriceOracle _gasPriceOracle = gasPriceOracle ?? throw new ArgumentNullException(nameof(gasPriceOracle));
private readonly IEthSyncingInfo _ethSyncingInfo = ethSyncingInfo ?? throw new ArgumentNullException(nameof(ethSyncingInfo));
private readonly IFeeHistoryOracle _feeHistoryOracle = feeHistoryOracle ?? throw new ArgumentNullException(nameof(feeHistoryOracle));
private readonly IJsonRpcClient? _sequencerRpcClient = sequencerRpcClient ?? throw new ArgumentNullException(nameof(sequencerRpcClient));
private readonly IAccountStateProvider _accountStateProvider = accountStateProvider ?? throw new ArgumentNullException(nameof(accountStateProvider));
private readonly IEthereumEcdsa _ecdsa = ecdsa ?? throw new ArgumentNullException(nameof(ecdsa));
private readonly ITxSealer _sealer = sealer ?? throw new ArgumentNullException(nameof(sealer));
Expand All @@ -82,7 +81,7 @@ public override IOptimismEthRpcModule Create()
_feeHistoryOracle,
secondsPerSlot,

_sequencerRpcClient,
sequencerRpcClient,
_accountStateProvider,
_ecdsa,
_sealer,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,13 +130,15 @@ public override async Task<ResultWrapper<Hash256>> eth_sendRawTransaction(byte[]
{
if (_sequencerRpcClient is null)
{
return ResultWrapper<Hash256>.Fail("No sequencer url in the config");
return await base.eth_sendRawTransaction(transaction);
}

Hash256? result = await _sequencerRpcClient.Post<Hash256>(nameof(eth_sendRawTransaction), transaction);
if (result is null)
{
return ResultWrapper<Hash256>.Fail("Failed to forward transaction");
}

return ResultWrapper<Hash256>.Success(result);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ protected override void RegisterEthRpcModule(IRpcModuleProvider rpcModuleProvide

if (_config.SequencerUrl is null && _logger.IsWarn)
{
_logger.Warn($"SequencerUrl is not set.");
_logger.Warn($"SequencerUrl is not set. Nethermind will behave as a Sequencer");
}

BasicJsonRpcClient? sequencerJsonRpcClient = _config.SequencerUrl is null
Expand Down

0 comments on commit 1605dd7

Please sign in to comment.