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

Add clique_proposals & fix JSON Snapshot serialization #7478

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
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 @@ -67,8 +67,7 @@ private Snapshot GenerateSnapshot(Hash256 hash, long number, Address candidate)
tally[candidate].Votes = 2;
tally[_signer2] = new Tally(false);
tally[_signer2].Votes = 1;
Snapshot snapshot = new(number, hash, signers, tally);
snapshot.Votes = votes;
Snapshot snapshot = new(number, hash, signers, tally) { Votes = votes };
return snapshot;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ public void ProduceOnTopOf(Hash256 hash)
_signalsQueue.Add(_blockTree.FindBlock(hash, BlockTreeLookupOptions.None));
}

public IReadOnlyDictionary<Address, bool> GetProposals() => _blockProducer.Proposals.ToDictionary();

private void TimerOnElapsed(object sender, ElapsedEventArgs e)
{
try
Expand Down
74 changes: 25 additions & 49 deletions src/Nethermind/Nethermind.Consensus.Clique/CliqueRpcModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// SPDX-License-Identifier: LGPL-3.0-only

using System;
using System.Collections.Generic;
using System.Linq;
using Nethermind.Blockchain;
using Nethermind.Blockchain.Find;
Expand All @@ -11,50 +12,46 @@

namespace Nethermind.Consensus.Clique
{
public class CliqueRpcModule : ICliqueRpcModule
public class CliqueRpcModule(
ICliqueBlockProducerRunner? cliqueBlockProducer,
ISnapshotManager snapshotManager,
IBlockFinder blockTree)
: ICliqueRpcModule
{
private const string CannotVoteOnNonValidatorMessage = "Not a signer node - cannot vote";

private readonly ICliqueBlockProducerRunner? _cliqueBlockProducer;
private readonly ISnapshotManager _snapshotManager;
private readonly IBlockFinder _blockTree;

public CliqueRpcModule(ICliqueBlockProducerRunner? cliqueBlockProducer, ISnapshotManager snapshotManager, IBlockFinder blockTree)
{
_cliqueBlockProducer = cliqueBlockProducer;
_snapshotManager = snapshotManager ?? throw new ArgumentNullException(nameof(snapshotManager));
_blockTree = blockTree ?? throw new ArgumentNullException(nameof(blockTree));
}
private readonly ISnapshotManager _snapshotManager = snapshotManager ?? throw new ArgumentNullException(nameof(snapshotManager));
private readonly IBlockFinder _blockTree = blockTree ?? throw new ArgumentNullException(nameof(blockTree));

public bool ProduceBlock(Hash256 parentHash)
{
if (_cliqueBlockProducer is null)
if (cliqueBlockProducer is null)
{
return false;
}

_cliqueBlockProducer?.ProduceOnTopOf(parentHash);
cliqueBlockProducer?.ProduceOnTopOf(parentHash);
return true;
}

public void CastVote(Address signer, bool vote)
{
if (_cliqueBlockProducer is null)
if (cliqueBlockProducer is null)
{
throw new InvalidOperationException(CannotVoteOnNonValidatorMessage);
}

_cliqueBlockProducer.CastVote(signer, vote);
cliqueBlockProducer.CastVote(signer, vote);
}

public void UncastVote(Address signer)
{
if (_cliqueBlockProducer is null)
if (cliqueBlockProducer is null)
{
throw new InvalidOperationException(CannotVoteOnNonValidatorMessage);
}

_cliqueBlockProducer.UncastVote(signer);
cliqueBlockProducer.UncastVote(signer);
}

public Snapshot GetSnapshot()
Expand Down Expand Up @@ -103,45 +100,24 @@ public string[] GetSignersAnnotated(Hash256 hash)
.Select(s => string.Concat(s.Key, $" ({KnownAddresses.GetDescription(s.Key)})")).ToArray();
}

public ResultWrapper<bool> clique_produceBlock(Hash256 parentHash)
{
return ResultWrapper<bool>.Success(ProduceBlock(parentHash));
}
public ResultWrapper<bool> clique_produceBlock(Hash256 parentHash) => ResultWrapper<bool>.Success(ProduceBlock(parentHash));

public ResultWrapper<Snapshot> clique_getSnapshot()
{
return ResultWrapper<Snapshot>.Success(GetSnapshot());
}
public ResultWrapper<IReadOnlyDictionary<Address, bool>> clique_proposals() =>
ResultWrapper<IReadOnlyDictionary<Address, bool>>.Success(cliqueBlockProducer?.GetProposals() ?? new Dictionary<Address, bool>());

public ResultWrapper<Snapshot> clique_getSnapshotAtHash(Hash256 hash)
{
return ResultWrapper<Snapshot>.Success(GetSnapshot(hash));
}
public ResultWrapper<Snapshot> clique_getSnapshot() => ResultWrapper<Snapshot>.Success(GetSnapshot());

public ResultWrapper<Address[]> clique_getSigners()
{
return ResultWrapper<Address[]>.Success(GetSigners().ToArray());
}
public ResultWrapper<Snapshot> clique_getSnapshotAtHash(Hash256 hash) => ResultWrapper<Snapshot>.Success(GetSnapshot(hash));

public ResultWrapper<Address[]> clique_getSignersAtHash(Hash256 hash)
{
return ResultWrapper<Address[]>.Success(GetSigners(hash).ToArray());
}
public ResultWrapper<Address[]> clique_getSigners() => ResultWrapper<Address[]>.Success(GetSigners().ToArray());

public ResultWrapper<Address[]> clique_getSignersAtNumber(long number)
{
return ResultWrapper<Address[]>.Success(GetSigners(number).ToArray());
}
public ResultWrapper<Address[]> clique_getSignersAtHash(Hash256 hash) => ResultWrapper<Address[]>.Success(GetSigners(hash).ToArray());

public ResultWrapper<string[]> clique_getSignersAnnotated()
{
return ResultWrapper<string[]>.Success(GetSignersAnnotated().ToArray());
}
public ResultWrapper<Address[]> clique_getSignersAtNumber(long number) => ResultWrapper<Address[]>.Success(GetSigners(number).ToArray());

public ResultWrapper<string[]> clique_getSignersAtHashAnnotated(Hash256 hash)
{
return ResultWrapper<string[]>.Success(GetSignersAnnotated(hash).ToArray());
}
public ResultWrapper<string[]> clique_getSignersAnnotated() => ResultWrapper<string[]>.Success(GetSignersAnnotated().ToArray());

public ResultWrapper<string[]> clique_getSignersAtHashAnnotated(Hash256 hash) => ResultWrapper<string[]>.Success(GetSignersAnnotated(hash).ToArray());

public ResultWrapper<Address?> clique_getBlockSigner(Hash256? hash)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited
// SPDX-License-Identifier: LGPL-3.0-only

using System.Collections.Generic;
using Nethermind.Core;
using Nethermind.Core.Crypto;

Expand All @@ -11,5 +12,6 @@ public interface ICliqueBlockProducerRunner : IBlockProducerRunner
void CastVote(Address signer, bool vote);
void UncastVote(Address signer);
void ProduceOnTopOf(Hash256 hash);
IReadOnlyDictionary<Address, bool> GetProposals();
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// SPDX-FileCopyrightText: 2022 Demerzel Solutions Limited
// SPDX-License-Identifier: LGPL-3.0-only

using System.Collections.Generic;
using Nethermind.Core;
using Nethermind.Core.Crypto;
using Nethermind.JsonRpc;
Expand Down Expand Up @@ -43,5 +44,8 @@ public interface ICliqueRpcModule : IRpcModule

[JsonRpcMethod(Description = "Forces Clique block producer to produce a new block", IsImplemented = true)]
ResultWrapper<bool> clique_produceBlock(Hash256 parentHash);

[JsonRpcMethod(Description = "Retrieves the current proposals the node is voting on.", IsImplemented = true)]
ResultWrapper<IReadOnlyDictionary<Address, bool>> clique_proposals();
}
}
17 changes: 9 additions & 8 deletions src/Nethermind/Nethermind.Consensus.Clique/Snapshot.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ public class Snapshot : ICloneable
public long Number { get; set; }
public Hash256 Hash { get; set; }
public SortedList<Address, long> Signers { get; }

public List<Vote> Votes;
public List<Vote> Votes { get; init; }
internal Dictionary<Address, Tally> Tally { get; }

internal Snapshot(long number, Hash256 hash, SortedList<Address, long> signers, Dictionary<Address, Tally> tally)
Expand All @@ -31,12 +30,14 @@ internal Snapshot(long number, Hash256 hash, SortedList<Address, long> signers)
{
}

public object Clone()
{
Snapshot clone = new Snapshot(Number, Hash, new SortedList<Address, long>(Signers, AddressComparer.Instance), new Dictionary<Address, Tally>(Tally));
clone.Votes = new List<Vote>(Votes);
return clone;
}
public object Clone() =>
new Snapshot(Number,
Hash,
new SortedList<Address, long>(Signers, AddressComparer.Instance),
new Dictionary<Address, Tally>(Tally))
{
Votes = [.. Votes]
};

public long SignerLimit => Signers.Count / 2 + 1;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@ public Snapshot Decode(RlpStream rlpStream, RlpBehaviors rlpBehaviors = RlpBehav
List<Vote> votes = DecodeVotes(rlpStream);
// Tally
Dictionary<Address, Tally> tally = DecodeTally(rlpStream);
Snapshot snapshot = new Snapshot(number, hash, signers, tally);
snapshot.Votes = votes;
Snapshot snapshot = new(number, hash, signers, tally) { Votes = votes };

return snapshot;
}
Expand Down
15 changes: 15 additions & 0 deletions src/Nethermind/Nethermind.Core/AddressConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@
// SPDX-License-Identifier: LGPL-3.0-only

using System;
using System.Runtime.CompilerServices;
using System.Text.Json;
using System.Text.Json.Serialization;

using Nethermind.Core;
using Nethermind.Core.Extensions;

namespace Nethermind.Serialization.Json;

Expand All @@ -27,4 +29,17 @@ public override void Write(
{
ByteArrayConverter.Convert(writer, address.Bytes, skipLeadingZeros: false);
}

[SkipLocalsInit]
public override void WriteAsPropertyName(Utf8JsonWriter writer,
Address value,
JsonSerializerOptions options)
{
Span<byte> addressBytes = stackalloc byte[Address.Size * 2 + 2];
addressBytes[0] = (byte)'0';
addressBytes[1] = (byte)'x';
Span<byte> hex = addressBytes.Slice(2);
value.Bytes.AsSpan().OutputBytesToByteHex(hex, false);
writer.WritePropertyName(addressBytes);
}
}
2 changes: 1 addition & 1 deletion src/Nethermind/Nethermind.Core/ByteArrayConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ namespace Nethermind.Serialization.Json;

public class ByteArrayConverter : JsonConverter<byte[]>
{
private readonly static ushort _hexPrefix = MemoryMarshal.Cast<byte, ushort>("0x"u8)[0];
private static readonly ushort _hexPrefix = MemoryMarshal.Cast<byte, ushort>("0x"u8)[0];

public override byte[]? Read(
ref Utf8JsonReader reader,
Expand Down
4 changes: 2 additions & 2 deletions src/Nethermind/Nethermind.Core/Extensions/SpanExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public static string ToHexString(this in Span<byte> span, bool withZeroX, bool n
}

[DebuggerStepThrough]
private unsafe static string ToHexViaLookup(ReadOnlySpan<byte> bytes, bool withZeroX, bool skipLeadingZeros, bool withEip55Checksum)
private static unsafe string ToHexViaLookup(ReadOnlySpan<byte> bytes, bool withZeroX, bool skipLeadingZeros, bool withEip55Checksum)
{
if (withEip55Checksum)
{
Expand All @@ -82,7 +82,7 @@ private unsafe static string ToHexViaLookup(ReadOnlySpan<byte> bytes, bool withZ
}
}

unsafe readonly struct StringParams(byte* input, int inputLength, int leadingZeros, bool withZeroX)
readonly unsafe struct StringParams(byte* input, int inputLength, int leadingZeros, bool withZeroX)
{
private readonly byte* _input = input;
public readonly int InputLength = inputLength;
Expand Down