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

Merge/continous block improvement #4488

Merged
merged 13 commits into from
Oct 4, 2022
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -32,41 +32,42 @@ private class DelayBlockImprovementContextFactory : IBlockImprovementContextFact
{
private readonly IManualBlockProductionTrigger _productionTrigger;
private readonly TimeSpan _timeout;
private readonly int _delay;
private readonly TimeSpan _delay;

public DelayBlockImprovementContextFactory(IManualBlockProductionTrigger productionTrigger, TimeSpan timeout, int delay)
public DelayBlockImprovementContextFactory(IManualBlockProductionTrigger productionTrigger, TimeSpan timeout, TimeSpan delay)
{
_productionTrigger = productionTrigger;
_timeout = timeout;
_delay = delay;
}

public IBlockImprovementContext StartBlockImprovementContext(Block currentBestBlock, BlockHeader parentHeader, PayloadAttributes payloadAttributes) =>
new DelayBlockImprovementContext(currentBestBlock, _productionTrigger, _timeout, parentHeader, payloadAttributes, _delay);
public IBlockImprovementContext StartBlockImprovementContext(Block currentBestBlock, BlockHeader parentHeader, PayloadAttributes payloadAttributes, DateTimeOffset startDateTime) =>
new DelayBlockImprovementContext(currentBestBlock, _productionTrigger, _timeout, parentHeader, payloadAttributes, _delay, startDateTime);
}

private class DelayBlockImprovementContext : IBlockImprovementContext
{
private CancellationTokenSource? _cancellationTokenSource;

public DelayBlockImprovementContext(
Block currentBestBlock,
public DelayBlockImprovementContext(Block currentBestBlock,
IManualBlockProductionTrigger blockProductionTrigger,
TimeSpan timeout,
BlockHeader parentHeader,
PayloadAttributes payloadAttributes,
int delay)
TimeSpan delay,
DateTimeOffset startDateTime)
{
_cancellationTokenSource = new CancellationTokenSource(timeout);
CurrentBestBlock = currentBestBlock;
StartDateTime = startDateTime;
ImprovementTask = BuildBlock(blockProductionTrigger, parentHeader, payloadAttributes, delay, _cancellationTokenSource.Token);
}

private async Task<Block?> BuildBlock(
IManualBlockProductionTrigger blockProductionTrigger,
BlockHeader parentHeader,
PayloadAttributes payloadAttributes,
int delay,
TimeSpan delay,
CancellationToken cancellationToken)
{
Block? block = await blockProductionTrigger.BuildBlock(parentHeader, cancellationToken, NullBlockTracer.Instance, payloadAttributes);
Expand All @@ -80,11 +81,13 @@ public DelayBlockImprovementContext(
}

public Task<Block?> ImprovementTask { get; }

public Block? CurrentBestBlock { get; private set; }
public bool Disposed { get; private set; }
public DateTimeOffset StartDateTime { get; }

public void Dispose()
{
Disposed = true;
CancellationTokenExtensions.CancelDisposeAndClear(ref _cancellationTokenSource);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
//
//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see <http://www.gnu.org/licenses/>.
//
//

using System;
using System.Collections.Generic;
Expand Down Expand Up @@ -59,12 +59,10 @@ private void AssertExecutionStatusChanged(IEngineRpcModule rpc, Keccak headBlock
private (UInt256, UInt256) AddTransactions(MergeTestBlockchain chain, ExecutionPayloadV1 executePayloadRequest,
PrivateKey from, Address to, uint count, int value, out BlockHeader parentHeader)
{
Transaction[] transactions = BuildTransactions(chain, executePayloadRequest.ParentHash, from, to, count, value,
out Account accountFrom, out parentHeader);
Transaction[] transactions = BuildTransactions(chain, executePayloadRequest.ParentHash, from, to, count, value, out Account accountFrom, out parentHeader);
executePayloadRequest.SetTransactions(transactions);
UInt256 totalValue = ((int)(count * value)).GWei();
return (accountFrom.Balance - totalValue,
chain.StateReader.GetBalance(parentHeader.StateRoot!, to) + totalValue);
return (accountFrom.Balance - totalValue, chain.StateReader.GetBalance(parentHeader.StateRoot!, to) + totalValue);
}

private Transaction[] BuildTransactions(MergeTestBlockchain chain, Keccak parentHash, PrivateKey from,
Expand All @@ -82,11 +80,10 @@ Transaction BuildTransaction(uint index, Account senderAccount) =>
.TestObject;

parentHeader = chain.BlockTree.FindHeader(parentHash, BlockTreeLookupOptions.None)!;
Account account = chain.StateReader.GetAccount(parentHeader.StateRoot!, @from.Address)!;
Account account = chain.StateReader.GetAccount(parentHeader.StateRoot!, from.Address)!;
accountFrom = account;

return Enumerable.Range(0, (int)count)
.Select(i => BuildTransaction((uint)i, account)).ToArray();
return Enumerable.Range(0, (int)count).Select(i => BuildTransaction((uint)i, account)).ToArray();
}

private ExecutionPayloadV1 CreateParentBlockRequestOnHead(IBlockTree blockTree)
Expand Down Expand Up @@ -141,8 +138,7 @@ private static ExecutionPayloadV1[] CreateBlockRequestBranch(ExecutionPayloadV1
private Block? RunForAllBlocksInBranch(IBlockTree blockTree, Keccak blockHash, Func<Block, bool> shouldStop,
bool requireCanonical)
{
BlockTreeLookupOptions options =
requireCanonical ? BlockTreeLookupOptions.RequireCanonical : BlockTreeLookupOptions.None;
BlockTreeLookupOptions options = requireCanonical ? BlockTreeLookupOptions.RequireCanonical : BlockTreeLookupOptions.None;
Block? current = blockTree.FindBlock(blockHash, options);
while (current is not null && !shouldStop(current))
{
Expand All @@ -160,8 +156,7 @@ private static TestCaseData GetNewBlockRequestBadDataTestCase<T>(
Action<ExecutionPayloadV1> wrongValueSetter = r => setter(r, wrongValue);
return new TestCaseData(wrongValueSetter)
{
TestName =
$"executePayload_rejects_incorrect_{propertyAccess.GetName().ToLower()}({wrongValue?.ToString()})"
TestName = $"executePayload_rejects_incorrect_{propertyAccess.GetName().ToLower()}({wrongValue?.ToString()})"
};
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see <http://www.gnu.org/licenses/>.
//

using System;
using System.Threading;
using System.Threading.Tasks;
using Nethermind.Consensus.Producers;
using Nethermind.Core;
using Nethermind.Core.Extensions;
using Nethermind.Evm.Tracing;
using Nethermind.Merge.Plugin.BlockProduction;

namespace Nethermind.Merge.Plugin.Test;

public partial class EngineModuleTests
{
private class MockBlockImprovementContextFactory : IBlockImprovementContextFactory
{
public IBlockImprovementContext StartBlockImprovementContext(Block currentBestBlock, BlockHeader parentHeader, PayloadAttributes payloadAttributes, DateTimeOffset startDateTime) =>
new MockBlockImprovementContext(currentBestBlock, startDateTime);
}

private class MockBlockImprovementContext : IBlockImprovementContext
{
public MockBlockImprovementContext(Block currentBestBlock, DateTimeOffset startDateTime)
{
CurrentBestBlock = currentBestBlock;
StartDateTime = startDateTime;
ImprovementTask = Task.FromResult((Block?)currentBestBlock);
}

public void Dispose() => Disposed = true;
public Task<Block?> ImprovementTask { get; }
public Block? CurrentBestBlock { get; }
public bool Disposed { get; private set; }
public DateTimeOffset StartDateTime { get; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Copyright (c) 2021 Demerzel Solutions Limited
// This file is part of the Nethermind library.
//
// The Nethermind library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The Nethermind library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the Nethermind. If not, see <http://www.gnu.org/licenses/>.
//

using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Nethermind.Consensus.Producers;
using Nethermind.Core;
using Nethermind.Core.Extensions;
using Nethermind.Evm.Tracing;
using Nethermind.Merge.Plugin.BlockProduction;

namespace Nethermind.Merge.Plugin.Test;

public partial class EngineModuleTests
{
private class StoringBlockImprovementContextFactory : IBlockImprovementContextFactory
{
private readonly IBlockImprovementContextFactory _blockImprovementContextFactory;
public IList<IBlockImprovementContext> CreatedContexts { get; } = new List<IBlockImprovementContext>();

public event EventHandler<ImprovementStartedEventArgs>? ImprovementStarted;

public StoringBlockImprovementContextFactory(IBlockImprovementContextFactory blockImprovementContextFactory)
{
_blockImprovementContextFactory = blockImprovementContextFactory;
}

public IBlockImprovementContext StartBlockImprovementContext(Block currentBestBlock, BlockHeader parentHeader, PayloadAttributes payloadAttributes, DateTimeOffset startDateTime)
{
IBlockImprovementContext blockImprovementContext = _blockImprovementContextFactory.StartBlockImprovementContext(currentBestBlock, parentHeader, payloadAttributes, startDateTime);
CreatedContexts.Add(blockImprovementContext);
Task.Run(() => ImprovementStarted?.Invoke(this, new ImprovementStartedEventArgs(blockImprovementContext)));
return blockImprovementContext;
}
}

private class ImprovementStartedEventArgs : EventArgs
{
public IBlockImprovementContext BlockImprovementContext { get; }

public ImprovementStartedEventArgs(IBlockImprovementContext blockImprovementContext)
{
BlockImprovementContext = blockImprovementContext;
}
}
}
Loading