From 8bb9e6d7d44144aaede3ee2fc6d1126a4848bcea Mon Sep 17 00:00:00 2001 From: Say Cheong Date: Tue, 11 Jun 2024 15:52:16 +0900 Subject: [PATCH 1/8] Bump lib9c to 51faf090f --- Lib9c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib9c b/Lib9c index ea35b3a5e..51faf090f 160000 --- a/Lib9c +++ b/Lib9c @@ -1 +1 @@ -Subproject commit ea35b3a5eac201841340bfadaf68304e8586a0ff +Subproject commit 51faf090f8663f463ffef17c5ea839a9e4d4d2e6 From 2d77b84dd49dfd5eab19a6922dee53aedbecc222 Mon Sep 17 00:00:00 2001 From: Say Cheong Date: Wed, 29 May 2024 15:07:33 +0900 Subject: [PATCH 2/8] Fix program test --- .../ProgramTest.cs | 34 ++++++++++++++++--- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/NineChronicles.Headless.Executable.Tests/ProgramTest.cs b/NineChronicles.Headless.Executable.Tests/ProgramTest.cs index d6911139f..981dd506d 100644 --- a/NineChronicles.Headless.Executable.Tests/ProgramTest.cs +++ b/NineChronicles.Headless.Executable.Tests/ProgramTest.cs @@ -3,13 +3,22 @@ using System.Net; using System.Net.Http; using System.Net.Http.Headers; -using System.Text; using System.Threading; using System.Threading.Tasks; using Grpc.Core; +using Libplanet.Action; +using Libplanet.Action.Loader; +using Libplanet.Blockchain; +using Libplanet.Blockchain.Policies; +using Libplanet.Common; using Libplanet.Crypto; using Libplanet.Net; +using Libplanet.Store; +using Libplanet.Store.Trie; +using Libplanet.Types.Blocks; using MagicOnion.Client; +using Nekoyume.Action.Loader; +using Nekoyume.Blockchain.Policy; using Nekoyume.Shared.Services; using Xunit; @@ -22,14 +31,31 @@ public class ProgramTest private readonly string _storePath; private readonly ushort _rpcPort; private readonly ushort _graphqlPort; + private readonly string _genesisBlockHash; + private readonly byte[] _genesisEncoded; public ProgramTest() { var privateKey = new PrivateKey(); _apvString = AppProtocolVersion.Sign(privateKey, 1000).Token; - _genesisBlockPath = "https://release.nine-chronicles.com/genesis-block-9c-main"; _storePath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); + Directory.CreateDirectory(_storePath); + _genesisBlockPath = Path.Combine(_storePath, "./genesis"); + + IStateStore stateStore = new TrieStateStore(new MemoryKeyValueStore()); + IActionLoader actionLoader = new NCActionLoader(); + IBlockPolicy blockPolicy = new BlockPolicySource(actionLoader, 1).GetPolicy(Nekoyume.Planet.Odin); + IActionEvaluator actionEvaluator = new ActionEvaluator( + _ => blockPolicy.BlockAction, + stateStore: stateStore, + actionTypeLoader: actionLoader); + var genesis = BlockChain.ProposeGenesisBlock(actionEvaluator); + + Bencodex.Codec codec = new Bencodex.Codec(); + _genesisBlockHash = ByteUtil.Hex(genesis.Hash.ByteArray); + _genesisEncoded = codec.Encode(BlockMarshaler.MarshalBlock(genesis)); + File.WriteAllBytes(_genesisBlockPath, _genesisEncoded); _rpcPort = 41234; _graphqlPort = 41238; @@ -72,7 +98,7 @@ public async Task Run() var response = await client.PostAsync($"http://localhost:{_graphqlPort}/graphql", content); var responseString = await response.Content.ReadAsStringAsync(); Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.Contains("\"data\":{\"chainQuery\":{\"blockQuery\":{\"block\":{\"hash\":\"4582250d0da33b06779a8475d283d5dd210c683b9b999d74d03fac4f58fa6bce\"}}}}", responseString); + Assert.Contains($"\"data\":{{\"chainQuery\":{{\"blockQuery\":{{\"block\":{{\"hash\":\"{_genesisBlockHash}\"}}}}}}}}", responseString); var channel = new Channel( $"localhost:{_rpcPort}", @@ -87,7 +113,7 @@ public async Task Run() var service = MagicOnionClient.Create(channel, Array.Empty()) .WithCancellationToken(channel.ShutdownToken); - Assert.Equal(11085612, (await service.GetTip()).Length); + Assert.Equal(_genesisEncoded.Length, (await service.GetTip()).Length); } finally { From 04a46d12fab2c6226baab2bc6b00d963fb3d6095 Mon Sep 17 00:00:00 2001 From: ilgyu Date: Wed, 12 Jun 2024 15:53:29 +0900 Subject: [PATCH 3/8] bump: Lib9c --- Lib9c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib9c b/Lib9c index 51faf090f..e79375205 160000 --- a/Lib9c +++ b/Lib9c @@ -1 +1 @@ -Subproject commit 51faf090f8663f463ffef17c5ea839a9e4d4d2e6 +Subproject commit e7937520578e08c2dc80de9e0ad633095adbc8bf From b335050c969fb9542778470fe3a73f77a6212f76 Mon Sep 17 00:00:00 2001 From: ilgyu Date: Thu, 9 May 2024 09:38:28 +0900 Subject: [PATCH 4/8] feat: Adjust APIs from sloth bump --- .../Commands/StateCommand.cs | 19 ++++++++++-------- .../Store/AnonymousStore.cs | 20 +++++++++++++++++++ .../GraphTypes/StandaloneQuery.cs | 5 +++++ 3 files changed, 36 insertions(+), 8 deletions(-) diff --git a/NineChronicles.Headless.Executable/Commands/StateCommand.cs b/NineChronicles.Headless.Executable/Commands/StateCommand.cs index 9c7eba6dd..e7c8f963d 100644 --- a/NineChronicles.Headless.Executable/Commands/StateCommand.cs +++ b/NineChronicles.Headless.Executable/Commands/StateCommand.cs @@ -134,14 +134,17 @@ IStateStore stateStore block.Index, block.Hash ); - HashDigest stateRootHash = block.Index < 1 - ? BlockChain.DetermineGenesisStateRootHash( - actionEvaluator, - preEvalBlock, - out _) - : chain.DetermineBlockStateRootHash( - preEvalBlock, - out _); + HashDigest? refSrh = block.ProtocolVersion < BlockMetadata.SlothProtocolVersion + ? store.GetStateRootHash(block.PreviousHash) + : store.GetStateRootHash(block.Hash); + refSrh = refSrh is { } prevSrh + ? prevSrh + : MerkleTrie.EmptyRootHash; + + IReadOnlyList evals = actionEvaluator.Evaluate(block, refSrh); + HashDigest stateRootHash = evals.Count > 0 + ? evals[evals.Count - 1].OutputState + : (HashDigest)refSrh; DateTimeOffset now = DateTimeOffset.Now; if (invalidStateRootHashBlock is null && !stateRootHash.Equals(block.StateRootHash)) { diff --git a/NineChronicles.Headless.Executable/Store/AnonymousStore.cs b/NineChronicles.Headless.Executable/Store/AnonymousStore.cs index d19a4c82c..c703c9bc5 100644 --- a/NineChronicles.Headless.Executable/Store/AnonymousStore.cs +++ b/NineChronicles.Headless.Executable/Store/AnonymousStore.cs @@ -1,5 +1,7 @@ using System; using System.Collections.Generic; +using System.Security.Cryptography; +using Libplanet.Common; using Libplanet.Crypto; using Libplanet.Store; using Libplanet.Types.Blocks; @@ -47,6 +49,9 @@ public class AnonymousStore : IStore public Action PutBlockCommit { get; set; } public Action DeleteBlockCommit { get; set; } public Func> GetBlockCommitHashes { get; set; } + public Func?> GetNextStateRootHash { get; set; } + public Action> PutNextStateRootHash { get; set; } + public Action DeleteNextStateRootHash { get; set; } #pragma warning restore CS8618 void IDisposable.Dispose() @@ -237,4 +242,19 @@ IEnumerable IStore.GetBlockCommitHashes() { return GetBlockCommitHashes(); } + + HashDigest? IStore.GetNextStateRootHash(BlockHash blockHash) + { + return GetNextStateRootHash(blockHash); + } + + void IStore.PutNextStateRootHash(BlockHash blockHash, HashDigest nextStateRootHash) + { + PutNextStateRootHash(blockHash, nextStateRootHash); + } + + void IStore.DeleteNextStateRootHash(BlockHash blockHash) + { + DeleteNextStateRootHash(blockHash); + } } diff --git a/NineChronicles.Headless/GraphTypes/StandaloneQuery.cs b/NineChronicles.Headless/GraphTypes/StandaloneQuery.cs index 8598ecd4c..78a510371 100644 --- a/NineChronicles.Headless/GraphTypes/StandaloneQuery.cs +++ b/NineChronicles.Headless/GraphTypes/StandaloneQuery.cs @@ -67,6 +67,11 @@ public StandaloneQuery(StandaloneContext standaloneContext, IConfiguration confi return null; } + if (!(blockHash is { } hash)) + { + return null; + } + return new StateContext( chain.GetWorldState(blockHash), chain[blockHash].Index, From 2740f57413232a76d50ce0ea832656ecc9791f90 Mon Sep 17 00:00:00 2001 From: ilgyu Date: Thu, 9 May 2024 09:40:37 +0900 Subject: [PATCH 5/8] test: Test build fix from sloth --- .../Hosting/LibplanetNodeServiceTest.cs | 6 +--- .../Commands/ChainCommandTest.cs | 8 +---- .../ProgramTest.cs | 10 +----- .../Store/StoreExtensionsTest.cs | 6 +--- .../Commands/ReplayCommand.cs | 7 +++-- .../GraphQLTestUtils.cs | 5 ++- .../GraphTypes/GraphQLTestBase.cs | 6 ---- .../GraphTypes/StandaloneMutationTest.cs | 5 --- .../GraphTypes/StandaloneQueryTest.cs | 31 +------------------ .../GraphTypes/StandaloneSubscriptionTest.cs | 5 --- .../TransactionHeadlessQueryTest.cs | 1 - 11 files changed, 12 insertions(+), 78 deletions(-) diff --git a/Libplanet.Headless.Tests/Hosting/LibplanetNodeServiceTest.cs b/Libplanet.Headless.Tests/Hosting/LibplanetNodeServiceTest.cs index 6be8af511..5584fd748 100644 --- a/Libplanet.Headless.Tests/Hosting/LibplanetNodeServiceTest.cs +++ b/Libplanet.Headless.Tests/Hosting/LibplanetNodeServiceTest.cs @@ -30,11 +30,7 @@ public void Constructor() new MemoryStore(), stateStore); var actionLoader = new SingleActionLoader(typeof(DummyAction)); - var actionEvaluator = new ActionEvaluator( - _ => policy.BlockAction, - stateStore, - actionLoader); - var genesisBlock = BlockChain.ProposeGenesisBlock(actionEvaluator); + var genesisBlock = BlockChain.ProposeGenesisBlock(); var service = new LibplanetNodeService( new LibplanetNodeServiceProperties() { diff --git a/NineChronicles.Headless.Executable.Tests/Commands/ChainCommandTest.cs b/NineChronicles.Headless.Executable.Tests/Commands/ChainCommandTest.cs index 637bafecc..252930e5e 100644 --- a/NineChronicles.Headless.Executable.Tests/Commands/ChainCommandTest.cs +++ b/NineChronicles.Headless.Executable.Tests/Commands/ChainCommandTest.cs @@ -57,11 +57,7 @@ public ChainCommandTest() [InlineData(StoreType.RocksDb)] public void Tip(StoreType storeType) { - var actionEvaluator = new ActionEvaluator( - _ => new BlockPolicy().BlockAction, - new TrieStateStore(new MemoryKeyValueStore()), - new NCActionLoader()); - Block genesisBlock = BlockChain.ProposeGenesisBlock(actionEvaluator); + Block genesisBlock = BlockChain.ProposeGenesisBlock(); IStore store = storeType.CreateStore(_storePath); Guid chainId = Guid.NewGuid(); store.SetCanonicalChainId(chainId); @@ -96,7 +92,6 @@ public void Inspect(StoreType storeType) stateStore, new NCActionLoader()); Block genesisBlock = BlockChain.ProposeGenesisBlock( - actionEvaluator, transactions: new IAction[] { new Initialize( @@ -157,7 +152,6 @@ public void Truncate(StoreType storeType) stateStore, new NCActionLoader()); Block genesisBlock = BlockChain.ProposeGenesisBlock( - actionEvaluator, transactions: new IAction[] { new Initialize( diff --git a/NineChronicles.Headless.Executable.Tests/ProgramTest.cs b/NineChronicles.Headless.Executable.Tests/ProgramTest.cs index 981dd506d..022a21e11 100644 --- a/NineChronicles.Headless.Executable.Tests/ProgramTest.cs +++ b/NineChronicles.Headless.Executable.Tests/ProgramTest.cs @@ -42,15 +42,7 @@ public ProgramTest() _storePath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); Directory.CreateDirectory(_storePath); _genesisBlockPath = Path.Combine(_storePath, "./genesis"); - - IStateStore stateStore = new TrieStateStore(new MemoryKeyValueStore()); - IActionLoader actionLoader = new NCActionLoader(); - IBlockPolicy blockPolicy = new BlockPolicySource(actionLoader, 1).GetPolicy(Nekoyume.Planet.Odin); - IActionEvaluator actionEvaluator = new ActionEvaluator( - _ => blockPolicy.BlockAction, - stateStore: stateStore, - actionTypeLoader: actionLoader); - var genesis = BlockChain.ProposeGenesisBlock(actionEvaluator); + var genesis = BlockChain.ProposeGenesisBlock(); Bencodex.Codec codec = new Bencodex.Codec(); _genesisBlockHash = ByteUtil.Hex(genesis.Hash.ByteArray); diff --git a/NineChronicles.Headless.Executable.Tests/Store/StoreExtensionsTest.cs b/NineChronicles.Headless.Executable.Tests/Store/StoreExtensionsTest.cs index d5d77b991..0895e3ac1 100644 --- a/NineChronicles.Headless.Executable.Tests/Store/StoreExtensionsTest.cs +++ b/NineChronicles.Headless.Executable.Tests/Store/StoreExtensionsTest.cs @@ -28,11 +28,7 @@ public StoreExtensionsTest() public void GetGenesisBlock(StoreType storeType) { IStore store = storeType.CreateStore(_storePath); - IActionEvaluator actionEvaluator = new ActionEvaluator( - _ => new BlockPolicy().BlockAction, - new TrieStateStore(new MemoryKeyValueStore()), - new NCActionLoader()); - Block genesisBlock = BlockChain.ProposeGenesisBlock(actionEvaluator); + Block genesisBlock = BlockChain.ProposeGenesisBlock(); Guid chainId = Guid.NewGuid(); store.SetCanonicalChainId(chainId); store.PutBlock(genesisBlock); diff --git a/NineChronicles.Headless.Executable/Commands/ReplayCommand.cs b/NineChronicles.Headless.Executable/Commands/ReplayCommand.cs index 23caeadfa..d5a1f7a8d 100644 --- a/NineChronicles.Headless.Executable/Commands/ReplayCommand.cs +++ b/NineChronicles.Headless.Executable/Commands/ReplayCommand.cs @@ -249,6 +249,7 @@ public int Blocks( var currentBlockIndex = startIndex.Value; while (currentBlockIndex <= endIndex) { + var previousBlock = blockChain[currentBlockIndex]; var block = blockChain[currentBlockIndex++]; if (verbose) { @@ -270,7 +271,8 @@ public int Blocks( try { - var rootHash = blockChain.DetermineBlockStateRootHash(block, + var rootHash = blockChain.DetermineNextBlockStateRootHash( + previousBlock, out IReadOnlyList actionEvaluations); if (verbose) @@ -301,7 +303,8 @@ public int Blocks( outputSw?.WriteLine(msg); var actionEvaluator = GetActionEvaluator(stateStore); - var actionEvaluations = blockChain.DetermineBlockStateRootHash(block, + var actionEvaluations = blockChain.DetermineNextBlockStateRootHash( + previousBlock, out IReadOnlyList failedActionEvaluations); LoggingActionEvaluations(failedActionEvaluations, outputSw); diff --git a/NineChronicles.Headless.Tests/GraphQLTestUtils.cs b/NineChronicles.Headless.Tests/GraphQLTestUtils.cs index 58c7f7eab..9dabef0d8 100644 --- a/NineChronicles.Headless.Tests/GraphQLTestUtils.cs +++ b/NineChronicles.Headless.Tests/GraphQLTestUtils.cs @@ -86,7 +86,7 @@ public static StandaloneContext CreateStandaloneContext() _ => policy.BlockAction, stateStore, new NCActionLoader()); - var genesisBlock = BlockChain.ProposeGenesisBlock(actionEvaluator); + var genesisBlock = BlockChain.ProposeGenesisBlock(); var blockchain = BlockChain.Create( new BlockPolicy(), new VolatileStagePolicy(), @@ -118,7 +118,6 @@ PrivateKey minerPrivateKey stateStore, new NCActionLoader()); var genesisBlock = BlockChain.ProposeGenesisBlock( - actionEvaluator, transactions: ImmutableList.Empty.Add(Transaction.Create( 0, minerPrivateKey, null, new ActionBase[] { @@ -133,7 +132,7 @@ PrivateKey minerPrivateKey stateStore, genesisBlock, actionEvaluator); - var ncg = new GoldCurrencyState((Dictionary)blockchain.GetWorldState().GetLegacyState(Addresses.GoldCurrency)) + var ncg = new GoldCurrencyState((Dictionary)blockchain.GetNextWorldState().GetLegacyState(Addresses.GoldCurrency)) .Currency; var currencyFactory = new CurrencyFactory(() => blockchain.GetWorldState(blockchain.Tip.Hash), ncg); var fungibleAssetValueFactory = new FungibleAssetValueFactory(currencyFactory); diff --git a/NineChronicles.Headless.Tests/GraphTypes/GraphQLTestBase.cs b/NineChronicles.Headless.Tests/GraphTypes/GraphQLTestBase.cs index d7393fbf7..c13666aa6 100644 --- a/NineChronicles.Headless.Tests/GraphTypes/GraphQLTestBase.cs +++ b/NineChronicles.Headless.Tests/GraphTypes/GraphQLTestBase.cs @@ -55,13 +55,7 @@ public GraphQLTestBase(ITestOutputHelper output) #pragma warning restore CS0618 var sheets = TableSheetsImporter.ImportSheets(); - var blockAction = new RewardGold(); - var actionEvaluator = new ActionEvaluator( - _ => blockAction, - new TrieStateStore(new MemoryKeyValueStore()), - new NCActionLoader()); var genesisBlock = BlockChain.ProposeGenesisBlock( - actionEvaluator, transactions: ImmutableList.Empty.Add(Transaction.Create(0, AdminPrivateKey, null, new ActionBase[] { diff --git a/NineChronicles.Headless.Tests/GraphTypes/StandaloneMutationTest.cs b/NineChronicles.Headless.Tests/GraphTypes/StandaloneMutationTest.cs index c84b87421..cd4d9c7a3 100644 --- a/NineChronicles.Headless.Tests/GraphTypes/StandaloneMutationTest.cs +++ b/NineChronicles.Headless.Tests/GraphTypes/StandaloneMutationTest.cs @@ -919,12 +919,7 @@ private Block MakeGenesisBlock( IImmutableSet
activatedAccounts, RankingState0? rankingState = null) { - var actionEvaluator = new ActionEvaluator( - _ => ServiceBuilder.BlockPolicy.BlockAction, - new TrieStateStore(new MemoryKeyValueStore()), - new NCActionLoader()); return BlockChain.ProposeGenesisBlock( - actionEvaluator, transactions: ImmutableList.Empty.Add(Transaction.Create(0, AdminPrivateKey, null, new ActionBase[] { diff --git a/NineChronicles.Headless.Tests/GraphTypes/StandaloneQueryTest.cs b/NineChronicles.Headless.Tests/GraphTypes/StandaloneQueryTest.cs index 4de25b8f3..7a99619fc 100644 --- a/NineChronicles.Headless.Tests/GraphTypes/StandaloneQueryTest.cs +++ b/NineChronicles.Headless.Tests/GraphTypes/StandaloneQueryTest.cs @@ -119,11 +119,7 @@ public async Task NodeStatus() var apvPrivateKey = new PrivateKey(); var apv = AppProtocolVersion.Sign(apvPrivateKey, 0); - var actionEvaluator = new ActionEvaluator( - _ => null, - new TrieStateStore(new MemoryKeyValueStore()), - new NCActionLoader()); - var genesisBlock = BlockChain.ProposeGenesisBlock(actionEvaluator); + var genesisBlock = BlockChain.ProposeGenesisBlock(); // 에러로 인하여 NineChroniclesNodeService 를 사용할 수 없습니다. https://git.io/JfS0M // 따라서 LibplanetNodeService로 비슷한 환경을 맞춥니다. @@ -447,13 +443,8 @@ public async Task ActivationStatus(bool existsActivatedAccounts) { new Libplanet.Types.Consensus.Validator(ProposerPrivateKey.PublicKey, BigInteger.One), }.ToList()); - var actionEvaluator = new ActionEvaluator( - _ => null, - new TrieStateStore(new MemoryKeyValueStore()), - new NCActionLoader()); Block genesis = BlockChain.ProposeGenesisBlock( - actionEvaluator, transactions: ImmutableList.Empty .Add(Transaction.Create(0, ProposerPrivateKey, null, new ActionBase[] @@ -840,13 +831,8 @@ public async Task ActivationKeyNonce(bool trim) { pendingActivation, }; - var actionEvaluator = new ActionEvaluator( - _ => null, - new TrieStateStore(new MemoryKeyValueStore()), - new NCActionLoader()); Block genesis = BlockChain.ProposeGenesisBlock( - actionEvaluator, transactions: ImmutableList.Empty.Add( Transaction.Create(0, new PrivateKey(), null, new ActionBase[] @@ -925,13 +911,8 @@ public async Task ActivationKeyNonce_Throw_ExecutionError(string code, string ms var activatedAccounts = ImmutableHashSet
.Empty; var pendingActivationStates = new List(); - var actionEvaluator = new ActionEvaluator( - _ => null, - new TrieStateStore(new MemoryKeyValueStore()), - new NCActionLoader()); Block genesis = BlockChain.ProposeGenesisBlock( - actionEvaluator, transactions: ImmutableList.Empty .Add(Transaction.Create( 0, @@ -1006,13 +987,8 @@ public async Task Balance() var activatedAccounts = ImmutableHashSet
.Empty; var pendingActivationStates = new List(); - var actionEvaluator = new ActionEvaluator( - _ => null, - new TrieStateStore(new MemoryKeyValueStore()), - new NCActionLoader()); Block genesis = BlockChain.ProposeGenesisBlock( - actionEvaluator, transactions: ImmutableList.Empty.Add( Transaction.Create(0, new PrivateKey(), null, new ActionBase[] @@ -1111,13 +1087,8 @@ private NineChroniclesNodeService MakeNineChroniclesNodeService(PrivateKey priva new Libplanet.Types.Consensus.Validator(ProposerPrivateKey.PublicKey, BigInteger.One), new Libplanet.Types.Consensus.Validator(privateKey.PublicKey, BigInteger.One), }.ToList()); - var actionEvaluator = new ActionEvaluator( - _ => blockPolicy.BlockAction, - new TrieStateStore(new MemoryKeyValueStore()), - new NCActionLoader()); Block genesis = BlockChain.ProposeGenesisBlock( - actionEvaluator, transactions: ImmutableList.Empty .Add( Transaction.Create(0, ProposerPrivateKey, null, diff --git a/NineChronicles.Headless.Tests/GraphTypes/StandaloneSubscriptionTest.cs b/NineChronicles.Headless.Tests/GraphTypes/StandaloneSubscriptionTest.cs index 8c3fc52ea..91cde4e91 100644 --- a/NineChronicles.Headless.Tests/GraphTypes/StandaloneSubscriptionTest.cs +++ b/NineChronicles.Headless.Tests/GraphTypes/StandaloneSubscriptionTest.cs @@ -133,12 +133,7 @@ public async Task SubscribePreloadProgress() var apvPrivateKey = new PrivateKey(); var apv = AppProtocolVersion.Sign(apvPrivateKey, 0); - var actionEvaluator = new ActionEvaluator( - _ => null, - new TrieStateStore(new MemoryKeyValueStore()), - new SingleActionLoader(typeof(EmptyAction))); var genesisBlock = BlockChain.ProposeGenesisBlock( - actionEvaluator, transactions: new IAction[] { new Initialize( diff --git a/NineChronicles.Headless.Tests/GraphTypes/TransactionHeadlessQueryTest.cs b/NineChronicles.Headless.Tests/GraphTypes/TransactionHeadlessQueryTest.cs index 62e3d68bf..34ce0ce3b 100644 --- a/NineChronicles.Headless.Tests/GraphTypes/TransactionHeadlessQueryTest.cs +++ b/NineChronicles.Headless.Tests/GraphTypes/TransactionHeadlessQueryTest.cs @@ -49,7 +49,6 @@ public TransactionHeadlessQueryTest() _stateStore, new NCActionLoader()); Block genesisBlock = BlockChain.ProposeGenesisBlock( - actionEvaluator, transactions: new IAction[] { new Initialize( From 04f6d9c720c1c9f7d93813d0b5a753166ed618a7 Mon Sep 17 00:00:00 2001 From: ilgyu Date: Fri, 10 May 2024 14:11:38 +0900 Subject: [PATCH 6/8] test: Update tests to use state of next block --- .../Commands/AccountCommandTest.cs | 1 + .../Commands/GenesisHelper.cs | 18 +++++ .../Commands/ChainCommand.cs | 2 + .../GraphQLTestUtils.cs | 62 +++++++++++++--- .../GraphTypes/ActionQueryTest.cs | 5 +- .../GraphTypes/AddressQueryTest.cs | 8 +-- .../GraphTypes/GraphQLTestBase.cs | 7 ++ .../GraphTypes/StandaloneMutationTest.cs | 22 +++--- .../GraphTypes/StandaloneQueryTest.cs | 72 ++++++++++++------- .../GraphTypes/WorldBossScenarioTest.cs | 5 +- 10 files changed, 146 insertions(+), 56 deletions(-) diff --git a/NineChronicles.Headless.Executable.Tests/Commands/AccountCommandTest.cs b/NineChronicles.Headless.Executable.Tests/Commands/AccountCommandTest.cs index e21a38c07..be3194fd1 100644 --- a/NineChronicles.Headless.Executable.Tests/Commands/AccountCommandTest.cs +++ b/NineChronicles.Headless.Executable.Tests/Commands/AccountCommandTest.cs @@ -58,6 +58,7 @@ public void Balance(StoreType storeType) stateStore, genesisBlock, actionEvaluator); + GenesisHelper.AppendEmptyBlock(chain); Guid chainId = chain.Id; store.Dispose(); stateStore.Dispose(); diff --git a/NineChronicles.Headless.Executable.Tests/Commands/GenesisHelper.cs b/NineChronicles.Headless.Executable.Tests/Commands/GenesisHelper.cs index 567aed4a7..97be5dc34 100644 --- a/NineChronicles.Headless.Executable.Tests/Commands/GenesisHelper.cs +++ b/NineChronicles.Headless.Executable.Tests/Commands/GenesisHelper.cs @@ -5,13 +5,16 @@ using System.Linq; using System.Numerics; using System.Text.Json; +using Libplanet.Blockchain; using Libplanet.Common; using Libplanet.Crypto; using Libplanet.Types.Blocks; +using Libplanet.Types.Consensus; using Nekoyume; using Nekoyume.Action; using Nekoyume.Model; using Nekoyume.Model.State; +using static Humanizer.In; using Lib9cUtils = Lib9c.DevExtensions.Utils; namespace NineChronicles.Headless.Executable.Tests.Commands @@ -96,6 +99,21 @@ public static Block MineGenesisBlock( return genesisBlock; } + public static void AppendEmptyBlock(BlockChain blockChain) + { + var lastHeight = blockChain.Tip.Index; + var block = blockChain.ProposeBlock(ValidatorKey, blockChain.GetBlockCommit(lastHeight)); + var blockCommit = new BlockCommit( + block.Index, + 0, + block.Hash, + new[] + { + new VoteMetadata(block.Index, 0, block.Hash, block.Timestamp, ValidatorKey.PublicKey, VoteFlag.PreCommit).Sign(ValidatorKey), + }.ToImmutableArray()); + blockChain.Append(block, blockCommit); + } + [Serializable] private struct AuthorizedMinerConfig { diff --git a/NineChronicles.Headless.Executable/Commands/ChainCommand.cs b/NineChronicles.Headless.Executable/Commands/ChainCommand.cs index 00c25e717..0eed89f37 100644 --- a/NineChronicles.Headless.Executable/Commands/ChainCommand.cs +++ b/NineChronicles.Headless.Executable/Commands/ChainCommand.cs @@ -37,9 +37,11 @@ public class ChainCommand : CoconaLiteConsoleAppBase public enum SnapshotType { +#pragma warning disable SA1602 // Enumeration items should be documented Full, Partition, All +#pragma warning restore SA1602 // Enumeration items should be documented } public ChainCommand(IConsole console) diff --git a/NineChronicles.Headless.Tests/GraphQLTestUtils.cs b/NineChronicles.Headless.Tests/GraphQLTestUtils.cs index 9dabef0d8..9ef27e239 100644 --- a/NineChronicles.Headless.Tests/GraphQLTestUtils.cs +++ b/NineChronicles.Headless.Tests/GraphQLTestUtils.cs @@ -1,17 +1,22 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; +using System.Linq; +using System.Numerics; using System.Threading.Tasks; using Bencodex.Types; using GraphQL; using GraphQL.Types; using Libplanet.Action; using Libplanet.Action.Loader; +using Libplanet.Action.Sys; using Libplanet.Blockchain; using Libplanet.Blockchain.Policies; using Libplanet.Crypto; using Libplanet.Store; using Libplanet.Store.Trie; +using Libplanet.Types.Blocks; +using Libplanet.Types.Consensus; using Libplanet.Types.Tx; using Microsoft.Extensions.DependencyInjection; using Nekoyume; @@ -26,6 +31,19 @@ namespace NineChronicles.Headless.Tests public static class GraphQLTestUtils { private static readonly IActionLoader _actionLoader = new NCActionLoader(); + private static readonly List ValidatorPrivateKeys = new List + { + PrivateKey.FromString( + "e5792a1518d9c7f7ecc35cd352899211a05164c9dde059c9811e0654860549ef"), + PrivateKey.FromString( + "91d61834be824c952754510fcf545180eca38e036d3d9b66564f0667b30d5b93"), + PrivateKey.FromString( + "b17c919b07320edfb3e6da2f1cfed75910322de2e49377d6d4d226505afca550"), + PrivateKey.FromString( + "91602d7091c5c7837ac8e71a8d6b1ed1355cfe311914d9a76107899add0ad56a"), + }; + + public static PrivateKey MinerPrivateKey => ValidatorPrivateKeys.First(); public static Task ExecuteQueryAsync( string query, @@ -106,8 +124,7 @@ public static StandaloneContext CreateStandaloneContext() } public static StandaloneContext CreateStandaloneContext( - InitializeStates initializeStates, - PrivateKey minerPrivateKey + InitializeStates initializeStates ) { var store = new DefaultStore(null); @@ -118,12 +135,29 @@ PrivateKey minerPrivateKey stateStore, new NCActionLoader()); var genesisBlock = BlockChain.ProposeGenesisBlock( - transactions: ImmutableList.Empty.Add(Transaction.Create( - 0, minerPrivateKey, null, new ActionBase[] - { - initializeStates, - }.ToPlainValues())), - privateKey: minerPrivateKey + transactions: ImmutableList.Empty + .Add( + Transaction.Create( + 0, MinerPrivateKey, + null, + new IAction[] + { + new Initialize( + new ValidatorSet( + ValidatorPrivateKeys.Select( + v => new Validator(v.PublicKey, BigInteger.One)).ToList()), + ImmutableDictionary.Create()) + }.Select(a => a.PlainValue))) + .Add( + Transaction.Create( + 1, + MinerPrivateKey, + null, + new ActionBase[] + { + initializeStates, + }.ToPlainValues())), + privateKey: MinerPrivateKey ); var blockchain = BlockChain.Create( new BlockPolicy(), @@ -132,7 +166,17 @@ PrivateKey minerPrivateKey stateStore, genesisBlock, actionEvaluator); - var ncg = new GoldCurrencyState((Dictionary)blockchain.GetNextWorldState().GetLegacyState(Addresses.GoldCurrency)) + var block = blockchain.ProposeBlock(MinerPrivateKey, null); + var blockCommit = new BlockCommit( + block.Index, + 0, + block.Hash, + ValidatorPrivateKeys.Select( + k => new VoteMetadata(block.Index, 0, block.Hash, block.Timestamp, k.PublicKey, VoteFlag.PreCommit).Sign(k)) + .ToImmutableArray()); + + blockchain.Append(block, blockCommit); + var ncg = new GoldCurrencyState((Dictionary)blockchain.GetWorldState().GetLegacyState(Addresses.GoldCurrency)) .Currency; var currencyFactory = new CurrencyFactory(() => blockchain.GetWorldState(blockchain.Tip.Hash), ncg); var fungibleAssetValueFactory = new FungibleAssetValueFactory(currencyFactory); diff --git a/NineChronicles.Headless.Tests/GraphTypes/ActionQueryTest.cs b/NineChronicles.Headless.Tests/GraphTypes/ActionQueryTest.cs index 45a5ccce9..1ab0f3719 100644 --- a/NineChronicles.Headless.Tests/GraphTypes/ActionQueryTest.cs +++ b/NineChronicles.Headless.Tests/GraphTypes/ActionQueryTest.cs @@ -44,7 +44,6 @@ public ActionQueryTest() _nonce = new byte[16]; new Random().NextBytes(_nonce); (_activationKey, PendingActivationState pending) = ActivationKey.Create(_activationCodeSeed, _nonce); - var minerPrivateKey = new PrivateKey(); var initializeStates = new InitializeStates( rankingState: new RankingState0(), shopState: new ShopState(), @@ -57,13 +56,13 @@ public ActionQueryTest() activatedAccountsState: new ActivatedAccountsState(), #pragma warning disable CS0618 // Use of obsolete method Currency.Legacy(): https://github.com/planetarium/lib9c/discussions/1319 - goldCurrencyState: new GoldCurrencyState(Currency.Legacy("NCG", 2, minerPrivateKey.Address)), + goldCurrencyState: new GoldCurrencyState(Currency.Legacy("NCG", 2, MinerPrivateKey.Address)), #pragma warning restore CS0618 goldDistributions: Array.Empty(), tableSheets: new Dictionary(), pendingActivationStates: new[] { pending } ); - _standaloneContext = CreateStandaloneContext(initializeStates, minerPrivateKey); + _standaloneContext = CreateStandaloneContext(initializeStates); } [Theory] diff --git a/NineChronicles.Headless.Tests/GraphTypes/AddressQueryTest.cs b/NineChronicles.Headless.Tests/GraphTypes/AddressQueryTest.cs index fad1668b6..03c3db385 100644 --- a/NineChronicles.Headless.Tests/GraphTypes/AddressQueryTest.cs +++ b/NineChronicles.Headless.Tests/GraphTypes/AddressQueryTest.cs @@ -15,13 +15,11 @@ namespace NineChronicles.Headless.Tests.GraphTypes { public class AddressQueryTest { - private const string MinerPrivateKeyHex = "b8ce43967d7270348906c3b30efd41c30ab834ce07a36ee8ac5fd52cb7a3f579"; - private const string NcgMinterAddress = "0x055D75489A163a5Ee9D2744e52dae1F598CA1817"; + private const string NcgMinterAddress = "0x1c54b2F83D26E2db2D93dE4539c301d8aE32E69d"; private readonly StandaloneContext _standaloneContext; public AddressQueryTest() { - var minerPrivateKey = new PrivateKey(MinerPrivateKeyHex); var initializeStates = new InitializeStates( rankingState: new RankingState0(), shopState: new ShopState(), @@ -35,13 +33,13 @@ public AddressQueryTest() #pragma warning disable CS0618 // Use of obsolete method Currency.Legacy(): https://github.com/planetarium/lib9c/discussions/1319 goldCurrencyState: - new GoldCurrencyState(Currency.Legacy("NCG", 2, minerPrivateKey.Address)), + new GoldCurrencyState(Currency.Legacy("NCG", 2, MinerPrivateKey.Address)), #pragma warning restore CS0618 goldDistributions: Array.Empty(), tableSheets: new Dictionary(), pendingActivationStates: new PendingActivationState[] { } ); - _standaloneContext = CreateStandaloneContext(initializeStates, minerPrivateKey); + _standaloneContext = CreateStandaloneContext(initializeStates); } [Theory] diff --git a/NineChronicles.Headless.Tests/GraphTypes/GraphQLTestBase.cs b/NineChronicles.Headless.Tests/GraphTypes/GraphQLTestBase.cs index c13666aa6..fe63fda43 100644 --- a/NineChronicles.Headless.Tests/GraphTypes/GraphQLTestBase.cs +++ b/NineChronicles.Headless.Tests/GraphTypes/GraphQLTestBase.cs @@ -247,5 +247,12 @@ protected LibplanetNodeService CreateLibplanetNodeService( VoteFlag.PreCommit).Sign(validator)).ToImmutableArray()) : (BlockCommit?)null; } + + public void AppendEmptyBlock(IEnumerable validators) + { + var block = BlockChain.ProposeBlock(ProposerPrivateKey, BlockChain.GetBlockCommit(BlockChain.Tip.Index)); + var blockCommit = GenerateBlockCommit(block.Index, block.Hash, validators.ToList()); + BlockChain.Append(block, blockCommit); + } } } diff --git a/NineChronicles.Headless.Tests/GraphTypes/StandaloneMutationTest.cs b/NineChronicles.Headless.Tests/GraphTypes/StandaloneMutationTest.cs index cd4d9c7a3..1cd0808af 100644 --- a/NineChronicles.Headless.Tests/GraphTypes/StandaloneMutationTest.cs +++ b/NineChronicles.Headless.Tests/GraphTypes/StandaloneMutationTest.cs @@ -127,6 +127,7 @@ public async Task ActivateAccount() ProposerPrivateKey, lastCommit: GenerateBlockCommit(BlockChain.Tip.Index, BlockChain.Tip.Hash, GenesisValidators)); BlockChain.Append(block, GenerateBlockCommit(block.Index, block.Hash, GenesisValidators)); + AppendEmptyBlock(GenesisValidators); var encodedActivationKey = activationKey.Encode(); var queryResult = await ExecuteQueryAsync( @@ -143,7 +144,7 @@ public async Task ActivateAccount() Assert.True(result); Address userAddress = StandaloneContextFx.NineChroniclesNodeService!.MinerPrivateKey!.Address; - IValue? state = BlockChain.GetWorldState().GetLegacyState(userAddress.Derive(ActivationKey.DeriveKey)); + IValue? state = BlockChain.GetNextWorldState().GetLegacyState(userAddress.Derive(ActivationKey.DeriveKey)); Assert.True((Bencodex.Types.Boolean)state); } @@ -156,7 +157,7 @@ public async Task Transfer(string? memo, bool error) { NineChroniclesNodeService service = StandaloneContextFx.NineChroniclesNodeService!; Currency goldCurrency = new GoldCurrencyState( - (Dictionary)BlockChain.GetWorldState().GetLegacyState(GoldCurrencyState.Address) + (Dictionary)BlockChain.GetNextWorldState().GetLegacyState(GoldCurrencyState.Address) ).Currency; Address senderAddress = service.MinerPrivateKey!.Address; @@ -173,7 +174,7 @@ public async Task Transfer(string? memo, bool error) // 10 + 10 (mining rewards) Assert.Equal( 20 * goldCurrency, - BlockChain.GetWorldState().GetBalance(senderAddress, goldCurrency) + BlockChain.GetNextWorldState().GetBalance(senderAddress, goldCurrency) ); var recipientKey = new PrivateKey(); @@ -227,13 +228,13 @@ public async Task Transfer(string? memo, bool error) // 10 + 10 - 17.5(transfer) Assert.Equal( FungibleAssetValue.Parse(goldCurrency, "2.5"), - BlockChain.GetWorldState().GetBalance(senderAddress, goldCurrency) + BlockChain.GetNextWorldState().GetBalance(senderAddress, goldCurrency) ); // 0 + 17.5(transfer) + 10(mining reward) Assert.Equal( FungibleAssetValue.Parse(goldCurrency, "27.5"), - BlockChain.GetWorldState().GetBalance(recipient, goldCurrency) + BlockChain.GetNextWorldState().GetBalance(recipient, goldCurrency) ); } } @@ -243,7 +244,7 @@ public async Task TransferGold() { NineChroniclesNodeService service = StandaloneContextFx.NineChroniclesNodeService!; Currency goldCurrency = new GoldCurrencyState( - (Dictionary)BlockChain.GetWorldState().GetLegacyState(GoldCurrencyState.Address) + (Dictionary)BlockChain.GetNextWorldState().GetLegacyState(GoldCurrencyState.Address) ).Currency; Address senderAddress = service.MinerPrivateKey!.Address; @@ -261,7 +262,7 @@ public async Task TransferGold() // 10 + 10 (mining rewards) Assert.Equal( 20 * goldCurrency, - BlockChain.GetWorldState().GetBalance(senderAddress, goldCurrency) + BlockChain.GetNextWorldState().GetBalance(senderAddress, goldCurrency) ); var recipientKey = new PrivateKey(); @@ -288,13 +289,13 @@ public async Task TransferGold() // 10 + 10 - 17.5(transfer) Assert.Equal( FungibleAssetValue.Parse(goldCurrency, "2.5"), - BlockChain.GetWorldState().GetBalance(senderAddress, goldCurrency) + BlockChain.GetNextWorldState().GetBalance(senderAddress, goldCurrency) ); // 0 + 17.5(transfer) + 10(mining reward) Assert.Equal( FungibleAssetValue.Parse(goldCurrency, "27.5"), - BlockChain.GetWorldState().GetBalance(recipient, goldCurrency) + BlockChain.GetNextWorldState().GetBalance(recipient, goldCurrency) ); } @@ -858,6 +859,7 @@ public async Task Tx_ActivateAccount() ProposerPrivateKey, lastCommit: GenerateBlockCommit(BlockChain.Tip.Index, BlockChain.Tip.Hash, GenesisValidators)); BlockChain.Append(block, GenerateBlockCommit(block.Index, block.Hash, GenesisValidators)); + AppendEmptyBlock(GenesisValidators); var encodedActivationKey = activationKey.Encode(); var actionCommand = new ActionCommand(new StandardConsole()); var filePath = Path.Combine(Path.GetTempPath(), Path.GetTempFileName()); @@ -879,7 +881,7 @@ public async Task Tx_ActivateAccount() var result = (bool)data["stageTx"]; Assert.True(result); - IValue? state = BlockChain.GetWorldState().GetLegacyState(privateKey.Address.Derive(ActivationKey.DeriveKey)); + IValue? state = BlockChain.GetNextWorldState().GetLegacyState(privateKey.Address.Derive(ActivationKey.DeriveKey)); Assert.True((Bencodex.Types.Boolean)state); } diff --git a/NineChronicles.Headless.Tests/GraphTypes/StandaloneQueryTest.cs b/NineChronicles.Headless.Tests/GraphTypes/StandaloneQueryTest.cs index 7a99619fc..d668b7cef 100644 --- a/NineChronicles.Headless.Tests/GraphTypes/StandaloneQueryTest.cs +++ b/NineChronicles.Headless.Tests/GraphTypes/StandaloneQueryTest.cs @@ -20,22 +20,18 @@ using Libplanet.Headless.Hosting; using Libplanet.KeyStore; using Libplanet.Net; -using Libplanet.Store; -using Libplanet.Store.Trie; using Libplanet.Types.Assets; using Libplanet.Types.Blocks; using Libplanet.Types.Consensus; using Libplanet.Types.Tx; using Nekoyume; using Nekoyume.Action; -using Nekoyume.Action.Loader; using Nekoyume.Blockchain.Policy; using Nekoyume.Helper; using Nekoyume.Model; using Nekoyume.Model.State; using Nekoyume.Module; using Nekoyume.TableData; -using NineChronicles.Headless.Properties; using NineChronicles.Headless.Tests.Common; using Xunit; using Xunit.Abstractions; @@ -55,6 +51,7 @@ public StandaloneQueryTest(ITestOutputHelper output) : base(output) [Fact] public async Task GetState() { + AppendEmptyBlock(GenesisValidators); Address adminStateAddress = AdminState.Address; var result = await ExecuteQueryAsync($"query {{ state(accountAddress: \"{ReservedAddresses.LegacyAccount}\", address: \"{adminStateAddress}\") }}"); var data = (Dictionary)((ExecutionNode)result.Data!).ToValue()!; @@ -512,6 +509,7 @@ public async Task ActivationStatus(bool existsActivatedAccounts) StandaloneContextFx.BlockChain = service.Swarm?.BlockChain; var blockChain = StandaloneContextFx.BlockChain!; + AppendEmptyBlock(GenesisValidators); var queryResult = await ExecuteQueryAsync("query { activationStatus { activated } }"); var data = (Dictionary)((ExecutionNode)queryResult.Data!).ToValue()!; @@ -538,6 +536,7 @@ public async Task ActivationStatus(bool existsActivatedAccounts) ProposerPrivateKey, lastCommit: GenerateBlockCommit(BlockChain.Tip.Index, BlockChain.Tip.Hash, GenesisValidators)); blockChain.Append(block, GenerateBlockCommit(block.Index, block.Hash, GenesisValidators)); + AppendEmptyBlock(GenesisValidators); queryResult = await ExecuteQueryAsync("query { activationStatus { activated } }"); data = (Dictionary)((ExecutionNode)queryResult.Data!).ToValue()!; @@ -559,6 +558,7 @@ public async Task GoldBalance() var service = MakeNineChroniclesNodeService(userPrivateKey); StandaloneContextFx.NineChroniclesNodeService = service; StandaloneContextFx.BlockChain = service.Swarm?.BlockChain; + AppendEmptyBlock(validators); var blockChain = StandaloneContextFx.BlockChain; var query = $"query {{ goldBalance(address: \"{userAddress}\") }}"; @@ -576,6 +576,7 @@ public async Task GoldBalance() userPrivateKey, lastCommit: GenerateBlockCommit(BlockChain.Tip.Index, BlockChain.Tip.Hash, validators)); blockChain!.Append(block, GenerateBlockCommit(block.Index, block.Hash, validators)); + AppendEmptyBlock(validators); queryResult = await ExecuteQueryAsync(query); data = (Dictionary)((ExecutionNode)queryResult.Data!).ToValue()!; @@ -744,6 +745,7 @@ public async Task MonsterCollectionStatus_MonsterCollectionState_Null(bool miner userPrivateKey, lastCommit: GenerateBlockCommit(BlockChain.Tip.Index, BlockChain.Tip.Hash, validators)); blockChain.Append(block, GenerateBlockCommit(block.Index, block.Hash, validators)); + AppendEmptyBlock(validators); string queryArgs = miner ? "" : $@"(address: ""{userAddress}"")"; string query = $@"query {{ @@ -795,6 +797,7 @@ public async Task Avatar() userPrivateKey, lastCommit: GenerateBlockCommit(BlockChain.Tip.Index, BlockChain.Tip.Hash, validators)); blockChain.Append(block, GenerateBlockCommit(block.Index, block.Hash, validators)); + AppendEmptyBlock(validators); var avatarAddress = userAddress.Derive( string.Format( @@ -833,30 +836,46 @@ public async Task ActivationKeyNonce(bool trim) }; Block genesis = BlockChain.ProposeGenesisBlock( - transactions: ImmutableList.Empty.Add( - Transaction.Create(0, new PrivateKey(), null, - new ActionBase[] - { - new InitializeStates( - rankingState: new RankingState0(), - shopState: new ShopState(), - gameConfigState: new GameConfigState(), - redeemCodeState: new RedeemCodeState(Bencodex.Types.Dictionary.Empty - .Add("address", RedeemCodeState.Address.Serialize()) - .Add("map", Bencodex.Types.Dictionary.Empty) - ), - adminAddressState: new AdminState(adminAddress, 1500000), - activatedAccountsState: new ActivatedAccountsState(activatedAccounts), + transactions: ImmutableList.Empty + .Add( + Transaction.Create( + 0, ProposerPrivateKey, + null, + new IAction[] + { + new Initialize( + new ValidatorSet( + GenesisValidators.Select( + v => new Validator(v.PublicKey, BigInteger.One)).ToList()), + ImmutableDictionary.Create()) + }.Select(a => a.PlainValue))) + .Add( + Transaction.Create( + 1, + ProposerPrivateKey, + null, + new ActionBase[] + { + new InitializeStates( + rankingState: new RankingState0(), + shopState: new ShopState(), + gameConfigState: new GameConfigState(), + redeemCodeState: new RedeemCodeState(Bencodex.Types.Dictionary.Empty + .Add("address", RedeemCodeState.Address.Serialize()) + .Add("map", Bencodex.Types.Dictionary.Empty) + ), + adminAddressState: new AdminState(adminAddress, 1500000), + activatedAccountsState: new ActivatedAccountsState(activatedAccounts), #pragma warning disable CS0618 - // Use of obsolete method Currency.Legacy(): - // https://github.com/planetarium/lib9c/discussions/1319 - goldCurrencyState: new GoldCurrencyState(Currency.Legacy("NCG", 2, null)), + // Use of obsolete method Currency.Legacy(): + // https://github.com/planetarium/lib9c/discussions/1319 + goldCurrencyState: new GoldCurrencyState(Currency.Legacy("NCG", 2, null)), #pragma warning restore CS0618 - goldDistributions: new GoldDistribution[0], - tableSheets: _sheets, - pendingActivationStates: pendingActivationStates.ToArray() - ), - }.ToPlainValues())) + goldDistributions: new GoldDistribution[0], + tableSheets: _sheets, + pendingActivationStates: pendingActivationStates.ToArray() + ), + }.ToPlainValues())) ); var apvPrivateKey = new PrivateKey(); @@ -887,6 +906,7 @@ public async Task ActivationKeyNonce(bool trim) var service = new NineChroniclesNodeService(userPrivateKey, properties, blockPolicy, Planet.Odin, StaticActionLoaderSingleton.Instance); StandaloneContextFx.NineChroniclesNodeService = service; StandaloneContextFx.BlockChain = service.Swarm?.BlockChain; + AppendEmptyBlock(GenesisValidators); var code = activationKey.Encode(); if (trim) diff --git a/NineChronicles.Headless.Tests/GraphTypes/WorldBossScenarioTest.cs b/NineChronicles.Headless.Tests/GraphTypes/WorldBossScenarioTest.cs index f1ad705bb..a215ef71a 100644 --- a/NineChronicles.Headless.Tests/GraphTypes/WorldBossScenarioTest.cs +++ b/NineChronicles.Headless.Tests/GraphTypes/WorldBossScenarioTest.cs @@ -65,7 +65,6 @@ public WorldBossScenarioTest() [2] = false, }; _stateContext = new StateContext(GetMockState(), 1L, new StateMemoryCache()); - var minerPrivateKey = new PrivateKey(); var initializeStates = new InitializeStates( rankingState: new RankingState0(), shopState: new ShopState(), @@ -79,13 +78,13 @@ public WorldBossScenarioTest() #pragma warning disable CS0618 // Use of obsolete method Currency.Legacy(): https://github.com/planetarium/lib9c/discussions/1319 goldCurrencyState: - new GoldCurrencyState(Currency.Legacy("NCG", 2, minerPrivateKey.Address)), + new GoldCurrencyState(Currency.Legacy("NCG", 2, MinerPrivateKey.Address)), #pragma warning restore CS0618 goldDistributions: Array.Empty(), tableSheets: new Dictionary(), pendingActivationStates: new PendingActivationState[] { } ); - _standaloneContext = CreateStandaloneContext(initializeStates, minerPrivateKey); + _standaloneContext = CreateStandaloneContext(initializeStates); } [Theory] From a4be33a3707614df982c7da89589a0ed8df40290 Mon Sep 17 00:00:00 2001 From: ilgyu Date: Wed, 12 Jun 2024 23:08:33 +0900 Subject: [PATCH 7/8] fix: Fix ChainCommand.Inspect --- NineChronicles.Headless.Executable/Commands/ChainCommand.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/NineChronicles.Headless.Executable/Commands/ChainCommand.cs b/NineChronicles.Headless.Executable/Commands/ChainCommand.cs index 0eed89f37..643d2ca16 100644 --- a/NineChronicles.Headless.Executable/Commands/ChainCommand.cs +++ b/NineChronicles.Headless.Executable/Commands/ChainCommand.cs @@ -120,7 +120,9 @@ public void Inspect( IStagePolicy stagePolicy = new VolatileStagePolicy(); IBlockPolicy blockPolicy = new BlockPolicySource().GetPolicy(); IStore store = storeType.CreateStore(storePath); - var stateStore = new TrieStateStore(new DefaultKeyValueStore(null)); + var statesPath = Path.Combine(storePath, "states"); + IKeyValueStore stateKeyValueStore = new RocksDBKeyValueStore(statesPath); + var stateStore = new TrieStateStore(stateKeyValueStore); if (!(store.GetCanonicalChainId() is { } chainId)) { throw new CommandExitedException($"There is no canonical chain: {storePath}", -1); @@ -217,6 +219,7 @@ public void Inspect( } store.Dispose(); + stateStore.Dispose(); } [Command(Description = "Truncate the chain from the tip by the input value (in blocks)")] From 9ae42c04aac21920dfb6ab62628be3872691e569 Mon Sep 17 00:00:00 2001 From: ilgyu Date: Fri, 14 Jun 2024 14:10:44 +0900 Subject: [PATCH 8/8] fix: ReplayCommand.RemoteTx to evaluate with BPV --- .../Commands/ReplayCommand.Queries.cs | 2 ++ .../Commands/ReplayCommand.cs | 9 +++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/NineChronicles.Headless.Executable/Commands/ReplayCommand.Queries.cs b/NineChronicles.Headless.Executable/Commands/ReplayCommand.Queries.cs index 3d61c5b89..7ad4950d5 100644 --- a/NineChronicles.Headless.Executable/Commands/ReplayCommand.Queries.cs +++ b/NineChronicles.Headless.Executable/Commands/ReplayCommand.Queries.cs @@ -50,6 +50,7 @@ query GetBlockData($hash: ID!) stateRootHash } stateRootHash + protocolVersion } }} } @@ -90,6 +91,7 @@ private sealed class BlockType public string? PreEvaluationHash { get; set; } public BlockType? PreviousBlock { get; set; } public string? StateRootHash { get; set; } + public int? ProtocolVersion { get; set; } } private sealed class TransactionQueryType diff --git a/NineChronicles.Headless.Executable/Commands/ReplayCommand.cs b/NineChronicles.Headless.Executable/Commands/ReplayCommand.cs index d5a1f7a8d..94606a02f 100644 --- a/NineChronicles.Headless.Executable/Commands/ReplayCommand.cs +++ b/NineChronicles.Headless.Executable/Commands/ReplayCommand.cs @@ -388,7 +388,12 @@ public int RemoteTx( var previousBlockHashStateRootHash = block?.PreviousBlock?.StateRootHash; var preEvaluationHashValue = block?.PreEvaluationHash; var minerValue = block?.Miner; - if (previousBlockHashValue is null || preEvaluationHashValue is null || minerValue is null || previousBlockHashStateRootHash is null) + var protocolVersion = block?.ProtocolVersion; + if (previousBlockHashValue is null + || preEvaluationHashValue is null + || minerValue is null + || previousBlockHashStateRootHash is null + || protocolVersion is null) { throw new CommandExitedException("Failed to get block from query", -1); } @@ -428,7 +433,7 @@ public int RemoteTx( var actionEvaluations = EvaluateActions( preEvaluationHash: HashDigest.FromString(preEvaluationHashValue), blockIndex: transactionResult.BlockIndex ?? 0, - blockProtocolVersion: 0, + blockProtocolVersion: (int)protocolVersion, txid: transaction.Id, previousStates: previousStates, miner: miner,