From 00fdcf4ef309594a584cc60aa1da111628b4dfa8 Mon Sep 17 00:00:00 2001 From: area363 Date: Tue, 7 Nov 2023 17:56:19 +0900 Subject: [PATCH 1/7] bump lib9c --- Lib9c | 2 +- .../IAccessControlService.cs | 9 ++ .../Policies/NCStagePolicy.cs | 140 ++++++++++++++++++ 3 files changed, 150 insertions(+), 1 deletion(-) create mode 100644 NineChronicles.Headless/AccessControlService/IAccessControlService.cs create mode 100644 NineChronicles.Headless/Policies/NCStagePolicy.cs diff --git a/Lib9c b/Lib9c index 1969277b9..b671329c6 160000 --- a/Lib9c +++ b/Lib9c @@ -1 +1 @@ -Subproject commit 1969277b9c5dedcd3d6e5cd46a48d5f259f2afca +Subproject commit b671329c641ed0cb00e5dc9b8e104b19532362b1 diff --git a/NineChronicles.Headless/AccessControlService/IAccessControlService.cs b/NineChronicles.Headless/AccessControlService/IAccessControlService.cs new file mode 100644 index 000000000..42e7dc120 --- /dev/null +++ b/NineChronicles.Headless/AccessControlService/IAccessControlService.cs @@ -0,0 +1,9 @@ +using Libplanet.Crypto; + +namespace Nekoyume.Blockchain +{ + public interface IAccessControlService + { + public int? GetTxQuota(Address address); + } +} diff --git a/NineChronicles.Headless/Policies/NCStagePolicy.cs b/NineChronicles.Headless/Policies/NCStagePolicy.cs new file mode 100644 index 000000000..0dbd00c1f --- /dev/null +++ b/NineChronicles.Headless/Policies/NCStagePolicy.cs @@ -0,0 +1,140 @@ +namespace Nekoyume.Blockchain +{ + using System; + using System.Collections.Concurrent; + using System.Collections.Generic; + using System.Collections.Immutable; + using System.Linq; + using Libplanet.Blockchain; + using Libplanet.Blockchain.Policies; + using Libplanet.Crypto; + using Libplanet.Types.Tx; + + public class NCStagePolicy : IStagePolicy + { + private readonly VolatileStagePolicy _impl; + private readonly ConcurrentDictionary> _txs; + private readonly int _quotaPerSigner; + private IAccessControlService? _accessControlService; + + public NCStagePolicy(TimeSpan txLifeTime, int quotaPerSigner, IAccessControlService? accessControlService = null) + { + if (quotaPerSigner < 1) + { + throw new ArgumentOutOfRangeException( + $"{nameof(quotaPerSigner)} must be positive: ${quotaPerSigner}"); + } + + _txs = new ConcurrentDictionary>(); + _quotaPerSigner = quotaPerSigner; + _impl = (txLifeTime == default) + ? new VolatileStagePolicy() + : new VolatileStagePolicy(txLifeTime); + + _accessControlService = accessControlService; + } + + public Transaction Get(BlockChain blockChain, TxId id, bool filtered = true) + => _impl.Get(blockChain, id, filtered); + + public long GetNextTxNonce(BlockChain blockChain, Address address) + => _impl.GetNextTxNonce(blockChain, address); + + public void Ignore(BlockChain blockChain, TxId id) + => _impl.Ignore(blockChain, id); + + public bool Ignores(BlockChain blockChain, TxId id) + => _impl.Ignores(blockChain, id); + + public IEnumerable Iterate(BlockChain blockChain, bool filtered = true) + { + if (filtered) + { + var txsPerSigner = new Dictionary>(); + foreach (Transaction tx in _impl.Iterate(blockChain, filtered)) + { + if (!txsPerSigner.TryGetValue(tx.Signer, out var s)) + { + txsPerSigner[tx.Signer] = s = new SortedSet(new TxComparer()); + } + + s.Add(tx); + int txQuotaPerSigner = _quotaPerSigner; + + // update txQuotaPerSigner if ACS returns a value for the signer. + if (_accessControlService?.GetTxQuota(tx.Signer) is { } acsTxQuota) + { + txQuotaPerSigner = acsTxQuota; + } + + + if (s.Count > txQuotaPerSigner) + { + s.Remove(s.Max); + } + } + +#pragma warning disable LAA1002 // DictionariesOrSetsShouldBeOrderedToEnumerate + return txsPerSigner.Values.SelectMany(i => i); +#pragma warning restore LAA1002 // DictionariesOrSetsShouldBeOrderedToEnumerate + } + else + { + return _impl.Iterate(blockChain, filtered); + } + } + + public bool Stage(BlockChain blockChain, Transaction transaction) + { + if (_accessControlService?.GetTxQuota(transaction.Signer) is { } acsTxQuota + && acsTxQuota == 0) + { + return false; + } + + var deniedTxs = new[] + { + // CreatePledge Transaction with 50000 addresses + TxId.FromHex("300826da62b595d8cd663dadf04995a7411534d1cdc17dac75ce88754472f774"), + // CreatePledge Transaction with 5000 addresses + TxId.FromHex("210d1374d8f068de657de6b991e63888da9cadbc68e505ac917b35568b5340f8"), + }; + if (deniedTxs.Contains(transaction.Id)) + { + return false; + } + + return _impl.Stage(blockChain, transaction); + } + + public bool Unstage(BlockChain blockChain, TxId id) + => _impl.Unstage(blockChain, id); + + private class TxComparer : IComparer + { + public int Compare(Transaction x, Transaction y) + { + if (x.Nonce < y.Nonce) + { + return -1; + } + else if (x.Nonce > y.Nonce) + { + return 1; + } + else if (x.Timestamp < y.Timestamp) + { + return -1; + } + else if (x.Timestamp > y.Timestamp) + { + return 1; + } + else + { + return 0; + } + } + } + } +} From 7b4b2bb256ce4bebacb7508772f242f9b89354eb Mon Sep 17 00:00:00 2001 From: area363 Date: Tue, 7 Nov 2023 17:57:00 +0900 Subject: [PATCH 2/7] add NCStagePolicy and IAccessControlService --- .../AccessControlService/IAccessControlService.cs | 2 +- NineChronicles.Headless/Policies/NCStagePolicy.cs | 13 +++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/NineChronicles.Headless/AccessControlService/IAccessControlService.cs b/NineChronicles.Headless/AccessControlService/IAccessControlService.cs index 42e7dc120..c96e7c64a 100644 --- a/NineChronicles.Headless/AccessControlService/IAccessControlService.cs +++ b/NineChronicles.Headless/AccessControlService/IAccessControlService.cs @@ -1,6 +1,6 @@ using Libplanet.Crypto; -namespace Nekoyume.Blockchain +namespace NineChronicles.Headless.AccessControlService { public interface IAccessControlService { diff --git a/NineChronicles.Headless/Policies/NCStagePolicy.cs b/NineChronicles.Headless/Policies/NCStagePolicy.cs index 0dbd00c1f..f5b17bb00 100644 --- a/NineChronicles.Headless/Policies/NCStagePolicy.cs +++ b/NineChronicles.Headless/Policies/NCStagePolicy.cs @@ -1,4 +1,4 @@ -namespace Nekoyume.Blockchain +namespace NineChronicles.Headless.Policies { using System; using System.Collections.Concurrent; @@ -9,6 +9,7 @@ namespace Nekoyume.Blockchain using Libplanet.Blockchain.Policies; using Libplanet.Crypto; using Libplanet.Types.Tx; + using NineChronicles.Headless.AccessControlService; public class NCStagePolicy : IStagePolicy { @@ -35,7 +36,7 @@ public NCStagePolicy(TimeSpan txLifeTime, int quotaPerSigner, IAccessControlServ } public Transaction Get(BlockChain blockChain, TxId id, bool filtered = true) - => _impl.Get(blockChain, id, filtered); + => _impl.Get(blockChain, id, filtered)!; public long GetNextTxNonce(BlockChain blockChain, Address address) => _impl.GetNextTxNonce(blockChain, address); @@ -70,7 +71,7 @@ public IEnumerable Iterate(BlockChain blockChain, bool filtered = t if (s.Count > txQuotaPerSigner) { - s.Remove(s.Max); + s.Remove(s.Max!); } } @@ -110,11 +111,11 @@ public bool Stage(BlockChain blockChain, Transaction transaction) public bool Unstage(BlockChain blockChain, TxId id) => _impl.Unstage(blockChain, id); - private class TxComparer : IComparer + private sealed class TxComparer : IComparer { - public int Compare(Transaction x, Transaction y) + public int Compare(Transaction? x, Transaction? y) { - if (x.Nonce < y.Nonce) + if (x!.Nonce < y!.Nonce) { return -1; } From 99525c058e4eac9c9fb7e1dfc786dd5877df5653 Mon Sep 17 00:00:00 2001 From: area363 Date: Tue, 7 Nov 2023 17:57:24 +0900 Subject: [PATCH 3/7] update reference --- .../AccessControlService/IMutableAccessControlService.cs | 2 +- NineChronicles.Headless/NineChroniclesNodeService.cs | 2 ++ NineChronicles.Headless/Services/AccessControlServiceFactory.cs | 2 +- NineChronicles.Headless/Services/RedisAccessControlService.cs | 2 +- NineChronicles.Headless/Services/SQLiteAccessControlService.cs | 2 +- 5 files changed, 6 insertions(+), 4 deletions(-) diff --git a/NineChronicles.Headless.AccessControlCenter/AccessControlService/IMutableAccessControlService.cs b/NineChronicles.Headless.AccessControlCenter/AccessControlService/IMutableAccessControlService.cs index b5d52f697..716fa8fe2 100644 --- a/NineChronicles.Headless.AccessControlCenter/AccessControlService/IMutableAccessControlService.cs +++ b/NineChronicles.Headless.AccessControlCenter/AccessControlService/IMutableAccessControlService.cs @@ -1,6 +1,6 @@ using Libplanet.Crypto; using System.Collections.Generic; -using Nekoyume.Blockchain; +using NineChronicles.Headless.AccessControlService; namespace NineChronicles.Headless.AccessControlCenter.AccessControlService { diff --git a/NineChronicles.Headless/NineChroniclesNodeService.cs b/NineChronicles.Headless/NineChroniclesNodeService.cs index 181f14e6e..7a2db6e4f 100644 --- a/NineChronicles.Headless/NineChroniclesNodeService.cs +++ b/NineChronicles.Headless/NineChroniclesNodeService.cs @@ -18,6 +18,8 @@ using Microsoft.Extensions.Hosting; using Nekoyume.Blockchain; using Nekoyume.Blockchain.Policy; +using NineChronicles.Headless.AccessControlService; +using NineChronicles.Headless.Policies; using NineChronicles.Headless.Properties; using NineChronicles.Headless.Utils; using NineChronicles.Headless.Services; diff --git a/NineChronicles.Headless/Services/AccessControlServiceFactory.cs b/NineChronicles.Headless/Services/AccessControlServiceFactory.cs index 0ff8e476a..7ef6a69a2 100644 --- a/NineChronicles.Headless/Services/AccessControlServiceFactory.cs +++ b/NineChronicles.Headless/Services/AccessControlServiceFactory.cs @@ -1,5 +1,5 @@ using System; -using Nekoyume.Blockchain; +using NineChronicles.Headless.AccessControlService; namespace NineChronicles.Headless.Services { diff --git a/NineChronicles.Headless/Services/RedisAccessControlService.cs b/NineChronicles.Headless/Services/RedisAccessControlService.cs index 40769292d..e3bf24498 100644 --- a/NineChronicles.Headless/Services/RedisAccessControlService.cs +++ b/NineChronicles.Headless/Services/RedisAccessControlService.cs @@ -1,7 +1,7 @@ using System; using StackExchange.Redis; using Libplanet.Crypto; -using Nekoyume.Blockchain; +using NineChronicles.Headless.AccessControlService; using Serilog; namespace NineChronicles.Headless.Services diff --git a/NineChronicles.Headless/Services/SQLiteAccessControlService.cs b/NineChronicles.Headless/Services/SQLiteAccessControlService.cs index f3e7263c8..219b7db3c 100644 --- a/NineChronicles.Headless/Services/SQLiteAccessControlService.cs +++ b/NineChronicles.Headless/Services/SQLiteAccessControlService.cs @@ -1,7 +1,7 @@ using System; using Microsoft.Data.Sqlite; using Libplanet.Crypto; -using Nekoyume.Blockchain; +using NineChronicles.Headless.AccessControlService; using Serilog; namespace NineChronicles.Headless.Services From f6b4a42fb636b2b80b43a30aeeee48d8e3cb60e2 Mon Sep 17 00:00:00 2001 From: area363 Date: Tue, 7 Nov 2023 18:10:32 +0900 Subject: [PATCH 4/7] bump lib9c --- .../Policies/StagePolicyTest.cs | 257 ++++++++++++++++++ 1 file changed, 257 insertions(+) create mode 100644 NineChronicles.Headless.Tests/Policies/StagePolicyTest.cs diff --git a/NineChronicles.Headless.Tests/Policies/StagePolicyTest.cs b/NineChronicles.Headless.Tests/Policies/StagePolicyTest.cs new file mode 100644 index 000000000..506b134d7 --- /dev/null +++ b/NineChronicles.Headless.Tests/Policies/StagePolicyTest.cs @@ -0,0 +1,257 @@ +namespace Lib9c.Tests +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Threading.Tasks; + using Lib9c.Renderers; + using Lib9c.Tests.TestHelper; + using Libplanet.Action; + using Libplanet.Blockchain; + using Libplanet.Blockchain.Policies; + using Libplanet.Crypto; + using Libplanet.Types.Tx; + using Nekoyume.Action; + using Nekoyume.Blockchain; + using Nekoyume.Blockchain.Policy; + using Serilog.Core; + using Xunit; + + public class StagePolicyTest + { + private readonly PrivateKey[] _accounts; + + private readonly Dictionary _txs; + + public StagePolicyTest() + { + _accounts = new[] + { + new PrivateKey(), + new PrivateKey(), + new PrivateKey(), + new PrivateKey(), + }; + _txs = _accounts.ToDictionary( + acc => acc.ToAddress(), + acc => Enumerable + .Range(0, 10) + .Select( + n => Transaction.Create( + n, + acc, + default, + new ActionBase[0].ToPlainValues() + ) + ) + .ToArray() + ); + } + + [Fact] + public void Stage() + { + NCStagePolicy stagePolicy = new NCStagePolicy(TimeSpan.FromHours(1), 2); + BlockChain chain = MakeChainWithStagePolicy(stagePolicy); + + stagePolicy.Stage(chain, _txs[_accounts[0].ToAddress()][0]); + stagePolicy.Stage(chain, _txs[_accounts[0].ToAddress()][1]); + stagePolicy.Stage(chain, _txs[_accounts[1].ToAddress()][0]); + stagePolicy.Stage(chain, _txs[_accounts[2].ToAddress()][0]); + + AssertTxs( + chain, + stagePolicy, + _txs[_accounts[0].ToAddress()][0], + _txs[_accounts[0].ToAddress()][1], + _txs[_accounts[1].ToAddress()][0], + _txs[_accounts[2].ToAddress()][0] + ); + } + + [Fact] + public void StageOverQuota() + { + NCStagePolicy stagePolicy = new NCStagePolicy(TimeSpan.FromHours(1), 2); + BlockChain chain = MakeChainWithStagePolicy(stagePolicy); + + stagePolicy.Stage(chain, _txs[_accounts[0].ToAddress()][0]); + stagePolicy.Stage(chain, _txs[_accounts[0].ToAddress()][1]); + stagePolicy.Stage(chain, _txs[_accounts[0].ToAddress()][2]); + stagePolicy.Stage(chain, _txs[_accounts[0].ToAddress()][3]); + + AssertTxs( + chain, + stagePolicy, + _txs[_accounts[0].ToAddress()][0], + _txs[_accounts[0].ToAddress()][1] + ); + } + + [Fact] + public void StageOverQuotaInverseOrder() + { + NCStagePolicy stagePolicy = new NCStagePolicy(TimeSpan.FromHours(1), 2); + BlockChain chain = MakeChainWithStagePolicy(stagePolicy); + + stagePolicy.Stage(chain, _txs[_accounts[0].ToAddress()][3]); + stagePolicy.Stage(chain, _txs[_accounts[0].ToAddress()][2]); + stagePolicy.Stage(chain, _txs[_accounts[0].ToAddress()][1]); + stagePolicy.Stage(chain, _txs[_accounts[0].ToAddress()][0]); + + AssertTxs( + chain, + stagePolicy, + _txs[_accounts[0].ToAddress()][0], + _txs[_accounts[0].ToAddress()][1] + ); + } + + [Fact] + public void StageOverQuotaOutOfOrder() + { + NCStagePolicy stagePolicy = new NCStagePolicy(TimeSpan.FromHours(1), 2); + BlockChain chain = MakeChainWithStagePolicy(stagePolicy); + + stagePolicy.Stage(chain, _txs[_accounts[0].ToAddress()][2]); + stagePolicy.Stage(chain, _txs[_accounts[0].ToAddress()][1]); + stagePolicy.Stage(chain, _txs[_accounts[0].ToAddress()][3]); + stagePolicy.Stage(chain, _txs[_accounts[0].ToAddress()][0]); + + AssertTxs( + chain, + stagePolicy, + _txs[_accounts[0].ToAddress()][0], + _txs[_accounts[0].ToAddress()][1] + ); + } + + [Fact] + public void StageSameNonce() + { + NCStagePolicy stagePolicy = new NCStagePolicy(TimeSpan.FromHours(1), 2); + BlockChain chain = MakeChainWithStagePolicy(stagePolicy); + var txA = Transaction.Create(0, _accounts[0], default, new ActionBase[0].ToPlainValues()); + var txB = Transaction.Create(0, _accounts[0], default, new ActionBase[0].ToPlainValues()); + var txC = Transaction.Create(0, _accounts[0], default, new ActionBase[0].ToPlainValues()); + + stagePolicy.Stage(chain, txA); + stagePolicy.Stage(chain, txB); + stagePolicy.Stage(chain, txC); + + AssertTxs(chain, stagePolicy, txA, txB); + } + + [Fact] + public async Task StateFromMultiThread() + { + NCStagePolicy stagePolicy = new NCStagePolicy(TimeSpan.FromHours(1), 2); + BlockChain chain = MakeChainWithStagePolicy(stagePolicy); + + await Task.WhenAll( + Enumerable + .Range(0, 40) + .Select(i => Task.Run(() => + { + stagePolicy.Stage(chain, _txs[_accounts[i / 10].ToAddress()][i % 10]); + })) + ); + AssertTxs( + chain, + stagePolicy, + _txs[_accounts[0].ToAddress()][0], + _txs[_accounts[0].ToAddress()][1], + _txs[_accounts[1].ToAddress()][0], + _txs[_accounts[1].ToAddress()][1], + _txs[_accounts[2].ToAddress()][0], + _txs[_accounts[2].ToAddress()][1], + _txs[_accounts[3].ToAddress()][0], + _txs[_accounts[3].ToAddress()][1] + ); + } + + [Fact] + public void IterateAfterUnstage() + { + NCStagePolicy stagePolicy = new NCStagePolicy(TimeSpan.FromHours(1), 2); + BlockChain chain = MakeChainWithStagePolicy(stagePolicy); + + stagePolicy.Stage(chain, _txs[_accounts[0].ToAddress()][0]); + stagePolicy.Stage(chain, _txs[_accounts[0].ToAddress()][1]); + stagePolicy.Stage(chain, _txs[_accounts[0].ToAddress()][2]); + stagePolicy.Stage(chain, _txs[_accounts[0].ToAddress()][3]); + + AssertTxs( + chain, + stagePolicy, + _txs[_accounts[0].ToAddress()][0], + _txs[_accounts[0].ToAddress()][1] + ); + + stagePolicy.Unstage(chain, _txs[_accounts[0].ToAddress()][0].Id); + + AssertTxs( + chain, + stagePolicy, + _txs[_accounts[0].ToAddress()][1], + _txs[_accounts[0].ToAddress()][2] + ); + } + + [Fact] + public void CalculateNextTxNonceCorrectWhenTxOverQuota() + { + NCStagePolicy stagePolicy = new NCStagePolicy(TimeSpan.FromHours(1), 2); + BlockChain chain = MakeChainWithStagePolicy(stagePolicy); + + long nextTxNonce = chain.GetNextTxNonce(_accounts[0].ToAddress()); + Assert.Equal(0, nextTxNonce); + var txA = Transaction.Create(nextTxNonce, _accounts[0], default, new ActionBase[0].ToPlainValues()); + stagePolicy.Stage(chain, txA); + + nextTxNonce = chain.GetNextTxNonce(_accounts[0].ToAddress()); + Assert.Equal(1, nextTxNonce); + var txB = Transaction.Create(nextTxNonce, _accounts[0], default, new ActionBase[0].ToPlainValues()); + stagePolicy.Stage(chain, txB); + + nextTxNonce = chain.GetNextTxNonce(_accounts[0].ToAddress()); + Assert.Equal(2, nextTxNonce); + var txC = Transaction.Create(nextTxNonce, _accounts[0], default, new ActionBase[0].ToPlainValues()); + stagePolicy.Stage(chain, txC); + + nextTxNonce = chain.GetNextTxNonce(_accounts[0].ToAddress()); + Assert.Equal(3, nextTxNonce); + + AssertTxs( + chain, + stagePolicy, + txA, + txB); + } + + private void AssertTxs(BlockChain blockChain, NCStagePolicy policy, params Transaction[] txs) + { + foreach (Transaction tx in txs) + { + Assert.Equal(tx, policy.Get(blockChain, tx.Id, filtered: true)); + } + + Assert.Equal( + txs.ToHashSet(), + policy.Iterate(blockChain, filtered: true).ToHashSet() + ); + } + + private BlockChain MakeChainWithStagePolicy(NCStagePolicy stagePolicy) + { + BlockPolicySource blockPolicySource = new BlockPolicySource(); + IBlockPolicy policy = blockPolicySource.GetPolicy(); + BlockChain chain = + BlockChainHelper.MakeBlockChain( + blockRenderers: new[] { new BlockRenderer() }, + policy: policy, + stagePolicy: stagePolicy); + return chain; + } + } +} From 8b42945c8b2caf4a2329c60db43a4e0561732759 Mon Sep 17 00:00:00 2001 From: area363 Date: Tue, 7 Nov 2023 18:10:38 +0900 Subject: [PATCH 5/7] add test --- .../Policies/StagePolicyTest.cs | 75 ++++++++++++++++++- 1 file changed, 71 insertions(+), 4 deletions(-) diff --git a/NineChronicles.Headless.Tests/Policies/StagePolicyTest.cs b/NineChronicles.Headless.Tests/Policies/StagePolicyTest.cs index 506b134d7..e291e7f27 100644 --- a/NineChronicles.Headless.Tests/Policies/StagePolicyTest.cs +++ b/NineChronicles.Headless.Tests/Policies/StagePolicyTest.cs @@ -1,20 +1,26 @@ -namespace Lib9c.Tests +namespace NineChronicles.Headless.Tests.Policies { using System; using System.Collections.Generic; + using System.Collections.Immutable; using System.Linq; using System.Threading.Tasks; using Lib9c.Renderers; - using Lib9c.Tests.TestHelper; using Libplanet.Action; using Libplanet.Blockchain; using Libplanet.Blockchain.Policies; using Libplanet.Crypto; + using Libplanet.Store; + using Libplanet.Store.Trie; + using Libplanet.Types.Blocks; using Libplanet.Types.Tx; + using Nekoyume; using Nekoyume.Action; - using Nekoyume.Blockchain; + using Nekoyume.Action.Loader; using Nekoyume.Blockchain.Policy; - using Serilog.Core; + using Nekoyume.Model; + using Nekoyume.Model.State; + using NineChronicles.Headless.Policies; using Xunit; public class StagePolicyTest @@ -253,5 +259,66 @@ private BlockChain MakeChainWithStagePolicy(NCStagePolicy stagePolicy) stagePolicy: stagePolicy); return chain; } + + public static class BlockChainHelper + { + public static BlockChain MakeBlockChain( + BlockRenderer[] blockRenderers, + IBlockPolicy policy = null, + IStagePolicy stagePolicy = null, + IStore store = null, + IStateStore stateStore = null) + { + PrivateKey adminPrivateKey = new PrivateKey(); + + policy ??= new BlockPolicy(); + stagePolicy ??= new VolatileStagePolicy(); + store ??= new DefaultStore(null); + stateStore ??= new TrieStateStore(new DefaultKeyValueStore(null)); + Block genesis = MakeGenesisBlock(adminPrivateKey.ToAddress(), ImmutableHashSet
.Empty); + return BlockChain.Create( + policy, + stagePolicy, + store, + stateStore, + genesis, + new ActionEvaluator( + policyBlockActionGetter: _ => policy.BlockAction, + stateStore: stateStore, + actionTypeLoader: new NCActionLoader() + ), + renderers: blockRenderers); + } + + public static Block MakeGenesisBlock( + Address adminAddress, + IImmutableSet
activatedAddresses, + AuthorizedMinersState authorizedMinersState = null, + DateTimeOffset? timestamp = null, + PendingActivationState[] pendingActivations = null + ) + { + PrivateKey privateKey = new PrivateKey(); + if (pendingActivations is null) + { + var nonce = new byte[] { 0x00, 0x01, 0x02, 0x03 }; + (ActivationKey activationKey, PendingActivationState pendingActivation) = + ActivationKey.Create(privateKey, nonce); + pendingActivations = new[] { pendingActivation }; + } + + var sheets = TableSheetsImporter.ImportSheets(); + return BlockHelper.ProposeGenesisBlock( + sheets, + new GoldDistribution[0], + pendingActivations, + new AdminState(adminAddress, 1500000), + activatedAccounts: activatedAddresses, + isActivateAdminAddress: false, + credits: null, + privateKey: privateKey, + timestamp: timestamp ?? DateTimeOffset.MinValue); + } + } } } From 5719b65b49e004f1ce5106d3bb889ccf7cecdea1 Mon Sep 17 00:00:00 2001 From: area363 Date: Thu, 9 Nov 2023 10:00:47 +0900 Subject: [PATCH 6/7] bump lib9c --- Lib9c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib9c b/Lib9c index b671329c6..fefa24749 160000 --- a/Lib9c +++ b/Lib9c @@ -1 +1 @@ -Subproject commit b671329c641ed0cb00e5dc9b8e104b19532362b1 +Subproject commit fefa24749fe4815233da217b4f563c8d2f2befb9 From cbdc3889f1c824627914e6bc22c343fd469f046b Mon Sep 17 00:00:00 2001 From: area363 Date: Thu, 9 Nov 2023 11:24:43 +0900 Subject: [PATCH 7/7] bump lib9c to development --- Lib9c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib9c b/Lib9c index fefa24749..d6f420a0e 160000 --- a/Lib9c +++ b/Lib9c @@ -1 +1 @@ -Subproject commit fefa24749fe4815233da217b4f563c8d2f2befb9 +Subproject commit d6f420a0ea2c714e3546a4fc346d8bf1cddd8f5f