From a73925dcf3caaf85703b7ea02ac3f2d1166e45e7 Mon Sep 17 00:00:00 2001 From: s2quake Date: Tue, 10 Dec 2024 17:41:03 +0900 Subject: [PATCH] wip --- .../Blockchain/Policies/BlockPolicy.cs | 2 +- .../GeneratedBlockChainFixture.cs | 37 +++++++++--- .../Queries/EvidenceQueryTest.cs | 56 ++++++++++--------- .../Queries/EvidenceQuery.cs | 45 +++++++-------- .../Queries/ExplorerQuery.cs | 18 +++--- 5 files changed, 92 insertions(+), 66 deletions(-) diff --git a/src/Libplanet/Blockchain/Policies/BlockPolicy.cs b/src/Libplanet/Blockchain/Policies/BlockPolicy.cs index 63b1f24196a..5700b504eb3 100644 --- a/src/Libplanet/Blockchain/Policies/BlockPolicy.cs +++ b/src/Libplanet/Blockchain/Policies/BlockPolicy.cs @@ -160,7 +160,7 @@ public BlockPolicy( if (block.Evidence.Any(evidence => evidence.Height < evidenceExpirationHeight)) { return new InvalidBlockEvidencePendingDurationException( - $"Block #{block.Index} {block.Hash} includes evidence" + + $"Block #{block.Index} {block.Hash} includes evidence " + $"that is older than expiration height {evidenceExpirationHeight}"); } diff --git a/test/Libplanet.Explorer.Tests/GeneratedBlockChainFixture.cs b/test/Libplanet.Explorer.Tests/GeneratedBlockChainFixture.cs index 79487a95b6d..319a73be956 100644 --- a/test/Libplanet.Explorer.Tests/GeneratedBlockChainFixture.cs +++ b/test/Libplanet.Explorer.Tests/GeneratedBlockChainFixture.cs @@ -16,6 +16,7 @@ using Libplanet.Types.Tx; using Libplanet.Store; using Libplanet.Store.Trie; +using Libplanet.Tests.Blockchain.Evidence; namespace Libplanet.Explorer.Tests; @@ -29,6 +30,8 @@ public class GeneratedBlockChainFixture public int MaxTxCount { get; } + public int MaxEvidenceCount { get; } + public ImmutableDictionary> MinedBlocks { get; private set; } @@ -43,7 +46,8 @@ public GeneratedBlockChainFixture( int maxTxCount = 20, int privateKeyCount = 10, ImmutableArray>>? - txActionsForSuffixBlocks = null) + txActionsForSuffixBlocks = null, + int maxEvidenceCount = 2) { txActionsForSuffixBlocks ??= ImmutableArray>>.Empty; @@ -65,6 +69,7 @@ public GeneratedBlockChainFixture( .ToImmutableDictionary( key => key.Address, key => ImmutableArray.Empty); + MaxEvidenceCount = maxEvidenceCount; var privateKey = new PrivateKey(); var policy = new BlockPolicy( @@ -105,7 +110,7 @@ public GeneratedBlockChainFixture( while (Chain.Count < blockCount) { - AddBlock(GetRandomTransactions()); + AddBlock(GetRandomTransactions(), GetRandomEvidence(height: Chain.Count - 1)); } if (txActionsForSuffixBlocks is { } txActionsForSuffixBlocksVal) @@ -113,14 +118,16 @@ public GeneratedBlockChainFixture( foreach (var actionsForTransactions in txActionsForSuffixBlocksVal) { var pk = PrivateKeys[Random.Next(PrivateKeys.Length)]; - AddBlock(actionsForTransactions + var txs = actionsForTransactions .Select(actions => Transaction.Create( nonce: Chain.GetNextTxNonce(pk.Address), privateKey: pk, genesisHash: Chain.Genesis.Hash, actions: actions.ToPlainValues())) - .ToImmutableArray()); + .ToImmutableArray(); + var evs = ImmutableArray.Empty; + AddBlock(txs, evs); } } } @@ -159,6 +166,21 @@ private Transaction GetRandomTransaction(PrivateKey pk, long nonce) gasLimit: null); } + private ImmutableArray GetRandomEvidence(long height) + { + return Enumerable + .Range(0, Random.Next(MaxEvidenceCount)) + .Select(_ => + { + return new TestEvidence( + height: height, + validatorAddress: new PrivateKey().Address, + timestamp: DateTimeOffset.UtcNow); + }) + .OrderBy(ev => ev.Id) + .ToImmutableArray(); + } + private ImmutableArray GetRandomActions() { return Enumerable @@ -167,7 +189,8 @@ private ImmutableArray GetRandomActions() .ToImmutableArray(); } - private void AddBlock(ImmutableArray transactions) + private void AddBlock( + ImmutableArray transactions, ImmutableArray evidence) { var proposer = PrivateKeys[Random.Next(PrivateKeys.Length)]; var block = Chain.EvaluateAndSign( @@ -179,9 +202,9 @@ private void AddBlock(ImmutableArray transactions) Chain.Tip.Hash, BlockContent.DeriveTxHash(transactions), Chain.Store.GetChainBlockCommit(Chain.Store.GetCanonicalChainId()!.Value), - evidenceHash: null), + evidenceHash: BlockContent.DeriveEvidenceHash(evidence)), transactions, - evidence: Array.Empty()).Propose(), + evidence: evidence).Propose(), proposer); Chain.Append( block, diff --git a/test/Libplanet.Explorer.Tests/Queries/EvidenceQueryTest.cs b/test/Libplanet.Explorer.Tests/Queries/EvidenceQueryTest.cs index e15302b5950..9a53ee1efed 100644 --- a/test/Libplanet.Explorer.Tests/Queries/EvidenceQueryTest.cs +++ b/test/Libplanet.Explorer.Tests/Queries/EvidenceQueryTest.cs @@ -22,49 +22,55 @@ using static Libplanet.Explorer.Tests.GraphQLTestUtils; using Libplanet.Action.Loader; using Libplanet.Types.Evidence; +using Libplanet.Types.Blocks; namespace Libplanet.Explorer.Tests.Queries; public class EvidenceQueryTest { - protected readonly BlockChain Chain; - protected MockBlockChainContext Source; + private readonly GeneratedBlockChainFixture _fixture; + private readonly MockBlockChainContext _source; + private readonly EvidenceQuery _queryGraph; public EvidenceQueryTest() { - Chain = Libplanet.Tests.TestUtils.MakeBlockChain( - new BlockPolicy(), - new MemoryStore(), - new TrieStateStore(new MemoryKeyValueStore()), - new SingleActionLoader(typeof(NullAction)), - privateKey: new PrivateKey(), - timestamp: DateTimeOffset.UtcNow - ); - Source = new MockBlockChainContext(Chain); + _fixture = new GeneratedBlockChainFixture(seed: 0); + _source = new MockBlockChainContext(_fixture.Chain); + _queryGraph = new EvidenceQuery(); + var _ = new ExplorerQuery(_source); } [Fact] public async Task ExecuteAsync() { - var tx = Transaction.Create( - 0L, - new PrivateKey(), - Source.BlockChain.Genesis.Hash, - Enumerable.Empty().ToPlainValues() - ); - tx.MarshalUnsignedTx(); - ExecutionResult result = await ExecuteQueryAsync(@$" + var blocks = GetBlocks().ToArray(); + var block = blocks[System.Random.Shared.Next(blocks.Length)]; + + ExecutionResult result = await ExecuteQueryAsync(@$" {{ - bindSignature( - unsignedTransaction: ""{ByteUtil.Hex(tx.SerializeUnsignedTx())}"", - signature: ""{ByteUtil.Hex(tx.Signature)}"" - ) + committedEvidence( + offset: {block.Index} + ) {{ + id + }} }} - ", source: Source); + ", _queryGraph, source: _source); Assert.Null(result.Errors); ExecutionNode resultData = Assert.IsAssignableFrom(result.Data); IDictionary resultDict = Assert.IsAssignableFrom>(resultData!.ToValue()); - Assert.Equal(tx.Serialize(), ByteUtil.ParseHex((string)resultDict["bindSignature"])); + // Assert.Equal(tx.Serialize(), ByteUtil.ParseHex((string)resultDict["bindSignature"])); + } + + private IEnumerable GetBlocks() + { + for (var i = 0; i < _fixture.Chain.Count; i++) + { + var block = _fixture.Chain[i]; + if (block.Evidence.Count > 0) + { + yield return block; + } + } } } diff --git a/tools/Libplanet.Explorer/Queries/EvidenceQuery.cs b/tools/Libplanet.Explorer/Queries/EvidenceQuery.cs index 52aab4ea506..3f1977d51d4 100644 --- a/tools/Libplanet.Explorer/Queries/EvidenceQuery.cs +++ b/tools/Libplanet.Explorer/Queries/EvidenceQuery.cs @@ -20,35 +20,32 @@ public EvidenceQuery() Field>>>( "committedEvidence", arguments: new QueryArguments( - new QueryArgument - { - Name = "blockHash", - DefaultValue = null, - }, - new QueryArgument + new QueryArgument { Name = "hash" }, + new QueryArgument { Name = "index" } + ), + resolve: context => + { + string hash = context.GetArgument("hash"); + long? index = context.GetArgument("index", null); + + if (!(hash is null ^ index is null)) { - Name = "desc", - DefaultValue = false, - }, - new QueryArgument + throw new ExecutionError( + "The parameters hash and index are mutually exclusive; " + + "give only one at a time."); + } + + if (hash is { } nonNullHash) { - Name = "offset", - DefaultValue = 0, - }, - new QueryArgument + return ExplorerQuery.ListCommitEvidence(BlockHash.FromString(nonNullHash)); + } + + if (index is { } nonNullIndex) { - Name = "limit", - DefaultValue = MaxLimit, + return ExplorerQuery.ListCommitEvidence(nonNullIndex); } - ), - resolve: context => - { - var blockHash = context.GetArgument("blockHash"); - bool desc = context.GetArgument("desc"); - int offset = context.GetArgument("offset"); - int? limit = context.GetArgument("limit"); - return ExplorerQuery.ListCommitEvidence(blockHash, desc, offset, limit); + throw new ExecutionError("Unexpected block query"); } ); diff --git a/tools/Libplanet.Explorer/Queries/ExplorerQuery.cs b/tools/Libplanet.Explorer/Queries/ExplorerQuery.cs index c992ed71df3..d83245e9c6b 100644 --- a/tools/Libplanet.Explorer/Queries/ExplorerQuery.cs +++ b/tools/Libplanet.Explorer/Queries/ExplorerQuery.cs @@ -131,18 +131,18 @@ internal static IEnumerable ListPendingEvidence( return evidence; } - internal static IEnumerable ListCommitEvidence( - BlockHash? blockHash, bool desc, int offset, int? limit) + internal static IEnumerable ListCommitEvidence(BlockHash blockHash) { var blockChain = Chain; - var block = blockHash != null ? blockChain[blockHash.Value] : blockChain.Tip; - var comparer = desc ? EvidenceIdComparer.Descending : EvidenceIdComparer.Ascending; - var evidence = block.Evidence - .Skip(offset) - .Take(limit ?? int.MaxValue) - .OrderBy(ev => ev.Id, comparer); + var block = blockChain[blockHash]; + return block.Evidence; + } - return evidence; + internal static IEnumerable ListCommitEvidence(long index) + { + var blockChain = Chain; + var block = blockChain[index]; + return block.Evidence; } internal static Block? GetBlockByHash(BlockHash hash) => Store.GetBlock(hash);