Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature t8n gnosis #7319

Merged
merged 9 commits into from
Oct 16, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
83 changes: 66 additions & 17 deletions src/Nethermind/Ethereum.Test.Base/GeneralTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public abstract class GeneralStateTestBase
private static ILogger _logger = new(new ConsoleAsyncLogger(LogLevel.Info));
private static ILogManager _logManager = LimboLogs.Instance;
private static readonly UInt256 _defaultBaseFeeForStateTest = 0xA;
private readonly TxValidator _txValidator = new(MainnetSpecProvider.Instance.ChainId);
private TxValidator _txValidator = new(MainnetSpecProvider.Instance.ChainId);
private readonly BeaconBlockRootHandler _beaconBlockRootHandler = new();

[SetUp]
Expand All @@ -60,25 +60,55 @@ protected static void Setup(ILogManager logManager)

protected EthereumTestResult RunTest(GeneralStateTest test)
{
return RunTest(test, NullTxTracer.Instance);
return RunTest(test, false, NullTxTracer.Instance);
}

protected EthereumTestResult RunTest(GeneralStateTest test, bool isGnosis)
{
if (isGnosis)
{
_txValidator = new TxValidator(GnosisSpecProvider.Instance.ChainId);
}

return RunTest(test, isGnosis, NullTxTracer.Instance);
}

protected EthereumTestResult RunTest(GeneralStateTest test, ITxTracer txTracer)
{
return RunTest(test, false, txTracer);
}

protected EthereumTestResult RunTest(GeneralStateTest test, bool isGnosis, ITxTracer txTracer)
{
TestContext.Write($"Running {test.Name} at {DateTime.UtcNow:HH:mm:ss.ffffff}");
Console.WriteLine("Passing over here");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Debug log?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed here

Assert.IsNull(test.LoadFailure, "test data loading failure");

IDb stateDb = new MemDb();
IDb codeDb = new MemDb();

ISpecProvider specProvider = new CustomSpecProvider(
((ForkActivation)0, Frontier.Instance), // TODO: this thing took a lot of time to find after it was removed!, genesis block is always initialized with Frontier
((ForkActivation)1, test.Fork));
ISpecProvider specProvider;
if (isGnosis)
{
specProvider = new CustomSpecProvider(
((ForkActivation)0,
GnosisSpecProvider.Instance
.GenesisSpec), // TODO: this thing took a lot of time to find after it was removed!, genesis block is always initialized with Frontier
((ForkActivation)1, test.Fork));
}
else
{
specProvider = new CustomSpecProvider(
((ForkActivation)0,
Frontier
.Instance), // TODO: this thing took a lot of time to find after it was removed!, genesis block is always initialized with Frontier
((ForkActivation)1, test.Fork));
}

if (specProvider.GenesisSpec != Frontier.Instance)
{
Assert.Fail("Expected genesis spec to be Frontier for blockchain tests");
}

IReleaseSpec? spec = specProvider.GetSpec((ForkActivation)test.CurrentNumber);

BlockHeader header = test.GetBlockHeader();
Expand All @@ -88,6 +118,7 @@ protected EthereumTestResult RunTest(GeneralStateTest test, ITxTracer txTracer)
{
test.CurrentBaseFee = header.BaseFeePerGas = CalculateBaseFeePerGas(test, parentHeader);
}

if (parentHeader != null)
{
header.ExcessBlobGas = BlobGasCalculator.CalculateExcessBlobGas(parentHeader, spec);
Expand Down Expand Up @@ -152,11 +183,14 @@ protected EthereumTestResult RunTest(GeneralStateTest test, ITxTracer txTracer)
compositeBlockTracer.Add(storageTxTracer);
if (test.IsTraceEnabled)
{
GethLikeBlockFileTracer gethLikeBlockFileTracer = new(block, test.GethTraceOptions, new FileSystem());
GethLikeBlockFileTracer gethLikeBlockFileTracer =
new(block, test.GethTraceOptions, new FileSystem());
compositeBlockTracer.Add(gethLikeBlockFileTracer);
}

blockReceiptsTracer.SetOtherTracer(compositeBlockTracer);
}

blockReceiptsTracer.StartNewBlockTrace(block);

if (!test.IsStateTest && test.ParentBeaconBlockRoot != null)
Expand All @@ -169,12 +203,14 @@ protected EthereumTestResult RunTest(GeneralStateTest test, ITxTracer txTracer)

foreach (var tx in test.Transactions)
{
bool isValid = _txValidator.IsWellFormed(tx, spec, out string error) && IsValidBlock(block, specProvider);
bool isValid = _txValidator.IsWellFormed(tx, spec, out string error) &&
IsValidBlock(block, specProvider);
if (isValid)
{
blockReceiptsTracer.StartNewTxTrace(tx);
TransactionResult transactionResult = transactionProcessor
.Execute(tx, new BlockExecutionContext(header), test.IsT8NTest ? blockReceiptsTracer : txTracer);
.Execute(tx, new BlockExecutionContext(header),
test.IsT8NTest ? blockReceiptsTracer : txTracer);
blockReceiptsTracer.EndTxTrace();

if (!test.IsT8NTest) continue;
Expand All @@ -189,16 +225,21 @@ protected EthereumTestResult RunTest(GeneralStateTest test, ITxTracer txTracer)
}
else if (transactionResult.Error != null)
{
transactionExecutionReport.RejectedTransactionReceipts.Add(new RejectedTx(txIndex, GethErrorMappings.GetErrorMapping(transactionResult.Error, tx.SenderAddress.ToString(true), tx.Nonce, stateProvider.GetNonce(tx.SenderAddress))));
transactionExecutionReport.RejectedTransactionReceipts.Add(new RejectedTx(txIndex,
GethErrorMappings.GetErrorMapping(transactionResult.Error, tx.SenderAddress.ToString(true),
tx.Nonce, stateProvider.GetNonce(tx.SenderAddress))));
stateProvider.Reset();
}

txIndex++;
}
else if (error != null)
{
transactionExecutionReport.RejectedTransactionReceipts.Add(new RejectedTx(txIndex, GethErrorMappings.GetErrorMapping(error)));
transactionExecutionReport.RejectedTransactionReceipts.Add(new RejectedTx(txIndex,
GethErrorMappings.GetErrorMapping(error)));
}
}

blockReceiptsTracer.EndBlockTrace();

stopwatch.Stop();
Expand All @@ -223,18 +264,21 @@ protected EthereumTestResult RunTest(GeneralStateTest test, ITxTracer txTracer)

if (test.IsT8NTest)
{
testResult.T8NResult = T8NResult.ConstructT8NResult(stateProvider, block, test, storageTxTracer, blockReceiptsTracer, specProvider, header, transactionExecutionReport);
testResult.T8NResult = T8NResult.ConstructT8NResult(stateProvider, block, test, storageTxTracer,
blockReceiptsTracer, specProvider, header, transactionExecutionReport);
}

return testResult;
}

private static IBlockhashProvider GetBlockHashProvider(GeneralStateTest test, BlockHeader header, BlockHeader? parent)
private static IBlockhashProvider GetBlockHashProvider(GeneralStateTest test, BlockHeader header,
BlockHeader? parent)
{
if (!test.IsT8NTest)
{
return new TestBlockhashProvider();
}

var t8NBlockHashProvider = new T8NBlockHashProvider();

if (header.Hash != null) t8NBlockHashProvider.Insert(header.Hash, header.Number);
Expand All @@ -243,6 +287,7 @@ private static IBlockhashProvider GetBlockHashProvider(GeneralStateTest test, Bl
{
t8NBlockHashProvider.Insert(blockHash.Value, long.Parse(blockHash.Key));
}

return t8NBlockHashProvider;
}

Expand All @@ -252,7 +297,8 @@ private static UInt256 CalculateBaseFeePerGas(GeneralStateTest test, BlockHeader
return test.IsT8NTest ? BaseFeeCalculator.Calculate(parentHeader, test.Fork) : _defaultBaseFeeForStateTest;
}

private static void InitializeTestPreState(Dictionary<Address, AccountState> pre, WorldState stateProvider, ISpecProvider specProvider)
private static void InitializeTestPreState(Dictionary<Address, AccountState> pre, WorldState stateProvider,
ISpecProvider specProvider)
{
foreach (KeyValuePair<Address, AccountState> accountState in pre)
{
Expand Down Expand Up @@ -285,15 +331,18 @@ private bool IsValidBlock(Block block, ISpecProvider specProvider)
.TestObject;

var difficultyCalculator = new EthashDifficultyCalculator(specProvider);
var sealer = new EthashSealValidator(_logManager, difficultyCalculator, new CryptoRandom(), new Ethash(_logManager), Timestamper.Default);
var sealer = new EthashSealValidator(_logManager, difficultyCalculator, new CryptoRandom(),
new Ethash(_logManager), Timestamper.Default);
IHeaderValidator headerValidator = new HeaderValidator(blockTree, sealer, specProvider, _logManager);
IUnclesValidator unclesValidator = new UnclesValidator(blockTree, headerValidator, _logManager);
IBlockValidator blockValidator = new BlockValidator(_txValidator, headerValidator, unclesValidator, specProvider, _logManager);
IBlockValidator blockValidator = new BlockValidator(_txValidator, headerValidator, unclesValidator,
specProvider, _logManager);

return blockValidator.ValidateOrphanedBlock(block, out _);
}

private static void CalculateReward(string? stateReward, bool isStateTest, Block block, WorldState stateProvider, IReleaseSpec spec)
private static void CalculateReward(string? stateReward, bool isStateTest, Block block,
WorldState stateProvider, IReleaseSpec spec)
{
if (stateReward == null || isStateTest) return;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,12 @@ public WithdrawalProcessor(IWorldState stateProvider, ILogManager logManager)
public void ProcessWithdrawals(Block block, IReleaseSpec spec)
{
if (!spec.WithdrawalsEnabled)
{
Console.WriteLine("Withdrawals not enabled");
return;
}

Console.WriteLine("Withdrawals enabled");

if (_logger.IsTrace) _logger.Trace($"Applying withdrawals for block {block}");

Expand Down
4 changes: 2 additions & 2 deletions src/Nethermind/Nethermind.Core/BlockchainIds.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public static string GetBlockchainName(ulong networkId)

public static class TestBlockchainIds
{
public const int NetworkId = 4261;
public const int ChainId = 1;
public const int NetworkId = 100;
public const int ChainId = 100;
}
}
2 changes: 1 addition & 1 deletion src/Nethermind/Nethermind.Specs/GnosisSpecProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public void UpdateMergeTransitionInfo(long? blockNumber, UInt256? terminalTotalD
public ForkActivation? MergeBlockNumber { get; private set; }
public ulong TimestampFork => ShanghaiTimestamp;
public UInt256? TerminalTotalDifficulty { get; private set; } = UInt256.Parse("8626000000000000000000058750000000000000000000");
public IReleaseSpec GenesisSpec => Byzantium.Instance;
public IReleaseSpec GenesisSpec => Cancun.Instance;
public long? DaoBlockNumber => null;
public ulong NetworkId => BlockchainIds.Gnosis;
public ulong ChainId => BlockchainIds.Gnosis;
Expand Down
2 changes: 2 additions & 0 deletions tools/evm/Evm.sln
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,6 @@ Global
{AAA9AF72-46AE-4535-9698-610C9E94AE06}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AAA9AF72-46AE-4535-9698-610C9E94AE06}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
EndGlobalSection
EndGlobal
3 changes: 3 additions & 0 deletions tools/evm/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ static void ConfigureT8NCommand(ref RootCommand rootCmd)
var traceOpt = new Option<bool>("--trace", description: "Configures the use of the JSON opcode tracer. This tracer emits traces to files as trace-<txIndex>-<txHash>.jsonl", getDefaultValue: () => false);
var traceNoStackOpt = new Option<bool>("--trace.noStack", description: "Trace no stack", getDefaultValue: () => false);
var traceReturnDataOpt = new Option<bool>("--trace.returnData", description: "Trace return data", getDefaultValue: () => false);
var isGnosisTests = new Option<bool>("--run.gnosis", description: "If set to true, will run under Gnosis spec", getDefaultValue: () => false);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just an idea for an improvement: instead of using a new --run.gnosis option maybe we can reuse --state.chainId and choose ISpecProvider based on chain / networkid? With such a way we will not need to add a new flag every time we have to add a new network to t8n.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea, removed --run.gnosis flag


var cmd = new Command("t8n", "EVM State Transition command")
{
Expand All @@ -53,6 +54,7 @@ static void ConfigureT8NCommand(ref RootCommand rootCmd)
traceMemoryOpt,
traceNoStackOpt,
traceReturnDataOpt,
isGnosisTests
};

cmd.AddAlias("transition");
Expand Down Expand Up @@ -86,6 +88,7 @@ await Task.Run(() =>
context.ParseResult.GetValueForOption(stateChainIdOpt),
context.ParseResult.GetValueForOption(stateForkOpt),
context.ParseResult.GetValueForOption(stateRewardOpt),
context.ParseResult.GetValueForOption(isGnosisTests),
traceOpts
);
Environment.ExitCode = output.ExitCode;
Expand Down
10 changes: 7 additions & 3 deletions tools/evm/T8NTool/InputProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using Nethermind.Evm.Tracing.GethStyle;
using Nethermind.Serialization.Json;
using Nethermind.Serialization.Rlp;
using Nethermind.Specs;
using Nethermind.Specs.Forks;
using Nethermind.Specs.Test;

Expand All @@ -23,14 +24,16 @@ public static GeneralStateTest ConvertToGeneralStateTest(string inputAlloc,
string stateFork,
string? stateReward,
ulong stateChainId,
bool isGnosis,
TraceOptions traceOptions)
{
GethTraceOptions gethTraceOptions = new GethTraceOptions
{
EnableMemory = traceOptions.Memory,
DisableStack = traceOptions.NoStack
};
Dictionary<Address, AccountState> allocJson = EthereumJsonSerializer.Deserialize<Dictionary<Address, AccountState>>(File.ReadAllText(inputAlloc));
Dictionary<Address, AccountState> allocJson =
EthereumJsonSerializer.Deserialize<Dictionary<Address, AccountState>>(File.ReadAllText(inputAlloc));
EnvInfo envInfo = EthereumJsonSerializer.Deserialize<EnvInfo>(File.ReadAllText(inputEnv));

Transaction[] transactions;
Expand Down Expand Up @@ -61,25 +64,26 @@ public static GeneralStateTest ConvertToGeneralStateTest(string inputAlloc,
throw new T8NException(e, ExitCodes.ErrorConfig);
}

ISpecProvider specProvider = new CustomSpecProvider(((ForkActivation)0, Frontier.Instance), ((ForkActivation)1, spec));
ISpecProvider specProvider = GnosisSpecProvider.Instance;
if (spec is Paris)
{
specProvider.UpdateMergeTransitionInfo(envInfo.CurrentNumber, 0);
}

envInfo.ApplyChecks(specProvider, spec);

GeneralStateTest generalStateTest = new();
generalStateTest.IsT8NTest = true;
generalStateTest.Fork = spec;
generalStateTest.Pre = allocJson;
generalStateTest.Transactions = transactions;
generalStateTest.StateChainId = isGnosis ? GnosisSpecProvider.Instance.ChainId : FrontierSpecProvider.Instance.ChainId;

generalStateTest.CurrentCoinbase = envInfo.CurrentCoinbase;
generalStateTest.CurrentGasLimit = envInfo.CurrentGasLimit;
generalStateTest.CurrentTimestamp = envInfo.CurrentTimestamp;
generalStateTest.CurrentNumber = envInfo.CurrentNumber;
generalStateTest.Withdrawals = envInfo.Withdrawals;
generalStateTest.Withdrawals = envInfo.Withdrawals;
generalStateTest.CurrentRandom = envInfo.GetCurrentRandomHash256();
generalStateTest.ParentTimestamp = envInfo.ParentTimestamp;
generalStateTest.ParentDifficulty = envInfo.ParentDifficulty;
Expand Down
16 changes: 13 additions & 3 deletions tools/evm/T8NTool/T8NTool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using Ethereum.Test.Base.T8NUtils;
using Evm.JsonTypes;
using Nethermind.Serialization.Json;
using Nethermind.Specs;

namespace Evm.T8NTool;

Expand All @@ -28,12 +29,18 @@ public T8NOutput Execute(
ulong stateChainId,
string stateFork,
string? stateReward,
bool isGnosis,
TraceOptions traceOptions)
{
T8NOutput t8NOutput = new();
try
{
var t8NExecutionResult = Execute(inputAlloc, inputEnv, inputTxs, stateFork, stateReward, stateChainId, traceOptions);
if (isGnosis)
{
stateChainId = GnosisSpecProvider.Instance.ChainId;
}
var t8NExecutionResult = Execute(inputAlloc, inputEnv, inputTxs, stateFork, stateReward, stateChainId,
isGnosis, traceOptions);

if (outputAlloc == "stdout") t8NOutput.Alloc = t8NExecutionResult.Alloc;
else if (outputAlloc != null) WriteToFile(outputAlloc, outputBasedir, t8NExecutionResult.Alloc);
Expand Down Expand Up @@ -72,6 +79,7 @@ public T8NOutput Execute(
Console.WriteLine(t8NOutput.ErrorMessage);
}
}

return t8NOutput;
}

Expand All @@ -82,11 +90,13 @@ private T8NExecutionResult Execute(
string stateFork,
string? stateReward,
ulong stateChainId,
bool isGnosis,
TraceOptions traceOptions)
{
var generalStateTest = InputProcessor.ConvertToGeneralStateTest(inputAlloc, inputEnv, inputTxs, stateFork, stateReward, stateChainId, traceOptions);
var generalStateTest = InputProcessor.ConvertToGeneralStateTest(inputAlloc, inputEnv, inputTxs, stateFork,
stateReward, stateChainId, isGnosis, traceOptions);

var res = RunTest(generalStateTest);
var res = RunTest(generalStateTest, isGnosis);

PostState postState = new PostState();
postState.StateRoot = res.StateRoot;
Expand Down
Loading