Skip to content

Commit

Permalink
Merge pull request planetarium#3855 from s2quake/feature/vote-power
Browse files Browse the repository at this point in the history
Add ValidatorPower property to Vote class
  • Loading branch information
s2quake authored Jul 4, 2024
2 parents 892b8ac + de87269 commit 6ff3c4f
Show file tree
Hide file tree
Showing 44 changed files with 711 additions and 143 deletions.
8 changes: 8 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ To be released.

### Backward-incompatible API changes

- (Libplanet.Explorer) Added `ValidatorPower` field to `VoteType`.
[[#3737], [#3813]]
- (Libplanet.Types) Added `ValidatorPower` property to `IVoteMetadata`
interface and its implementations. [[#3737], [#3813]]

### Backward-incompatible network protocol changes

### Backward-incompatible storage format changes
Expand All @@ -24,6 +29,9 @@ To be released.

### CLI tools

[#3737]: https://github.com/planetarium/libplanet/pull/3737
[#3813]: https://github.com/planetarium/libplanet/pull/3813


Version 5.0.0
-------------
Expand Down
1 change: 1 addition & 0 deletions src/Libplanet.Net/Consensus/Context.cs
Original file line number Diff line number Diff line change
Expand Up @@ -539,6 +539,7 @@ private Vote MakeVote(int round, BlockHash hash, VoteFlag flag)
hash,
DateTimeOffset.UtcNow,
_privateKey.PublicKey,
_validatorSet.GetValidator(_privateKey.PublicKey).Power,
flag).Sign(_privateKey);
}

Expand Down
8 changes: 8 additions & 0 deletions src/Libplanet.Net/Consensus/HeightVoteSet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,14 @@ public void AddVote(Vote vote)
vote);
}

if (vote.ValidatorPower is { } power &&
_validatorSet.GetValidator(validatorKey).Power != power)
{
const string msg = "ValidatorPower of the vote is given and the value is " +
"not the same with the one in the validator set";
throw new InvalidVoteException(msg, vote);
}

if (!vote.Flag.Equals(VoteFlag.PreVote) &&
!vote.Flag.Equals(VoteFlag.PreCommit))
{
Expand Down
1 change: 1 addition & 0 deletions src/Libplanet.Net/Consensus/VoteSet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,7 @@ public List<Vote> MappedList(long height, int round, ValidatorSet validatorSet)
BlockHash,
DateTimeOffset.UtcNow,
key,
validatorSet.GetValidator(key).Power,
VoteFlag.Null).Sign(null))
.ToList();
}
Expand Down
6 changes: 4 additions & 2 deletions src/Libplanet.Types/Blocks/BlockCommit.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,12 +93,14 @@ public BlockCommit(
vote.Height != height ||
vote.Round != round ||
!blockHash.Equals(vote.BlockHash) ||
(vote.Flag != VoteFlag.Null && vote.Flag != VoteFlag.PreCommit)))
(vote.Flag != VoteFlag.Null && vote.Flag != VoteFlag.PreCommit) ||
(vote.Flag == VoteFlag.PreCommit && !vote.Verify())))
{
throw new ArgumentException(
$"Every vote must have the same height as {height}, the same round " +
$"as {round}, the same hash as {blockHash}, and must have flag value of " +
$"either {VoteFlag.Null} or {VoteFlag.PreCommit}.",
$"either {VoteFlag.Null} or {VoteFlag.PreCommit}, " +
$"and must be signed if the vote's flag is {VoteFlag.PreCommit}.",
nameof(votes));
}

Expand Down
2 changes: 1 addition & 1 deletion src/Libplanet.Types/Blocks/PreEvaluationBlockHeader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ public ImmutableArray<byte> MakeSignature(
}
else if (!privateKey.PublicKey.Equals(PublicKey))
{
string m = "The given private key does not match to the miner's public key." +
string m = "The given private key does not match to the proposer's public key." +
$"Block's public key: {PublicKey}\n" +
$"Derived public key: {privateKey.PublicKey}\n";
throw new ArgumentException(m, nameof(privateKey));
Expand Down
6 changes: 6 additions & 0 deletions src/Libplanet.Types/Consensus/IVoteMetadata.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Numerics;
using Libplanet.Crypto;
using Libplanet.Types.Blocks;

Expand Down Expand Up @@ -35,6 +36,11 @@ public interface IVoteMetadata
/// </summary>
PublicKey ValidatorPublicKey { get; }

/// <summary>
/// The voting power of the validator that voted.
/// </summary>
BigInteger? ValidatorPower { get; }

/// <summary>
/// The <see cref="VoteFlag"/> indicating the type of a <see cref="Vote"/>.
/// </summary>
Expand Down
13 changes: 10 additions & 3 deletions src/Libplanet.Types/Consensus/ValidatorSet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -249,15 +249,22 @@ public Validator GetProposer(long height, int round)

/// <summary>
/// Checks whether <see cref="BlockCommit.Votes"/> is ordered
/// by <see cref="Address"/> of each <see cref="Vote.ValidatorPublicKey"/>.
/// by <see cref="Address"/> of each <see cref="Vote.ValidatorPublicKey"/>,
/// and <see cref="Vote.ValidatorPower"/> equals to the one recorded in the chain states.
/// </summary>
/// <remarks>
/// If <see cref="Vote.ValidatorPower"/> is null, power check is ignored.</remarks>
/// <param name="blockCommit">The <see cref="BlockCommit"/> to check.</param>
/// <returns><see langword="true"/> if the <see cref="BlockCommit.Votes"/> is
/// ordered, <see langword="false"/> otherwise.</returns>
public bool ValidateBlockCommitValidators(BlockCommit blockCommit)
{
return Validators.Select(validator => validator.PublicKey).SequenceEqual(
blockCommit.Votes.Select(vote => vote.ValidatorPublicKey).ToList());
return Validators.Select(validator => validator.PublicKey)
.SequenceEqual(
blockCommit.Votes.Select(vote => vote.ValidatorPublicKey).ToList()) &&
blockCommit.Votes.All(
v => v.ValidatorPower is null ||
v.ValidatorPower == GetValidator(v.ValidatorPublicKey).Power);
}
}
}
5 changes: 5 additions & 0 deletions src/Libplanet.Types/Consensus/Vote.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Diagnostics.Contracts;
using System.Globalization;
using System.Linq;
using System.Numerics;
using System.Text.Json;
using System.Text.Json.Serialization;
using Bencodex;
Expand Down Expand Up @@ -101,6 +102,9 @@ private Vote(Bencodex.Types.Dictionary encoded)
/// <inheritdoc/>
public PublicKey ValidatorPublicKey => _metadata.ValidatorPublicKey;

/// <inheritdoc/>
public BigInteger? ValidatorPower => _metadata.ValidatorPower;

/// <inheritdoc/>
public VoteFlag Flag => _metadata.Flag;

Expand Down Expand Up @@ -162,6 +166,7 @@ public override string ToString()
var dict = new Dictionary<string, object>
{
{ "validator_public_key", ValidatorPublicKey.ToString() },
{ "validator_power", ValidatorPower.ToString() },

Check warning on line 169 in src/Libplanet.Types/Consensus/Vote.cs

View workflow job for this annotation

GitHub Actions / check-build

Possible null reference argument for parameter 'value' in 'void Dictionary<string, object>.Add(string key, object value)'.

Check warning on line 169 in src/Libplanet.Types/Consensus/Vote.cs

View workflow job for this annotation

GitHub Actions / check-build

Possible null reference argument for parameter 'value' in 'void Dictionary<string, object>.Add(string key, object value)'.

Check warning on line 169 in src/Libplanet.Types/Consensus/Vote.cs

View workflow job for this annotation

GitHub Actions / build

Possible null reference argument for parameter 'value' in 'void Dictionary<string, object>.Add(string key, object value)'.

Check warning on line 169 in src/Libplanet.Types/Consensus/Vote.cs

View workflow job for this annotation

GitHub Actions / build

Possible null reference argument for parameter 'value' in 'void Dictionary<string, object>.Add(string key, object value)'.

Check warning on line 169 in src/Libplanet.Types/Consensus/Vote.cs

View workflow job for this annotation

GitHub Actions / build

Possible null reference argument for parameter 'value' in 'void Dictionary<string, object>.Add(string key, object value)'.
{ "vote_flag", Flag.ToString() },
{ "block_hash", BlockHash.ToString() },
{ "height", Height },
Expand Down
25 changes: 25 additions & 0 deletions src/Libplanet.Types/Consensus/VoteMetadata.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Immutable;
using System.Globalization;
using System.Numerics;
using System.Text.Json.Serialization;
using Bencodex;
using Bencodex.Types;
Expand Down Expand Up @@ -30,6 +31,9 @@ public class VoteMetadata : IVoteMetadata, IEquatable<VoteMetadata>, IBencodable
private static readonly Binary ValidatorPublicKeyKey =
new Binary(new byte[] { 0x50 }); // 'P'

private static readonly Binary ValidatorPowerKey =
new Binary(new byte[] { 0x70 }); // 'p'

private static readonly Binary FlagKey =
new Binary(new byte[] { 0x46 }); // 'F'

Expand All @@ -45,6 +49,7 @@ public class VoteMetadata : IVoteMetadata, IEquatable<VoteMetadata>, IBencodable
/// <param name="validatorPublicKey">
/// <see cref="PublicKey"/> of the validator made the vote.
/// </param>
/// <param name="validatorPower">The voting power of the validator.</param>
/// <param name="flag"><see cref="VoteFlag"/> for the vote's status.</param>
/// <exception cref="ArgumentException">Thrown for any of the following reasons:
/// <list type="bullet">
Expand All @@ -64,6 +69,7 @@ public VoteMetadata(
BlockHash blockHash,
DateTimeOffset timestamp,
PublicKey validatorPublicKey,
BigInteger? validatorPower,
VoteFlag flag)
{
if (height < 0)
Expand All @@ -76,6 +82,12 @@ public VoteMetadata(
throw new ArgumentException(
$"Given {nameof(round)} cannot be negative: {round}");
}
else if (validatorPower is { } power && power <= 0)
{
var msg = $"Given {nameof(validatorPower)} cannot be negative " +
$"or equal to zero: {validatorPower}";
throw new ArgumentException(msg);
}
else if (
blockHash.Equals(default) && (flag == VoteFlag.Null || flag == VoteFlag.Unknown))
{
Expand All @@ -89,6 +101,7 @@ public VoteMetadata(
BlockHash = blockHash;
Timestamp = timestamp;
ValidatorPublicKey = validatorPublicKey;
ValidatorPower = validatorPower;
Flag = flag;
}

Expand All @@ -114,6 +127,9 @@ private VoteMetadata(Bencodex.Types.Dictionary bencoded)
CultureInfo.InvariantCulture),
validatorPublicKey: new PublicKey(
((Binary)bencoded[ValidatorPublicKeyKey]).ByteArray),
validatorPower: bencoded.ContainsKey(ValidatorPowerKey)
? (Integer)bencoded[ValidatorPowerKey]
: (Integer?)null,
flag: (VoteFlag)(int)(Integer)bencoded[FlagKey])
{
}
Expand All @@ -134,6 +150,9 @@ private VoteMetadata(Bencodex.Types.Dictionary bencoded)
/// <inheritdoc/>
public PublicKey ValidatorPublicKey { get; }

/// <inheritdoc/>
public BigInteger? ValidatorPower { get; }

/// <inheritdoc/>
public VoteFlag Flag { get; }

Expand All @@ -157,6 +176,11 @@ public Bencodex.Types.IValue Bencoded
encoded = encoded.Add(BlockHashKey, blockHash.ByteArray);
}

if (ValidatorPower is { } power)
{
encoded = encoded.Add(ValidatorPowerKey, power);
}

return encoded;
}
}
Expand Down Expand Up @@ -189,6 +213,7 @@ public bool Equals(VoteMetadata? other)
TimestampFormat,
CultureInfo.InvariantCulture)) &&
ValidatorPublicKey.Equals(metadata.ValidatorPublicKey) &&
ValidatorPower == metadata.ValidatorPower &&
Flag == metadata.Flag;
}

Expand Down
2 changes: 2 additions & 0 deletions test/Libplanet.Explorer.Tests/GeneratedBlockChainFixture.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Immutable;
using System.Linq;
using System.Numerics;
using Bencodex.Types;
using Libplanet.Action;
using Libplanet.Action.Loader;
Expand Down Expand Up @@ -193,6 +194,7 @@ private void AddBlock(ImmutableArray<Transaction> transactions)
block.Hash,
DateTimeOffset.UtcNow,
pk.PublicKey,
BigInteger.One,
VoteFlag.PreCommit).Sign(pk)).ToImmutableArray()));
MinedBlocks = MinedBlocks
.SetItem(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Numerics;
using GraphQL;
using GraphQL.Types;
using GraphQL.Execution;
Expand Down Expand Up @@ -28,6 +29,7 @@ public async void Query()
blockHash,
DateTimeOffset.Now,
privateKey.PublicKey,
BigInteger.One,
VoteFlag.PreCommit).Sign(privateKey);
var blockCommit = new BlockCommit(1, 0, blockHash, ImmutableArray.Create(vote));

Expand Down
4 changes: 4 additions & 0 deletions test/Libplanet.Explorer.Tests/GraphTypes/BlockTypeTest.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Numerics;
using System.Security.Cryptography;
using GraphQL;
using GraphQL.Execution;
Expand Down Expand Up @@ -31,6 +32,7 @@ public async void Query()
lastBlockHash,
DateTimeOffset.Now,
privateKey.PublicKey,
BigInteger.One,
VoteFlag.PreCommit).Sign(privateKey));
var lastBlockCommit = new BlockCommit(1, 0, lastBlockHash, lastVotes);
var preEval = new BlockContent(
Expand Down Expand Up @@ -70,6 +72,7 @@ public async void Query()
blockHash
timestamp
validatorPublicKey
validatorPower
flag
signature
}
Expand Down Expand Up @@ -118,6 +121,7 @@ public async void Query()
{ "blockHash", lastVotes[0].BlockHash.ToString() },
{ "timestamp", new DateTimeOffsetGraphType().Serialize(lastVotes[0].Timestamp) },
{ "validatorPublicKey", lastVotes[0].ValidatorPublicKey.ToString() },
{ "validatorPower", lastVotes[0].ValidatorPower },
{ "flag", lastVotes[0].Flag.ToString() },
{ "signature", ByteUtil.Hex(lastVotes[0].Signature) },
}
Expand Down
4 changes: 4 additions & 0 deletions test/Libplanet.Explorer.Tests/GraphTypes/VoteTypeTest.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Numerics;
using GraphQL;
using GraphQL.Types;
using GraphQL.Execution;
Expand Down Expand Up @@ -27,6 +28,7 @@ public async void Query()
blockHash,
DateTimeOffset.Now,
privateKey.PublicKey,
123,
VoteFlag.PreCommit).Sign(privateKey);

var query =
Expand All @@ -36,6 +38,7 @@ public async void Query()
blockHash
timestamp
validatorPublicKey
validatorPower
flag
signature
}";
Expand All @@ -54,6 +57,7 @@ public async void Query()
Assert.Equal(vote.BlockHash.ToString(), resultData["blockHash"]);
Assert.Equal(new DateTimeOffsetGraphType().Serialize(vote.Timestamp), resultData["timestamp"]);
Assert.Equal(vote.ValidatorPublicKey.ToString(), resultData["validatorPublicKey"]);
Assert.Equal(vote.ValidatorPower, resultData["validatorPower"]);
Assert.Equal(vote.Flag.ToString(), resultData["flag"]);
Assert.Equal(ByteUtil.Hex(vote.Signature), resultData["signature"]);
}
Expand Down
2 changes: 2 additions & 0 deletions test/Libplanet.Explorer.Tests/Indexing/BlockChainIndexTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Numerics;
using System.Threading;
using System.Threading.Tasks;
using Libplanet.Crypto;
Expand Down Expand Up @@ -57,6 +58,7 @@ await index.SynchronizeAsync(
divergentBlock.Hash,
DateTimeOffset.UtcNow,
pk.PublicKey,
BigInteger.One,
VoteFlag.PreCommit)
.Sign(pk))
.ToImmutableArray()));
Expand Down
Loading

0 comments on commit 6ff3c4f

Please sign in to comment.