Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -176,9 +176,9 @@ protected override ContainerBuilder ConfigureContainer(ContainerBuilder builder,
ctx.Resolve<ITxPoolConfig>(),
ctx.Resolve<ITxValidator>(),
ctx.Resolve<ILogManager>(),
new XdcTransactionComparerProvider(SpecProvider, BlockTree).GetDefaultComparer(),
new XdcTransactionComparerProvider(ctx.Resolve<ISpecProvider>(), ctx.Resolve<IBlockTree>()).GetDefaultComparer(),
ctx.Resolve<ITxGossipPolicy>(),
new SignTransactionFilter(SnapshotManager, BlockTree, SpecProvider),
new SignTransactionFilter(ctx.Resolve<ISnapshotManager>(), ctx.Resolve<IBlockTree>(), ctx.Resolve<ISpecProvider>()),
ctx.Resolve<ITxValidator>()
);

Expand Down Expand Up @@ -453,15 +453,15 @@ public override async Task<Block> AddBlock(params Transaction[] transactions)

public override async Task<Block> AddBlockFromParent(BlockHeader parent, params Transaction[] transactions)
{
Block b = await base.AddBlockFromParent(parent, transactions);
Block b = await _fromContainer.TestBlockchainUtil.AddBlock(parent, TestBlockchainUtil.AddBlockFlags.DoNotWaitForHead | TestBlockchainUtil.AddBlockFlags.MayHaveExtraTx, CreateCancellationSource().Token, transactions);
CreateAndCommitQC((XdcBlockHeader)b.Header);

return b;
}

public async Task<Block> AddBlockWithoutCommitQc(params Transaction[] txs)
{
await base.AddBlock(txs);
await base.AddBlockMayHaveExtraTx(txs);
return BlockTree.Head!;
}

Expand Down
63 changes: 60 additions & 3 deletions src/Nethermind/Nethermind.Xdc/SignTransactionManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,37 @@
// SPDX-License-Identifier: LGPL-3.0-only


using Microsoft.Extensions.Logging;
using Nethermind.Blockchain;
using Nethermind.Consensus;
using Nethermind.Core;
using Nethermind.Core.Caching;
using Nethermind.Core.Crypto;
using Nethermind.Core.Extensions;
using Nethermind.Core.Specs;
using Nethermind.Crypto;
using Nethermind.Int256;
using Nethermind.Logging;
using Nethermind.TxPool;
using Nethermind.Xdc.Spec;
using Nethermind.Logging;
using Nethermind.Xdc.Types;
using System;
using System.Threading.Tasks;

namespace Nethermind.Xdc;

internal class SignTransactionManager(ISigner signer, ITxPool txPool, ILogger logger) : ISignTransactionManager
internal class SignTransactionManager(
ISigner signer,
ITxPool txPool,
IBlockTree blockTree,
ISnapshotManager snapshotManager,
ISpecProvider specProvider,
ILogManager logManager) : ISignTransactionManager, IStartable, IDisposable

Check failure on line 30 in src/Nethermind/Nethermind.Xdc/SignTransactionManager.cs

View workflow job for this annotation

GitHub Actions / Build (release, DocGen/DocGen.slnx)

The type or namespace name 'IStartable' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 30 in src/Nethermind/Nethermind.Xdc/SignTransactionManager.cs

View workflow job for this annotation

GitHub Actions / Build (release, DocGen/DocGen.slnx)

The type or namespace name 'IStartable' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 30 in src/Nethermind/Nethermind.Xdc/SignTransactionManager.cs

View workflow job for this annotation

GitHub Actions / Run Nethermind.Xdc.Test (windows-latest)

The type or namespace name 'IStartable' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 30 in src/Nethermind/Nethermind.Xdc/SignTransactionManager.cs

View workflow job for this annotation

GitHub Actions / Run Nethermind.Monitoring.Test (windows-latest)

The type or namespace name 'IStartable' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 30 in src/Nethermind/Nethermind.Xdc/SignTransactionManager.cs

View workflow job for this annotation

GitHub Actions / Run Nethermind.EthStats.Test (windows-latest)

The type or namespace name 'IStartable' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 30 in src/Nethermind/Nethermind.Xdc/SignTransactionManager.cs

View workflow job for this annotation

GitHub Actions / Run Nethermind.Api.Test (windows-latest)

The type or namespace name 'IStartable' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 30 in src/Nethermind/Nethermind.Xdc/SignTransactionManager.cs

View workflow job for this annotation

GitHub Actions / Run Nethermind.Merge.AuRa.Test (windows-latest)

The type or namespace name 'IStartable' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 30 in src/Nethermind/Nethermind.Xdc/SignTransactionManager.cs

View workflow job for this annotation

GitHub Actions / Run Nethermind.Hive.Test (windows-latest)

The type or namespace name 'IStartable' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 30 in src/Nethermind/Nethermind.Xdc/SignTransactionManager.cs

View workflow job for this annotation

GitHub Actions / Run Nethermind.Flashbots.Test (windows-latest)

The type or namespace name 'IStartable' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 30 in src/Nethermind/Nethermind.Xdc/SignTransactionManager.cs

View workflow job for this annotation

GitHub Actions / Run Nethermind.Merge.Plugin.Test (windows-latest)

The type or namespace name 'IStartable' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 30 in src/Nethermind/Nethermind.Xdc/SignTransactionManager.cs

View workflow job for this annotation

GitHub Actions / Run Nethermind.Shutter.Test (windows-latest)

The type or namespace name 'IStartable' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 30 in src/Nethermind/Nethermind.Xdc/SignTransactionManager.cs

View workflow job for this annotation

GitHub Actions / Run Nethermind.Clique.Test (windows-latest)

The type or namespace name 'IStartable' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 30 in src/Nethermind/Nethermind.Xdc/SignTransactionManager.cs

View workflow job for this annotation

GitHub Actions / Run Nethermind.Synchronization.Test (windows-latest)

The type or namespace name 'IStartable' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 30 in src/Nethermind/Nethermind.Xdc/SignTransactionManager.cs

View workflow job for this annotation

GitHub Actions / Run Nethermind.Runner.Test (windows-latest)

The type or namespace name 'IStartable' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 30 in src/Nethermind/Nethermind.Xdc/SignTransactionManager.cs

View workflow job for this annotation

GitHub Actions / Build (debug, Nethermind)

The type or namespace name 'IStartable' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 30 in src/Nethermind/Nethermind.Xdc/SignTransactionManager.cs

View workflow job for this annotation

GitHub Actions / Build (debug, Nethermind)

The type or namespace name 'IStartable' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 30 in src/Nethermind/Nethermind.Xdc/SignTransactionManager.cs

View workflow job for this annotation

GitHub Actions / Check code lint

The type or namespace name 'IStartable' could not be found (are you missing a using directive or an assembly reference?) [/home/runner/work/nethermind/nethermind/src/Nethermind/Nethermind.Xdc/Nethermind.Xdc.csproj]

Check failure on line 30 in src/Nethermind/Nethermind.Xdc/SignTransactionManager.cs

View workflow job for this annotation

GitHub Actions / Build (release, Nethermind)

The type or namespace name 'IStartable' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 30 in src/Nethermind/Nethermind.Xdc/SignTransactionManager.cs

View workflow job for this annotation

GitHub Actions / Build (release, Nethermind)

The type or namespace name 'IStartable' could not be found (are you missing a using directive or an assembly reference?)
{
private readonly AssociativeKeyCache<ValueHash256> _alreadySigned = new(128);
private Logging.ILogger _logger = logManager.GetClassLogger<SignTransactionManager>();
public void Start() => blockTree.BlockAddedToMain += OnBlockAddedToMain;

public async Task SubmitTransactionSign(XdcBlockHeader header, IXdcReleaseSpec spec)
{
UInt256 nonce = txPool.GetLatestPendingNonce(signer.Address);
Expand All @@ -29,10 +45,45 @@
AcceptTxResult added = txPool.SubmitTx(transaction, TxHandlingOptions.PersistentBroadcast);
if (!added)
{
logger.Warn($"Failed to add signed transaction to the pool: {added} {header.ToString(BlockHeader.Format.FullHashAndNumber)}");
_logger.Warn($"Failed to add signed transaction to the pool: {added} {header.ToString(BlockHeader.Format.FullHashAndNumber)}");
}
}

private void OnBlockAddedToMain(object? sender, BlockReplacementEventArgs e)
{
if (e.Block.Header is not XdcBlockHeader xdcHeader)
return;

if (e.Block.Hash is null || !blockTree.WasProcessed(e.Block.Number, e.Block.Hash) || blockTree.IsSyncing().isSyncing)
return;

if (_alreadySigned.Contains(xdcHeader.Hash))
return;

ulong round = xdcHeader.ExtraConsensusData.BlockRound;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Medium: potential NullReferenceException

ExtraConsensusData is not null-checked before accessing .BlockRound. XdcHotStuff.OnNewHeadBlock throws explicitly when it's null; this event handler would throw an unhandled exception from the blockchain core instead.

Suggested change
ulong round = xdcHeader.ExtraConsensusData.BlockRound;
if (xdcHeader.ExtraConsensusData is null)
return;
ulong round = xdcHeader.ExtraConsensusData.BlockRound;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

It is expected to be a xdc header

IXdcReleaseSpec spec = specProvider.GetXdcSpec(xdcHeader, round);
if (spec is null)
return;

if (xdcHeader.Number % spec.MergeSignRange != 0)
return;

Snapshot snapshot = snapshotManager.GetSnapshotByBlockNumber(xdcHeader.Number, spec);
if (snapshot is null)
return;

if (IsMasternode(snapshot, signer.Address))
{
_alreadySigned.Set(xdcHeader.Hash);
_ = SubmitTransactionSign(xdcHeader, spec)
.ContinueWith(t => _logger.Error("Failed to submit sign transaction", t.Exception),
TaskContinuationOptions.OnlyOnFaulted);
}
}

private static bool IsMasternode(Snapshot snapshot, Address signerAddress) =>
snapshot.NextEpochCandidates.AsSpan().IndexOf(signerAddress) != -1;

internal static Transaction CreateTxSign(UInt256 number, Hash256 hash, UInt256 nonce, Address blockSignersAddress, Address sender)
{
byte[] inputData = [.. XdcConstants.SignMethod, .. number.PaddedBytes(32), .. hash.Bytes.PadLeft(32)];
Expand All @@ -50,4 +101,10 @@

return transaction;
}

public void Dispose()
{
blockTree.BlockAddedToMain -= OnBlockAddedToMain;
GC.SuppressFinalize(this);
}
}
14 changes: 0 additions & 14 deletions src/Nethermind/Nethermind.Xdc/XdcHotStuff.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ internal class XdcHotStuff(
ISigner signer,
ITimeoutTimer timeoutTimer,
IProcessExitSource processExit,
ISignTransactionManager signTransactionManager,
ILogManager logManager) : IBlockProducerRunner
{
private readonly IBlockTree _blockTree = blockTree ?? throw new ArgumentNullException(nameof(blockTree));
Expand All @@ -48,7 +47,6 @@ internal class XdcHotStuff(
private readonly ITimeoutTimer _timeoutTimer = timeoutTimer;
private readonly IProcessExitSource _processExit = processExit;
private readonly ILogger _logger = logManager?.GetClassLogger<XdcHotStuff>() ?? throw new ArgumentNullException(nameof(logManager));
private readonly ISignTransactionManager _signTransactionManager = signTransactionManager ?? throw new ArgumentNullException(nameof(signTransactionManager));

private CancellationTokenSource? _cancellationTokenSource;
private Task? _runTask;
Expand All @@ -60,7 +58,6 @@ internal class XdcHotStuff(
private ulong _highestSelfMinedRound;
private ulong _highestVotedRound;
private bool _writeRoundInfo = true;
private long _highestSignTxNumber = 0;

/// <summary>
/// Starts the consensus runner.
Expand Down Expand Up @@ -233,17 +230,6 @@ internal async Task RunRoundChecks(CancellationToken ct)
Task blockBuilder = BuildAndProposeBlock(roundParent, currentRound, spec, ct);
}

if (_highestSignTxNumber < roundParent.Number
&& ((roundParent.Number % spec.MergeSignRange == 0)))
{
Snapshot snapshot = _snapshotManager.GetSnapshotByBlockNumber(roundParent.Number, spec);
if (snapshot is not null && snapshot.NextEpochCandidates.AsSpan().IndexOf(_signer.Address) != -1)
{
_highestSignTxNumber = roundParent.Number;
await _signTransactionManager.SubmitTransactionSign(roundParent, spec);
}
}

_writeRoundInfo = false;
}

Expand Down
4 changes: 2 additions & 2 deletions src/Nethermind/Nethermind.Xdc/XdcModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,6 @@ protected override void Load(ContainerBuilder builder)
.AddSingleton<IXdcConsensusContext, XdcConsensusContext>()
.AddDatabase(XdcRocksDbConfigFactory.XdcSnapshotDbName)
.AddSingleton<ISnapshotManager, IDb, IBlockTree, IMasternodeVotingContract, ISpecProvider>(CreateSnapshotManager)
.AddSingleton<ISignTransactionManager, ISigner, ITxPool, ILogManager>(CreateSignTransactionManager)
.AddSingleton<IPenaltyHandler, PenaltyHandler>()
.AddSingleton<ITimeoutTimer, TimeoutTimer>()
.AddSingleton<ISyncInfoManager, SyncInfoManager>()
Expand Down Expand Up @@ -130,10 +129,11 @@ protected override void Load(ContainerBuilder builder)
.AddSingleton<IGasLimitCalculator, XdcGasLimitCalculator>()
.AddSingleton<IDifficultyCalculator, XdcDifficultyCalculator>()
.AddScoped<IProducedBlockSuggester, XdcBlockSuggester>();

builder.RegisterType<SignTransactionManager>().As<IStartable>().SingleInstance();
}

private ISnapshotManager CreateSnapshotManager([KeyFilter(XdcRocksDbConfigFactory.XdcSnapshotDbName)] IDb db, IBlockTree blockTree, IMasternodeVotingContract votingContract, ISpecProvider specProvider) => new SnapshotManager(db, blockTree, votingContract, specProvider);
private ISignTransactionManager CreateSignTransactionManager(ISigner signer, ITxPool txPool, ILogManager logManager) => new SignTransactionManager(signer, txPool, logManager.GetClassLogger<SignTransactionManager>());

private IMasternodeVotingContract CreateVotingContract(
IAbiEncoder abiEncoder,
Expand Down
1 change: 0 additions & 1 deletion src/Nethermind/Nethermind.Xdc/XdcPlugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ public Task InitNetworkProtocol()
_nethermindApi.Context.Resolve<ISigner>(),
_nethermindApi.Context.Resolve<ITimeoutTimer>(),
_nethermindApi.ProcessExit,
_nethermindApi.Context.Resolve<ISignTransactionManager>(),
_nethermindApi.Context.Resolve<ILogManager>()
);
public IBlockProducer InitBlockProducer()
Expand Down
Loading