Beispiel #1
0
        public static Block <PolymorphicAction <ActionBase> > MineGenesisBlock(
            IDictionary <string, string> tableSheets,
            GoldDistribution[] goldDistributions,
            PendingActivationState[] pendingActivationStates,
            AdminState adminState,
            AuthorizedMinersState authorizedMinersState = null,
            IImmutableSet <Address> activatedAccounts   = null,
            bool isActivateAdminAddress  = false,
            IEnumerable <string> credits = null,
            int maximumTransactions      = 100,
            PrivateKey privateKey        = null
            )
        {
            if (!tableSheets.TryGetValue(nameof(GameConfigSheet), out var csv))
            {
                throw new KeyNotFoundException(nameof(GameConfigSheet));
            }
            var gameConfigState     = new GameConfigState(csv);
            var redeemCodeListSheet = new RedeemCodeListSheet();

            redeemCodeListSheet.Set(tableSheets[nameof(RedeemCodeListSheet)]);

            if (privateKey is null)
            {
                privateKey = new PrivateKey();
            }

            var ncg = new Currency("NCG", 2, privateKey.ToAddress());

            activatedAccounts = activatedAccounts ?? ImmutableHashSet <Address> .Empty;
            var initialStatesAction = new InitializeStates
                                      (
                rankingState: new RankingState(),
                shopState: new ShopState(),
                tableSheets: (Dictionary <string, string>)tableSheets,
                gameConfigState: gameConfigState,
                redeemCodeState: new RedeemCodeState(redeemCodeListSheet),
                adminAddressState: adminState,
                activatedAccountsState: new ActivatedAccountsState(
                    isActivateAdminAddress
                    ? activatedAccounts.Add(adminState.AdminAddress)
                    : activatedAccounts),
                goldCurrencyState: new GoldCurrencyState(ncg),
                goldDistributions: goldDistributions,
                pendingActivationStates: pendingActivationStates,
                authorizedMinersState: authorizedMinersState,
                creditsState: credits is null ? null : new CreditsState(credits)
                                      );
            var actions = new PolymorphicAction <ActionBase>[]
            {
                initialStatesAction,
            };
            var blockAction = new BlockPolicySource(Log.Logger).GetPolicy(5000000, maximumTransactions).BlockAction;

            return
                (BlockChain <PolymorphicAction <ActionBase> > .MakeGenesisBlock(
                     actions,
                     privateKey : privateKey,
                     blockAction : blockAction));
        }
Beispiel #2
0
        public void Tip(
            [Argument("STORE-TYPE")]
            StoreType storeType,
            [Argument("STORE-PATH")]
            string storePath)
        {
            if (!Directory.Exists(storePath))
            {
                throw new CommandExitedException($"The given STORE-PATH, {storePath} seems not existed.", -1);
            }

            IStagePolicy <NCAction> stagePolicy = new VolatileStagePolicy <PolymorphicAction <ActionBase> >();
            IBlockPolicy <NCAction> blockPolicy = new BlockPolicySource(Logger.None).GetPolicy();
            IStore                store         = storeType.CreateStore(storePath);
            var                   stateStore    = new TrieStateStore(new DefaultKeyValueStore(null));
            Block <NCAction>      genesisBlock  = store.GetGenesisBlock <NCAction>(blockPolicy.GetHashAlgorithm);
            BlockChain <NCAction> chain         = new BlockChain <NCAction>(
                blockPolicy,
                stagePolicy,
                store,
                stateStore,
                genesisBlock);

            _console.Out.WriteLine(Utils.SerializeHumanReadable(chain.Tip.Header));
            (store as IDisposable)?.Dispose();
        }
Beispiel #3
0
        public void DoesTransactionFollowsPolicyWithEmpty()
        {
            var adminPrivateKey = new PrivateKey();
            var adminAddress = new Address(adminPrivateKey.PublicKey);
            var blockPolicySource = new BlockPolicySource(Logger.None);
            IBlockPolicy<PolymorphicAction<ActionBase>> policy = blockPolicySource.GetPolicy(10000, 100);
            Block<PolymorphicAction<ActionBase>> genesis = MakeGenesisBlock(adminAddress, ImmutableHashSet<Address>.Empty);

            using var store = new DefaultStore(null);
            using var stateStore = new TrieStateStore(new DefaultKeyValueStore(null), new DefaultKeyValueStore(null));
            var blockChain = new BlockChain<PolymorphicAction<ActionBase>>(
                policy,
                store,
                stateStore,
                genesis,
                renderers: new[] { blockPolicySource.BlockRenderer }
            );
            Transaction<PolymorphicAction<ActionBase>> tx = Transaction<PolymorphicAction<ActionBase>>.Create(
                0,
                new PrivateKey(),
                genesis.Hash,
                new PolymorphicAction<ActionBase>[] { });

            Assert.True(policy.DoesTransactionFollowsPolicy(tx, blockChain));
        }
        public void Tip(
            [Argument("STORE-TYPE")]
            StoreType storeType,
            [Argument("STORE-PATH")]
            string storePath)
        {
            if (!Directory.Exists(storePath))
            {
                throw new CommandExitedException($"The given STORE-PATH, {storePath} seems not existed.", -1);
            }

            const int minimumDifficulty = 5000000, maximumTransactions = 100;
            IStagePolicy <NCAction> stagePolicy = new VolatileStagePolicy <PolymorphicAction <ActionBase> >();
            IBlockPolicy <NCAction> blockPolicy = new BlockPolicySource(Logger.None).GetPolicy(minimumDifficulty, maximumTransactions);
            IStore                store         = storeType.CreateStore(storePath);
            Block <NCAction>      genesisBlock  = store.GetGenesisBlock <NCAction>();
            BlockChain <NCAction> chain         = new BlockChain <NCAction>(
                blockPolicy,
                stagePolicy,
                store,
                new NoOpStateStore(),
                genesisBlock);

            _console.Out.WriteLine(JsonSerializer.Serialize(chain.Tip.Header));
        }
Beispiel #5
0
        public void ValidateNextBlockTxWithAuthorizedMiners()
        {
            var adminPrivateKey           = new PrivateKey();
            var adminAddress              = adminPrivateKey.ToAddress();
            var authorizedMinerPrivateKey = new PrivateKey();

            (ActivationKey ak, PendingActivationState ps) = ActivationKey.Create(
                new PrivateKey(),
                new byte[] { 0x00, 0x01 }
                );

            var blockPolicySource = new BlockPolicySource(Logger.None);
            IBlockPolicy <PolymorphicAction <ActionBase> > policy = blockPolicySource.GetPolicy(
                minimumDifficulty: 10_000,
                hashAlgorithmTypePolicy: null,
                maxBlockBytesPolicy: null,
                minTransactionsPerBlockPolicy: null,
                maxTransactionsPerBlockPolicy: null,
                maxTransactionsPerSignerPerBlockPolicy: null,
                authorizedMinersPolicy: AuthorizedMinersPolicy
                .Default
                .Add(new SpannedSubPolicy <ImmutableHashSet <Address> >(
                         startIndex: 0,
                         endIndex: 10,
                         filter: index => index % 5 == 0,
                         value: new Address[] { authorizedMinerPrivateKey.ToAddress() }
                         .ToImmutableHashSet())),
                permissionedMinersPolicy: null);
            IStagePolicy <PolymorphicAction <ActionBase> > stagePolicy =
                new VolatileStagePolicy <PolymorphicAction <ActionBase> >();
            Block <PolymorphicAction <ActionBase> > genesis = MakeGenesisBlock(
                adminAddress,
                ImmutableHashSet.Create(adminAddress),
                pendingActivations: new[] { ps }
                );

            using var store      = new DefaultStore(null);
            using var stateStore = new TrieStateStore(new DefaultKeyValueStore(null));
            var blockChain = new BlockChain <PolymorphicAction <ActionBase> >(
                policy,
                stagePolicy,
                store,
                stateStore,
                genesis,
                renderers: new[] { blockPolicySource.BlockRenderer }
                );

            Transaction <PolymorphicAction <ActionBase> > txFromAuthorizedMiner =
                Transaction <PolymorphicAction <ActionBase> > .Create(
                    0,
                    authorizedMinerPrivateKey,
                    genesis.Hash,
                    new PolymorphicAction <ActionBase>[] { ak.CreateActivateAccount(new byte[] { 0x00, 0x01 }) }
                    );

            // Deny tx even if contains valid activation key.
            Assert.NotNull(policy.ValidateNextBlockTx(blockChain, txFromAuthorizedMiner));
        }
        internal static IBlockPolicy <NCAction> GetBlockPolicy(NetworkType networkType)
        {
            var source = new BlockPolicySource(Log.Logger, LogEventLevel.Debug);

            return(networkType switch
            {
                NetworkType.Main => source.GetPolicy(),
                NetworkType.Internal => source.GetInternalPolicy(),
                NetworkType.Test => source.GetTestPolicy(),
                _ => throw new ArgumentOutOfRangeException(nameof(networkType), networkType, null),
            });
Beispiel #7
0
        public static (BlockChain <NCAction> Chain, IStore Store) GetBlockChain(
            ILogger logger,
            string storePath,
            bool monorocksdb = false,
            Guid?chainId     = null
            )
        {
            var policySource = new BlockPolicySource(logger);
            IBlockPolicy <NCAction> policy      = policySource.GetPolicy();
            IStagePolicy <NCAction> stagePolicy = new VolatileStagePolicy <NCAction>();
            IStore store
                = monorocksdb
                ? (IStore) new MonoRocksDBStore(storePath)
                : new RocksDBStore(storePath);
            IKeyValueStore stateKeyValueStore =
                new RocksDBKeyValueStore(Path.Combine(storePath, "states"));
            IStateStore stateStore = new TrieStateStore(stateKeyValueStore);
            Guid        chainIdValue
                = chainId ??
                  store.GetCanonicalChainId() ??
                  throw new CommandExitedException(
                            "No canonical chain ID.  Available chain IDs:\n    " +
                            string.Join("\n    ", store.ListChainIds()),
                            1);

            BlockHash genesisBlockHash;

            try
            {
                genesisBlockHash = store.IterateIndexes(chainIdValue).First();
            }
            catch (InvalidOperationException)
            {
                throw new CommandExitedException(
                          $"The chain {chainIdValue} seems empty; try with another chain ID:\n    " +
                          string.Join("\n    ", store.ListChainIds()),
                          1
                          );
            }
            Block <NCAction> genesis = store.GetBlock <NCAction>(
                policy.GetHashAlgorithm,
                genesisBlockHash
                );
            BlockChain <NCAction> chain = new BlockChain <NCAction>(
                policy,
                stagePolicy,
                store,
                stateStore,
                genesis
                );

            return(chain, store);
        }
Beispiel #8
0
        public async void EarnMiningGoldWhenSuccessMining()
        {
            var adminPrivateKey           = new PrivateKey();
            var adminAddress              = adminPrivateKey.ToAddress();
            var authorizedMinerPrivateKey = new PrivateKey();

            (ActivationKey ak, PendingActivationState ps) = ActivationKey.Create(
                new PrivateKey(),
                new byte[] { 0x00, 0x01 }
                );

            var blockPolicySource = new BlockPolicySource(Logger.None);
            IBlockPolicy <PolymorphicAction <ActionBase> > policy = blockPolicySource.GetPolicy(
                10_000, null, null, null, null, null, null, null);
            IStagePolicy <PolymorphicAction <ActionBase> > stagePolicy =
                new VolatileStagePolicy <PolymorphicAction <ActionBase> >();
            Block <PolymorphicAction <ActionBase> > genesis = MakeGenesisBlock(
                adminAddress,
                ImmutableHashSet.Create(adminAddress),
                new AuthorizedMinersState(
                    new[] { authorizedMinerPrivateKey.ToAddress() },
                    5,
                    10
                    ),
                pendingActivations: new[] { ps }
                );

            using var store      = new DefaultStore(null);
            using var stateStore = new TrieStateStore(new DefaultKeyValueStore(null));
            var blockChain = new BlockChain <PolymorphicAction <ActionBase> >(
                policy,
                stagePolicy,
                store,
                stateStore,
                genesis,
                renderers: new[] { blockPolicySource.BlockRenderer }
                );

            blockChain.MakeTransaction(
                adminPrivateKey,
                new PolymorphicAction <ActionBase>[] { new DailyReward(), }
                );

            await blockChain.MineBlock(adminPrivateKey);

            FungibleAssetValue actualBalance   = blockChain.GetBalance(adminAddress, _currency);
            FungibleAssetValue expectedBalance = new FungibleAssetValue(_currency, 10, 0);

            Assert.True(expectedBalance.Equals(actualBalance));
        }
        public async Task Inspect(StoreType storeType)
        {
            Block <NCAction> genesisBlock = BlockChain <NCAction> .MakeGenesisBlock(
                HashAlgorithmType.Of <SHA256>()
                );

            IStore store   = storeType.CreateStore(_storePath2);
            Guid   chainId = Guid.NewGuid();

            store.SetCanonicalChainId(chainId);
            store.PutBlock(genesisBlock);
            store.AppendIndex(chainId, genesisBlock.Hash);
            var stateStore = new TrieStateStore(new DefaultKeyValueStore(null));

            IStagePolicy <NCAction> stagePolicy = new VolatileStagePolicy <PolymorphicAction <ActionBase> >();
            IBlockPolicy <NCAction> blockPolicy = new BlockPolicySource(Logger.None).GetPolicy();
            BlockChain <NCAction>   chain       = new BlockChain <NCAction>(
                blockPolicy,
                stagePolicy,
                store,
                stateStore,
                genesisBlock);

            var action = new HackAndSlash
            {
                costumes      = new List <Guid>(),
                equipments    = new List <Guid>(),
                foods         = new List <Guid>(),
                worldId       = 1,
                stageId       = 1,
                avatarAddress = default
            };

            var minerKey = new PrivateKey();

            chain.MakeTransaction(minerKey, new PolymorphicAction <ActionBase>[] { action });
            await chain.MineBlock(minerKey, DateTimeOffset.Now);

            store.Dispose();

            _command.Inspect(storeType, _storePath2);
            List <double> output = _console.Out.ToString().Split("\n")[1]
                                   .Split(',').Select(double.Parse).ToList();
            var totalTxCount      = Convert.ToInt32(output[2]);
            var hackandslashCount = Convert.ToInt32(output[3]);

            Assert.Equal(1, totalTxCount);
            Assert.Equal(1, hackandslashCount);
        }
Beispiel #10
0
        public void DoesTransactionFollowsPolicyWithAuthorizedMiners()
        {
            var adminPrivateKey           = new PrivateKey();
            var adminAddress              = adminPrivateKey.ToAddress();
            var authorizedMinerPrivateKey = new PrivateKey();

            (ActivationKey ak, PendingActivationState ps) = ActivationKey.Create(
                new PrivateKey(),
                new byte[] { 0x00, 0x01 }
                );

            var blockPolicySource = new BlockPolicySource(Logger.None);
            IBlockPolicy <PolymorphicAction <ActionBase> > policy      = blockPolicySource.GetPolicy(10000, 100);
            IStagePolicy <PolymorphicAction <ActionBase> > stagePolicy =
                new VolatileStagePolicy <PolymorphicAction <ActionBase> >();
            Block <PolymorphicAction <ActionBase> > genesis = MakeGenesisBlock(
                adminAddress,
                ImmutableHashSet.Create(adminAddress),
                new AuthorizedMinersState(
                    new[] { authorizedMinerPrivateKey.ToAddress() },
                    5,
                    10
                    ),
                pendingActivations: new[] { ps }
                );

            using var store      = new DefaultStore(null);
            using var stateStore = new TrieStateStore(new DefaultKeyValueStore(null), new DefaultKeyValueStore(null));
            var blockChain = new BlockChain <PolymorphicAction <ActionBase> >(
                policy,
                stagePolicy,
                store,
                stateStore,
                genesis,
                renderers: new[] { blockPolicySource.BlockRenderer }
                );

            Transaction <PolymorphicAction <ActionBase> > txFromAuthorizedMiner =
                Transaction <PolymorphicAction <ActionBase> > .Create(
                    0,
                    authorizedMinerPrivateKey,
                    genesis.Hash,
                    new PolymorphicAction <ActionBase>[] { ak.CreateActivateAccount(new byte[] { 0x00, 0x01 }) }
                    );

            // Deny tx even if contains valid activation key.
            Assert.False(policy.DoesTransactionFollowsPolicy(txFromAuthorizedMiner, blockChain));
        }
Beispiel #11
0
        public void MustNotIncludeBlockActionAtTransaction()
        {
            var adminPrivateKey           = new PrivateKey();
            var adminAddress              = adminPrivateKey.ToAddress();
            var authorizedMinerPrivateKey = new PrivateKey();

            (ActivationKey ak, PendingActivationState ps) = ActivationKey.Create(
                new PrivateKey(),
                new byte[] { 0x00, 0x01 }
                );

            var blockPolicySource = new BlockPolicySource(Logger.None);
            IBlockPolicy <PolymorphicAction <ActionBase> > policy = blockPolicySource.GetPolicy(
                10_000, null, null, null, null, null, null, null);
            IStagePolicy <PolymorphicAction <ActionBase> > stagePolicy =
                new VolatileStagePolicy <PolymorphicAction <ActionBase> >();
            Block <PolymorphicAction <ActionBase> > genesis = MakeGenesisBlock(
                adminAddress,
                ImmutableHashSet.Create(adminAddress),
                new AuthorizedMinersState(
                    new[] { authorizedMinerPrivateKey.ToAddress() },
                    5,
                    10
                    ),
                pendingActivations: new[] { ps }
                );

            using var store      = new DefaultStore(null);
            using var stateStore = new TrieStateStore(new DefaultKeyValueStore(null));
            var blockChain = new BlockChain <PolymorphicAction <ActionBase> >(
                policy,
                stagePolicy,
                store,
                stateStore,
                genesis,
                renderers: new[] { blockPolicySource.BlockRenderer }
                );

            Assert.Throws <MissingActionTypeException>(() =>
            {
                blockChain.MakeTransaction(
                    adminPrivateKey,
                    new PolymorphicAction <ActionBase>[] { new RewardGold() }
                    );
            });
        }
Beispiel #12
0
        public async Task Proof()
        {
            using var store      = new DefaultStore(null);
            using var stateStore = new TrieStateStore(new DefaultKeyValueStore(null));
            var blockPolicySource = new BlockPolicySource(Logger.None);
            var genesis           = BlockChain <NCAction> .MakeGenesisBlock(HashAlgorithmType.Of <SHA256>());

            var blockChain = new BlockChain <NCAction>(
                blockPolicySource.GetPolicy(10_000, null, null, null, null, null, null),
                new VolatileStagePolicy <NCAction>(),
                store,
                stateStore,
                genesis,
                renderers: new[] { blockPolicySource.BlockRenderer }
                );

            var minerKey           = new PrivateKey();
            var miner              = new Miner(blockChain, null, minerKey, false);
            Block <NCAction> mined = await miner.MineBlockAsync(default);
Beispiel #13
0
        public async Task GetNextBlockDifficultyWithAuthorizedMinersPolicy()
        {
            var adminPrivateKey = new PrivateKey();
            var adminAddress    = adminPrivateKey.ToAddress();
            var minerKey        = new PrivateKey();
            var miners          = new[] { minerKey.ToAddress() };

            var blockPolicySource = new BlockPolicySource(Logger.None);
            IBlockPolicy <PolymorphicAction <ActionBase> > policy = blockPolicySource.GetPolicy(
                minimumDifficulty: 4096,
                hashAlgorithmTypePolicy: null,
                maxBlockBytesPolicy: null,
                minTransactionsPerBlockPolicy: null,
                maxTransactionsPerBlockPolicy: null,
                maxTransactionsPerSignerPerBlockPolicy: null,
                authorizedMinersPolicy: AuthorizedMinersPolicy
                .Default
                .Add(new SpannedSubPolicy <ImmutableHashSet <Address> >(
                         startIndex: 0,
                         endIndex: 6,
                         filter: index => index % 2 == 0,
                         value: miners.ToImmutableHashSet())),
                permissionedMinersPolicy: null);
            IStagePolicy <PolymorphicAction <ActionBase> > stagePolicy =
                new VolatileStagePolicy <PolymorphicAction <ActionBase> >();
            Block <PolymorphicAction <ActionBase> > genesis = MakeGenesisBlock(
                adminAddress,
                ImmutableHashSet <Address> .Empty);

            using var store      = new DefaultStore(null);
            using var stateStore = new TrieStateStore(new DefaultKeyValueStore(null));
            var blockChain = new BlockChain <PolymorphicAction <ActionBase> >(
                policy,
                stagePolicy,
                store,
                stateStore,
                genesis,
                renderers: new[] { blockPolicySource.BlockRenderer }
                );
            var minerObj = new Miner(blockChain, null, minerKey);

            var dateTimeOffset = DateTimeOffset.MinValue;

            // Index 1
            Assert.Equal(4096, policy.GetNextBlockDifficulty(blockChain));
            blockChain.MakeTransaction(
                adminPrivateKey,
                new PolymorphicAction <ActionBase>[] { new DailyReward(), }
                );
            dateTimeOffset += TimeSpan.FromSeconds(1);
            await blockChain.MineBlock(minerKey, dateTimeOffset);

            // Index 2, target index
            Assert.Equal(4096, policy.GetNextBlockDifficulty(blockChain));

            minerObj.StageProofTransaction();
            dateTimeOffset += TimeSpan.FromSeconds(1);
            await blockChain.MineBlock(minerKey, dateTimeOffset);

            // Index 3
            Assert.Equal(4096, policy.GetNextBlockDifficulty(blockChain));
            blockChain.MakeTransaction(
                adminPrivateKey,
                new PolymorphicAction <ActionBase>[] { new DailyReward(), }
                );
            dateTimeOffset += TimeSpan.FromSeconds(1);
            await blockChain.MineBlock(minerKey, dateTimeOffset);

            // Index 4, target index
            Assert.Equal(4096, policy.GetNextBlockDifficulty(blockChain));

            minerObj.StageProofTransaction();
            dateTimeOffset += TimeSpan.FromSeconds(1);
            await blockChain.MineBlock(minerKey, dateTimeOffset);

            // Index 5
            Assert.Equal(4096, policy.GetNextBlockDifficulty(blockChain));

            blockChain.MakeTransaction(
                adminPrivateKey,
                new PolymorphicAction <ActionBase>[] { new DailyReward(), }
                );
            dateTimeOffset += TimeSpan.FromSeconds(1);
            await blockChain.MineBlock(minerKey, dateTimeOffset);

            // Index 6, target index
            Assert.Equal(4096, policy.GetNextBlockDifficulty(blockChain));

            minerObj.StageProofTransaction();
            dateTimeOffset += TimeSpan.FromSeconds(1);
            await blockChain.MineBlock(minerKey, dateTimeOffset);

            // Index 7
            Assert.Equal(4098, policy.GetNextBlockDifficulty(blockChain));
            blockChain.MakeTransaction(
                adminPrivateKey,
                new PolymorphicAction <ActionBase>[] { new DailyReward(), }
                );
            dateTimeOffset += TimeSpan.FromSeconds(1);
            await blockChain.MineBlock(minerKey, dateTimeOffset);

            // Index 8
            Assert.Equal(4100, policy.GetNextBlockDifficulty(blockChain));
            blockChain.MakeTransaction(
                adminPrivateKey,
                new PolymorphicAction <ActionBase>[] { new DailyReward(), }
                );
            dateTimeOffset += TimeSpan.FromSeconds(1);
            await blockChain.MineBlock(minerKey, dateTimeOffset);

            // Index 9
            Assert.Equal(4102, policy.GetNextBlockDifficulty(blockChain));
            blockChain.MakeTransaction(
                adminPrivateKey,
                new PolymorphicAction <ActionBase>[] { new DailyReward(), }
                );
            dateTimeOffset += TimeSpan.FromSeconds(1);
            await blockChain.MineBlock(minerKey, dateTimeOffset);

            // Index 10
            Assert.Equal(4104, policy.GetNextBlockDifficulty(blockChain));
            blockChain.MakeTransaction(
                adminPrivateKey,
                new PolymorphicAction <ActionBase>[] { new DailyReward(), }
                );
            dateTimeOffset += TimeSpan.FromSeconds(1);
            await blockChain.MineBlock(minerKey, dateTimeOffset);

            // Index 11
            Assert.Equal(4106, policy.GetNextBlockDifficulty(blockChain));
            blockChain.MakeTransaction(
                adminPrivateKey,
                new PolymorphicAction <ActionBase>[] { new DailyReward(), }
                );
            dateTimeOffset += TimeSpan.FromSeconds(20);
            await blockChain.MineBlock(minerKey, dateTimeOffset);

            // Index 12
            Assert.Equal(4104, policy.GetNextBlockDifficulty(blockChain));
        }
Beispiel #14
0
        public async Task ValidateNextBlockWithAuthorizedMinersPolicy()
        {
            var adminPrivateKey = new PrivateKey();
            var adminAddress    = adminPrivateKey.ToAddress();
            var minerKeys       = new[] { new PrivateKey(), new PrivateKey() };

            Address[] miners   = minerKeys.Select(AddressExtensions.ToAddress).ToArray();
            var       stranger = new PrivateKey();

            var blockPolicySource = new BlockPolicySource(Logger.None);
            IBlockPolicy <PolymorphicAction <ActionBase> > policy = blockPolicySource.GetPolicy(
                minimumDifficulty: 10_000,
                hashAlgorithmTypePolicy: null,
                maxBlockBytesPolicy: null,
                minTransactionsPerBlockPolicy: null,
                maxTransactionsPerBlockPolicy: null,
                maxTransactionsPerSignerPerBlockPolicy: null,
                authorizedMinersPolicy: AuthorizedMinersPolicy
                .Default
                .Add(new SpannedSubPolicy <ImmutableHashSet <Address> >(
                         startIndex: 0,
                         endIndex: 4,
                         filter: index => index % 2 == 0,
                         value: miners.ToImmutableHashSet())),
                permissionedMinersPolicy: null);
            IStagePolicy <PolymorphicAction <ActionBase> > stagePolicy =
                new VolatileStagePolicy <PolymorphicAction <ActionBase> >();
            Block <PolymorphicAction <ActionBase> > genesis = MakeGenesisBlock(
                adminAddress,
                ImmutableHashSet <Address> .Empty);

            using var store      = new DefaultStore(null);
            using var stateStore = new TrieStateStore(new DefaultKeyValueStore(null));
            var blockChain = new BlockChain <PolymorphicAction <ActionBase> >(
                policy,
                stagePolicy,
                store,
                stateStore,
                genesis,
                renderers: new[] { blockPolicySource.BlockRenderer }
                );

            blockChain.MakeTransaction(
                adminPrivateKey,
                new PolymorphicAction <ActionBase>[] { new DailyReward(), }
                );

            // Index 1. Anyone can mine.
            await blockChain.MineBlock(stranger);

            // Index 2. Only authorized miner can mine.
            await Assert.ThrowsAsync <BlockPolicyViolationException>(async() =>
            {
                await blockChain.MineBlock(stranger);
            });

            // Old proof mining still works.
            new Miner(blockChain, null, minerKeys[0]).StageProofTransaction();
            await blockChain.MineBlock(minerKeys[0]);

            // Index 3. Anyone can mine.
            blockChain.MakeTransaction(
                adminPrivateKey,
                new PolymorphicAction <ActionBase>[] { new DailyReward(), }
                );
            await blockChain.MineBlock(stranger);

            // Index 4. Again, only authorized miner can mine.
            blockChain.MakeTransaction(
                adminPrivateKey,
                new PolymorphicAction <ActionBase>[] { new DailyReward(), }
                );
            await Assert.ThrowsAsync <BlockPolicyViolationException>(async() =>
            {
                await blockChain.MineBlock(stranger);
            });

            // No proof is required.
            blockChain.MakeTransaction(
                adminPrivateKey,
                new PolymorphicAction <ActionBase>[] { new DailyReward(), }
                );
            await blockChain.MineBlock(minerKeys[1]);

            // Index 5, 6. Anyone can mine.
            await blockChain.MineBlock(stranger);

            blockChain.MakeTransaction(
                adminPrivateKey,
                new PolymorphicAction <ActionBase>[] { new DailyReward(), }
                );
            await blockChain.MineBlock(stranger);
        }
Beispiel #15
0
        public async Task ValidateNextBlockWithAuthorizedMinersState()
        {
            var adminPrivateKey = new PrivateKey();
            var adminAddress = adminPrivateKey.ToAddress();
            var miners = new[]
            {
                new Address(
                    new byte[]
                    {
                        0x01, 0x00, 0x00, 0x00, 0x00,
                        0x00, 0x00, 0x00, 0x00, 0x00,
                        0x00, 0x00, 0x00, 0x00, 0x00,
                        0x00, 0x00, 0x00, 0x00, 0x00,
                    }
                ),
                new Address(
                    new byte[]
                    {
                        0x02, 0x00, 0x00, 0x00, 0x00,
                        0x00, 0x00, 0x00, 0x00, 0x00,
                        0x00, 0x00, 0x00, 0x00, 0x00,
                        0x00, 0x00, 0x00, 0x00, 0x00,
                    }
                ),
            };
            var stranger = new Address(
                new byte[]
                {
                    0x03, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00,
                    0x00, 0x00, 0x00, 0x00, 0x00,
                }
            );

            var blockPolicySource = new BlockPolicySource(Logger.None);
            IBlockPolicy<PolymorphicAction<ActionBase>> policy = blockPolicySource.GetPolicy(10000, 100);
            Block<PolymorphicAction<ActionBase>> genesis = MakeGenesisBlock(
                adminAddress,
                ImmutableHashSet<Address>.Empty,
                new AuthorizedMinersState(miners, 2, 4)
            );
            using var store = new DefaultStore(null);
            using var stateStore = new TrieStateStore(new DefaultKeyValueStore(null), new DefaultKeyValueStore(null));
            var blockChain = new BlockChain<PolymorphicAction<ActionBase>>(
                policy,
                store,
                stateStore,
                genesis,
                renderers: new[] { blockPolicySource.BlockRenderer }
            );

            if (policy is BlockPolicy bp)
            {
                bp.AuthorizedMinersState = new AuthorizedMinersState(
                    (Dictionary)blockChain.GetState(AuthorizedMinersState.Address)
                    );
            }

            await blockChain.MineBlock(stranger);

            await Assert.ThrowsAsync<InvalidMinerException>(async () =>
            {
                await blockChain.MineBlock(stranger);
            });

            await blockChain.MineBlock(miners[0]);

            // it's okay because next block index is 3
            await blockChain.MineBlock(stranger);

            // it isn't :(
            await Assert.ThrowsAsync<InvalidMinerException>(async () =>
            {
                await blockChain.MineBlock(stranger);
            });

            await blockChain.MineBlock(miners[1]);

            // it's okay because block index exceeds limitations.
            await blockChain.MineBlock(stranger);
        }
Beispiel #16
0
        public void IsAllowedtoMine()
        {
            var nonce = new byte[] { 0x00, 0x01, 0x02, 0x03 };
            var authorizedMinerKey   = new PrivateKey();
            var permissionedMinerKey = new PrivateKey();
            var someMinerKey         = new PrivateKey();
            var addresses            = new Address[]
            {
                authorizedMinerKey.ToAddress(),
                permissionedMinerKey.ToAddress(),
                someMinerKey.ToAddress(),
            };
            var pendingActivations = new[]
            {
                authorizedMinerKey,
                permissionedMinerKey,
                someMinerKey,
            }.Select(key => ActivationKey.Create(key, nonce).Item2).ToArray();

            // This creates genesis with _privateKey as its miner.
            Block <PolymorphicAction <ActionBase> > genesis = MakeGenesisBlock(
                default(Address),
                ImmutableHashSet <Address> .Empty,
                pendingActivations: pendingActivations);

            using var store      = new DefaultStore(null);
            using var stateStore = new TrieStateStore(new DefaultKeyValueStore(null));
            var blockPolicySource = new BlockPolicySource(Logger.None);

            var policy = (BlockPolicy)blockPolicySource.GetPolicy(
                minimumDifficulty: 10_000,
                hashAlgorithmTypePolicy: null,
                maxBlockBytesPolicy: null,
                minTransactionsPerBlockPolicy: null,
                maxTransactionsPerBlockPolicy: null,
                maxTransactionsPerSignerPerBlockPolicy: null,
                authorizedMinersPolicy: AuthorizedMinersPolicy
                .Default
                .Add(new SpannedSubPolicy <ImmutableHashSet <Address> >(
                         startIndex: 0,
                         endIndex: 10,
                         filter: index => index % 2 == 0,
                         value: new Address[] { authorizedMinerKey.ToAddress() }
                         .ToImmutableHashSet())),
                permissionedMinersPolicy: PermissionedMinersPolicy
                .Default
                .Add(new SpannedSubPolicy <ImmutableHashSet <Address> >(
                         startIndex: 5,
                         endIndex: 20,
                         filter: index => index % 3 == 0,
                         value: new Address[] { permissionedMinerKey.ToAddress() }
                         .ToImmutableHashSet())));

            // For genesis, any miner is allowed.
            Assert.All(addresses, address => Assert.True(policy.IsAllowedToMine(address, 0)));
            // Same goes for the next one.
            Assert.All(addresses, address => Assert.True(policy.IsAllowedToMine(address, 1)));
            // Only authorized miner should be allowed for index 2.
            Assert.True(policy.IsAllowedToMine(authorizedMinerKey.ToAddress(), 2));
            Assert.False(policy.IsAllowedToMine(permissionedMinerKey.ToAddress(), 2));
            Assert.False(policy.IsAllowedToMine(someMinerKey.ToAddress(), 2));
            // Only authorized miner should be allowed for index 6.
            Assert.True(policy.IsAllowedToMine(authorizedMinerKey.ToAddress(), 6));
            Assert.False(policy.IsAllowedToMine(permissionedMinerKey.ToAddress(), 6));
            Assert.False(policy.IsAllowedToMine(someMinerKey.ToAddress(), 6));
            // Any miner should be able to mine for index 7.
            Assert.True(policy.IsAllowedToMine(authorizedMinerKey.ToAddress(), 7));
            Assert.True(policy.IsAllowedToMine(permissionedMinerKey.ToAddress(), 7));
            Assert.True(policy.IsAllowedToMine(someMinerKey.ToAddress(), 7));
            // Only permissioned miner should be allowed for index 9.
            Assert.False(policy.IsAllowedToMine(authorizedMinerKey.ToAddress(), 9));
            Assert.True(policy.IsAllowedToMine(permissionedMinerKey.ToAddress(), 9));
            Assert.False(policy.IsAllowedToMine(someMinerKey.ToAddress(), 9));
            // Only permissioned miner should be allowed for index 12.
            Assert.False(policy.IsAllowedToMine(authorizedMinerKey.ToAddress(), 12));
            Assert.True(policy.IsAllowedToMine(permissionedMinerKey.ToAddress(), 12));
            Assert.False(policy.IsAllowedToMine(someMinerKey.ToAddress(), 12));
            // Any miner should be able to mine 24.
            Assert.True(policy.IsAllowedToMine(authorizedMinerKey.ToAddress(), 24));
            Assert.True(policy.IsAllowedToMine(permissionedMinerKey.ToAddress(), 24));
            Assert.True(policy.IsAllowedToMine(someMinerKey.ToAddress(), 24));
        }
Beispiel #17
0
        public async Task PermissionedBlockPolicy()
        {
            // This creates genesis with _privateKey as its miner.
            var nonce = new byte[] { 0x00, 0x01, 0x02, 0x03 };
            var permissionedMinerKey    = new PrivateKey();
            var nonPermissionedMinerKey = new PrivateKey();
            var pendingActivations      = new[]
            {
                permissionedMinerKey,
                nonPermissionedMinerKey,
            }.Select(key => ActivationKey.Create(key, nonce).Item2).ToArray();

            Block <PolymorphicAction <ActionBase> > genesis = MakeGenesisBlock(
                default(Address),
                ImmutableHashSet <Address> .Empty,
                pendingActivations: pendingActivations);

            using var store      = new DefaultStore(null);
            using var stateStore = new TrieStateStore(new DefaultKeyValueStore(null));
            var blockPolicySource = new BlockPolicySource(Logger.None);
            var blockChain        = new BlockChain <PolymorphicAction <ActionBase> >(
                blockPolicySource.GetPolicy(
                    minimumDifficulty: 10_000,
                    hashAlgorithmTypePolicy: null,
                    maxBlockBytesPolicy: null,
                    minTransactionsPerBlockPolicy: null,
                    maxTransactionsPerBlockPolicy: null,
                    maxTransactionsPerSignerPerBlockPolicy: null,
                    authorizedMinersPolicy: null,
                    permissionedMinersPolicy: PermissionedMinersPolicy
                    .Default
                    .Add(new SpannedSubPolicy <ImmutableHashSet <Address> >(
                             startIndex: 1,
                             endIndex: null,
                             filter: null,
                             value: new Address[] { permissionedMinerKey.ToAddress() }
                             .ToImmutableHashSet()))),
                new VolatileStagePolicy <PolymorphicAction <ActionBase> >(),
                store,
                stateStore,
                genesis,
                renderers: new[] { blockPolicySource.BlockRenderer }
                );

            // Old proof mining is still allowed.
            blockChain.StageTransaction(Transaction <PolymorphicAction <ActionBase> > .Create(
                                            0,
                                            permissionedMinerKey,
                                            genesis.Hash,
                                            new PolymorphicAction <ActionBase>[] { }
                                            ));
            await blockChain.MineBlock(permissionedMinerKey);

            // Bad proof can also be mined.
            blockChain.StageTransaction(Transaction <PolymorphicAction <ActionBase> > .Create(
                                            0,
                                            nonPermissionedMinerKey,
                                            genesis.Hash,
                                            new PolymorphicAction <ActionBase>[] { }
                                            ));
            await blockChain.MineBlock(permissionedMinerKey);

            await blockChain.MineBlock(permissionedMinerKey);

            // Error, it isn't permissioned miner.
            await Assert.ThrowsAsync <BlockPolicyViolationException>(
                () => blockChain.MineBlock(nonPermissionedMinerKey));
        }
Beispiel #18
0
        public NineChroniclesNodeService(
            LibplanetNodeServiceProperties <NineChroniclesActionType> properties,
            RpcNodeServiceProperties?rpcNodeServiceProperties,
            Progress <PreloadState> preloadProgress = null,
            bool ignoreBootstrapFailure             = false,
            bool strictRendering = false,
            bool isDev           = false,
            int blockInterval    = 10000,
            int reorgInterval    = 0
            )
        {
            Properties    = properties;
            RpcProperties = rpcNodeServiceProperties;

            try
            {
                Libplanet.Crypto.CryptoConfig.CryptoBackend = new Secp256K1CryptoBackend <SHA256>();
                Log.Debug("Secp256K1CryptoBackend initialized.");
            }
            catch (Exception e)
            {
                Log.Error("Secp256K1CryptoBackend initialize failed. Use default backend. {e}", e);
            }

            var blockPolicySource = new BlockPolicySource(Log.Logger, LogEventLevel.Debug);
            // BlockPolicy shared through Lib9c.
            IBlockPolicy <PolymorphicAction <ActionBase> > blockPolicy = null;
            // Policies for dev mode.
            IBlockPolicy <PolymorphicAction <ActionBase> > easyPolicy = null;
            IBlockPolicy <PolymorphicAction <ActionBase> > hardPolicy = null;

            if (isDev)
            {
                easyPolicy = new ReorgPolicy(new RewardGold(), 1);
                hardPolicy = new ReorgPolicy(new RewardGold(), 2);
            }
            else
            {
                blockPolicy = blockPolicySource.GetPolicy(properties.MinimumDifficulty, properties.MaximumTransactions);
            }

            BlockRenderer      = blockPolicySource.BlockRenderer;
            ActionRenderer     = blockPolicySource.ActionRenderer;
            ExceptionRenderer  = new ExceptionRenderer();
            NodeStatusRenderer = new NodeStatusRenderer();
            var renderers      = new List <IRenderer <NineChroniclesActionType> >();
            var strictRenderer = new StrictRenderer(onError: exc =>
                                                    ExceptionRenderer.RenderException(
                                                        RPCException.InvalidRenderException,
                                                        exc.Message.Split("\n")[0]
                                                        )
                                                    );

            if (Properties.Render)
            {
                renderers.Add(blockPolicySource.BlockRenderer);
                renderers.Add(blockPolicySource.LoggedActionRenderer);
            }
            else
            {
                renderers.Add(blockPolicySource.LoggedBlockRenderer);
            }

            if (strictRendering)
            {
                Log.Debug(
                    $"Strict rendering is on. Add {nameof(StrictRenderer)}.");
                renderers.Add(strictRenderer);
            }

            async Task minerLoopAction(
                BlockChain <NineChroniclesActionType> chain,
                Swarm <NineChroniclesActionType> swarm,
                PrivateKey privateKey,
                CancellationToken cancellationToken)
            {
                var miner = new Miner(chain, swarm, privateKey);

                Log.Debug("Miner called.");
                while (!cancellationToken.IsCancellationRequested)
                {
                    try
                    {
                        if (swarm.Running)
                        {
                            Log.Debug("Start mining.");
                            await miner.MineBlockAsync(properties.MaximumTransactions, cancellationToken);
                        }
                        else
                        {
                            await Task.Delay(1000, cancellationToken);
                        }
                    }
                    catch (Exception ex)
                    {
                        Log.Error(ex, "Exception occurred.");
                    }
                }
            }

            async Task devMinerLoopAction(
                Swarm <NineChroniclesActionType> mainSwarm,
                Swarm <NineChroniclesActionType> subSwarm,
                PrivateKey privateKey,
                CancellationToken cancellationToken)
            {
                var miner = new ReorgMiner(mainSwarm, subSwarm, privateKey, reorgInterval);

                Log.Debug("Miner called.");
                while (!cancellationToken.IsCancellationRequested)
                {
                    try
                    {
                        if (mainSwarm.Running)
                        {
                            Log.Debug("Start mining.");
                            await miner.MineBlockAsync(properties.MaximumTransactions, cancellationToken);

                            await Task.Delay(blockInterval, cancellationToken);
                        }
                        else
                        {
                            await Task.Delay(1000, cancellationToken);
                        }
                    }
                    catch (Exception ex)
                    {
                        Log.Error(ex, "Exception occurred.");
                    }
                }
            }

            if (isDev)
            {
                NodeService = new DevLibplanetNodeService <NineChroniclesActionType>(
                    Properties,
                    easyPolicy,
                    hardPolicy,
                    renderers,
                    devMinerLoopAction,
                    preloadProgress,
                    (code, msg) =>
                {
                    ExceptionRenderer.RenderException(code, msg);
                    Log.Error(msg);
                },
                    isPreloadStarted => { NodeStatusRenderer.PreloadStatus(isPreloadStarted); },
                    ignoreBootstrapFailure
                    );
            }
            else
            {
                NodeService = new LibplanetNodeService <NineChroniclesActionType>(
                    Properties,
                    blockPolicy,
                    renderers,
                    minerLoopAction,
                    preloadProgress,
                    (code, msg) =>
                {
                    ExceptionRenderer.RenderException(code, msg);
                    Log.Error(msg);
                },
                    isPreloadStarted =>
                {
                    NodeStatusRenderer.PreloadStatus(isPreloadStarted);
                },
                    ignoreBootstrapFailure
                    );
            }

            strictRenderer.BlockChain = NodeService?.BlockChain ?? throw new Exception("BlockChain is null.");
            if (NodeService?.BlockChain?.GetState(AuthorizedMinersState.Address) is Dictionary ams &&
                blockPolicy is BlockPolicy bp)
            {
                bp.AuthorizedMinersState = new AuthorizedMinersState(ams);
            }
        }
        public NineChroniclesNodeService(
            PrivateKey?minerPrivateKey,
            LibplanetNodeServiceProperties <NCAction> properties,
            IBlockPolicy <NCAction> blockPolicy,
            NetworkType networkType,
            Progress <PreloadState>?preloadProgress = null,
            bool ignoreBootstrapFailure             = false,
            bool ignorePreloadFailure = false,
            bool strictRendering      = false,
            bool authorizedMiner      = false,
            bool isDev           = false,
            int blockInterval    = 10000,
            int reorgInterval    = 0,
            TimeSpan txLifeTime  = default,
            int minerCount       = 1,
            int txQuotaPerSigner = 10
            )
        {
            MinerPrivateKey = minerPrivateKey;
            Properties      = properties;

            LogEventLevel logLevel          = LogEventLevel.Debug;
            var           blockPolicySource = new BlockPolicySource(Log.Logger, logLevel);
            // Policies for dev mode.
            IBlockPolicy <NCAction>?easyPolicy  = null;
            IBlockPolicy <NCAction>?hardPolicy  = null;
            IStagePolicy <NCAction> stagePolicy = new StagePolicy(txLifeTime, txQuotaPerSigner);

            if (isDev)
            {
                easyPolicy = new ReorgPolicy(new RewardGold(), 1);
                hardPolicy = new ReorgPolicy(new RewardGold(), 2);
            }

            BlockRenderer      = blockPolicySource.BlockRenderer;
            ActionRenderer     = blockPolicySource.ActionRenderer;
            ExceptionRenderer  = new ExceptionRenderer();
            NodeStatusRenderer = new NodeStatusRenderer();
            var renderers      = new List <IRenderer <NCAction> >();
            var strictRenderer = new StrictRenderer(onError: exc =>
                                                    ExceptionRenderer.RenderException(
                                                        RPCException.InvalidRenderException,
                                                        exc.Message.Split("\n")[0]
                                                        )
                                                    );

            if (Properties.Render)
            {
                renderers.Add(blockPolicySource.BlockRenderer);
                renderers.Add(blockPolicySource.LoggedActionRenderer);
            }
            else if (Properties.LogActionRenders)
            {
                renderers.Add(blockPolicySource.BlockRenderer);
                // The following "nullRenderer" does nothing.  It's just for filling
                // the LoggedActionRenderer<T>() constructor's parameter:
                IActionRenderer <NCAction> nullRenderer =
                    new AnonymousActionRenderer <NCAction>();
                renderers.Add(
                    new LoggedActionRenderer <NCAction>(
                        nullRenderer,
                        Log.Logger,
                        logLevel
                        )
                    );
            }
            else
            {
                renderers.Add(blockPolicySource.LoggedBlockRenderer);
            }

            if (strictRendering)
            {
                Log.Debug(
                    $"Strict rendering is on. Add {nameof(StrictRenderer)}.");
                renderers.Add(strictRenderer);
            }

            async Task minerLoopAction(
                BlockChain <NCAction> chain,
                Swarm <NCAction> swarm,
                PrivateKey privateKey,
                CancellationToken cancellationToken)
            {
                var miner = new Miner(chain, swarm, privateKey, authorizedMiner);

                Log.Debug("Miner called.");
                while (!cancellationToken.IsCancellationRequested)
                {
                    try
                    {
                        long nextBlockIndex = chain.Tip.Index + 1;

                        if (swarm.Running)
                        {
                            Log.Debug("Start mining.");

                            if (chain.Policy is BlockPolicy bp)
                            {
                                if (bp.IsAllowedToMine(privateKey.ToAddress(), chain.Count))
                                {
                                    IEnumerable <Task <Block <NCAction> > > miners = Enumerable
                                                                                     .Range(0, minerCount)
                                                                                     .Select(_ => miner.MineBlockAsync(cancellationToken));
                                    await Task.WhenAll(miners);
                                }
                                else
                                {
                                    Log.Debug(
                                        "Miner {MinerAddress} is not allowed to mine a block with index {Index} " +
                                        "under current policy.",
                                        privateKey.ToAddress(),
                                        chain.Count);
                                    await Task.Delay(1000, cancellationToken);
                                }
                            }
                            else
                            {
                                Log.Error(
                                    "No suitable policy was found for chain {ChainId}.",
                                    chain.Id);
                                await Task.Delay(1000, cancellationToken);
                            }
                        }
                        else
                        {
                            await Task.Delay(1000, cancellationToken);
                        }
                    }
                    catch (Exception ex)
                    {
                        Log.Error(ex, "Exception occurred.");
                    }
                }
            }

            async Task devMinerLoopAction(
                Swarm <NCAction> mainSwarm,
                Swarm <NCAction> subSwarm,
                PrivateKey privateKey,
                CancellationToken cancellationToken)
            {
                var miner = new ReorgMiner(mainSwarm, subSwarm, privateKey, reorgInterval);

                Log.Debug("Miner called.");
                while (!cancellationToken.IsCancellationRequested)
                {
                    try
                    {
                        if (mainSwarm.Running)
                        {
                            Log.Debug("Start mining.");
                            await miner.MineBlockAsync(cancellationToken);

                            await Task.Delay(blockInterval, cancellationToken);
                        }
                        else
                        {
                            await Task.Delay(1000, cancellationToken);
                        }
                    }
                    catch (Exception ex)
                    {
                        Log.Error(ex, "Exception occurred.");
                    }
                }
            }

            if (isDev)
            {
                NodeService = new DevLibplanetNodeService <NCAction>(
                    Properties,
                    easyPolicy,
                    hardPolicy,
                    stagePolicy,
                    renderers,
                    devMinerLoopAction,
                    preloadProgress,
                    (code, msg) =>
                {
                    ExceptionRenderer.RenderException(code, msg);
                    Log.Error(msg);
                },
                    isPreloadStarted => { NodeStatusRenderer.PreloadStatus(isPreloadStarted); },
                    ignoreBootstrapFailure
                    );
            }
            else
            {
                NodeService = new LibplanetNodeService <NCAction>(
                    Properties,
                    blockPolicy,
                    stagePolicy,
                    renderers,
                    minerLoopAction,
                    preloadProgress,
                    (code, msg) =>
                {
                    ExceptionRenderer.RenderException(code, msg);
                    Log.Error(msg);
                },
                    isPreloadStarted =>
                {
                    NodeStatusRenderer.PreloadStatus(isPreloadStarted);
                },
                    ignoreBootstrapFailure,
                    ignorePreloadFailure
                    );
            }

            strictRenderer.BlockChain = NodeService.BlockChain ?? throw new Exception("BlockChain is null.");
        }
Beispiel #20
0
        public async Task DoesTransactionFollowsPolicy()
        {
            var adminPrivateKey = new PrivateKey();
            var adminAddress = adminPrivateKey.ToAddress();
            var activatedPrivateKey = new PrivateKey();
            var activatedAddress = activatedPrivateKey.ToAddress();

            var blockPolicySource = new BlockPolicySource(Logger.None);
            IBlockPolicy<PolymorphicAction<ActionBase>> policy = blockPolicySource.GetPolicy(10000, 100);
            Block<PolymorphicAction<ActionBase>> genesis = MakeGenesisBlock(
                adminAddress,
                ImmutableHashSet.Create(activatedAddress).Add(adminAddress)
            );
            using var store = new DefaultStore(null);
            using var stateStore = new TrieStateStore(new DefaultKeyValueStore(null), new DefaultKeyValueStore(null));
            var blockChain = new BlockChain<PolymorphicAction<ActionBase>>(
                policy,
                store,
                stateStore,
                genesis,
                renderers: new[] { blockPolicySource.BlockRenderer }
            );
            Transaction<PolymorphicAction<ActionBase>> txByStranger =
                Transaction<PolymorphicAction<ActionBase>>.Create(
                    0,
                    new PrivateKey(),
                    genesis.Hash,
                    new PolymorphicAction<ActionBase>[] { }
                );

            // New private key which is not in activated addresses list is blocked.
            Assert.False(policy.DoesTransactionFollowsPolicy(txByStranger, blockChain));

            var newActivatedPrivateKey = new PrivateKey();
            var newActivatedAddress = newActivatedPrivateKey.ToAddress();

            // Activate with admin account.
            Transaction<PolymorphicAction<ActionBase>> invitationTx = blockChain.MakeTransaction(
                adminPrivateKey,
                new PolymorphicAction<ActionBase>[] { new AddActivatedAccount(newActivatedAddress) }
            );
            blockChain.StageTransaction(invitationTx);
            await blockChain.MineBlock(adminAddress);

            Transaction<PolymorphicAction<ActionBase>> txByNewActivated =
                Transaction<PolymorphicAction<ActionBase>>.Create(
                    0,
                    newActivatedPrivateKey,
                    genesis.Hash,
                    new PolymorphicAction<ActionBase>[] { }
                );

            // Test success because the key is activated.
            Assert.True(policy.DoesTransactionFollowsPolicy(txByNewActivated, blockChain));

            var singleAction = new PolymorphicAction<ActionBase>[]
            {
                new RewardGold(),
            };
            var manyActions = new PolymorphicAction<ActionBase>[]
            {
                new RewardGold(),
                new RewardGold(),
            };
            Transaction<PolymorphicAction<ActionBase>> txWithSingleAction =
                Transaction<PolymorphicAction<ActionBase>>.Create(
                    0,
                    activatedPrivateKey,
                    genesis.Hash,
                    singleAction
                );
            Transaction<PolymorphicAction<ActionBase>> txWithManyActions =
                Transaction<PolymorphicAction<ActionBase>>.Create(
                    0,
                    activatedPrivateKey,
                    genesis.Hash,
                    manyActions
                );

            // Transaction with more than two actions is rejected.
            Assert.True(policy.DoesTransactionFollowsPolicy(txWithSingleAction, blockChain));
            Assert.False(policy.DoesTransactionFollowsPolicy(txWithManyActions, blockChain));
        }
Beispiel #21
0
        public void ValidateNextBlockWithManyTransactions()
        {
            var adminPrivateKey = new PrivateKey();
            var adminAddress = new Address(adminPrivateKey.PublicKey);
            var blockPolicySource = new BlockPolicySource(Logger.None);
            IBlockPolicy<PolymorphicAction<ActionBase>> policy = blockPolicySource.GetPolicy(3000, 10);
            Block<PolymorphicAction<ActionBase>> genesis = MakeGenesisBlock(adminAddress, ImmutableHashSet<Address>.Empty);

            using var store = new DefaultStore(null);
            var stateStore = new NoOpStateStore();
            var blockChain = new BlockChain<PolymorphicAction<ActionBase>>(
                policy,
                store,
                stateStore,
                genesis
            );

            int nonce = 0;
            List<Transaction<PolymorphicAction<ActionBase>>> GenerateTransactions(int count)
            {
                var list = new List<Transaction<PolymorphicAction<ActionBase>>>();
                for (int i = 0; i < count; i++)
                {
                    list.Add(Transaction<PolymorphicAction<ActionBase>>.Create(
                        nonce++,
                        adminPrivateKey,
                        genesis.Hash,
                        new PolymorphicAction<ActionBase>[] { }
                    ));
                }

                return list;
            }

            Assert.Equal(1, blockChain.Count);
            Block<PolymorphicAction<ActionBase>> block1 = Block<PolymorphicAction<ActionBase>>.Mine(
                index: 1,
                difficulty: policy.GetNextBlockDifficulty(blockChain),
                previousTotalDifficulty: blockChain.Tip.TotalDifficulty,
                miner: adminAddress,
                previousHash: blockChain.Tip.Hash,
                timestamp: DateTimeOffset.MinValue,
                transactions: GenerateTransactions(5));
            blockChain.Append(block1);
            Assert.Equal(2, blockChain.Count);
            Assert.True(blockChain.ContainsBlock(block1.Hash));
            Block<PolymorphicAction<ActionBase>> block2 = Block<PolymorphicAction<ActionBase>>.Mine(
                index: 2,
                difficulty: policy.GetNextBlockDifficulty(blockChain),
                previousTotalDifficulty: blockChain.Tip.TotalDifficulty,
                miner: adminAddress,
                previousHash: blockChain.Tip.Hash,
                timestamp: DateTimeOffset.MinValue,
                transactions: GenerateTransactions(10));
            blockChain.Append(block2);
            Assert.Equal(3, blockChain.Count);
            Assert.True(blockChain.ContainsBlock(block2.Hash));
            Block<PolymorphicAction<ActionBase>> block3 = Block<PolymorphicAction<ActionBase>>.Mine(
                index: 3,
                difficulty: policy.GetNextBlockDifficulty(blockChain),
                previousTotalDifficulty: blockChain.Tip.TotalDifficulty,
                miner: adminAddress,
                previousHash: blockChain.Tip.Hash,
                timestamp: DateTimeOffset.MinValue,
                transactions: GenerateTransactions(11));
            Assert.Throws<BlockExceedingTransactionsException>(() => blockChain.Append(block3));
            Assert.Equal(3, blockChain.Count);
            Assert.False(blockChain.ContainsBlock(block3.Hash));
        }
Beispiel #22
0
        static void Main(string[] args)
        {
            if (args.Length < 2)
            {
                Console.Error.WriteLine("Too few arguments.");
                Environment.Exit(1);
                return;
            }

            string  storePath = args[0];
            int     limit     = int.Parse(args[1]);
            ILogger logger    = new LoggerConfiguration().CreateLogger();

            Libplanet.Crypto.CryptoConfig.CryptoBackend = new Secp256K1CryptoBackend <SHA256>();
            var policySource = new BlockPolicySource(logger, LogEventLevel.Verbose);
            IBlockPolicy <NCAction> policy =
                policySource.GetPolicy(BlockPolicySource.DifficultyBoundDivisor + 1, 0);
            IStagePolicy <NCAction> stagePolicy = new VolatileStagePolicy <NCAction>();
            var store = new RocksDBStore(storePath);

            if (!(store.GetCanonicalChainId() is Guid chainId))
            {
                Console.Error.WriteLine("There is no canonical chain: {0}", storePath);
                Environment.Exit(1);
                return;
            }

            if (!(store.IndexBlockHash(chainId, 0) is HashDigest <SHA256> gHash))
            {
                Console.Error.WriteLine("There is no genesis block: {0}", storePath);
                Environment.Exit(1);
                return;
            }

            DateTimeOffset   started = DateTimeOffset.UtcNow;
            Block <NCAction> genesis = store.GetBlock <NCAction>(gHash);
            IKeyValueStore   stateRootKeyValueStore = new RocksDBKeyValueStore(Path.Combine(storePath, "state_hashes")),
                             stateKeyValueStore     = new RocksDBKeyValueStore(Path.Combine(storePath, "states"));
            IStateStore stateStore = new TrieStateStore(stateKeyValueStore, stateRootKeyValueStore);
            var         chain      = new BlockChain <NCAction>(policy, stagePolicy, store, stateStore, genesis);
            long        height     = chain.Tip.Index;

            HashDigest <SHA256>[] blockHashes = limit < 0
                ? chain.BlockHashes.SkipWhile((_, i) => i < height + limit).ToArray()
                : chain.BlockHashes.Take(limit).ToArray();
            Console.Error.WriteLine(
                "Executing {0} blocks: {1}-{2} (inclusive).",
                blockHashes.Length,
                blockHashes[0],
                blockHashes.Last()
                );
            Block <NCAction>[] blocks       = blockHashes.Select(h => chain[h]).ToArray();
            DateTimeOffset     blocksLoaded = DateTimeOffset.UtcNow;
            long txs     = 0;
            long actions = 0;

            foreach (Block <NCAction> block in blocks)
            {
                Console.Error.WriteLine(
                    "Block #{0} {1}; {2} txs",
                    block.Index,
                    block.Hash,
                    block.Transactions.Count()
                    );

                IEnumerable <ActionEvaluation> blockEvals;
                if (block.Index > 0)
                {
                    blockEvals = block.Evaluate(
                        DateTimeOffset.UtcNow,
                        address => chain.GetState(address, block.Hash),
                        (address, currency) => chain.GetBalance(address, currency, block.Hash)
                        );
                }
                else
                {
                    blockEvals = block.Evaluate(
                        DateTimeOffset.UtcNow,
                        _ => null,
                        ((_, currency) => new FungibleAssetValue(currency))
                        );
                }
                SetStates(chain.Id, stateStore, block, blockEvals.ToArray(), buildStateReferences: true);
                txs     += block.Transactions.LongCount();
                actions += block.Transactions.Sum(tx => tx.Actions.LongCount()) + 1;
            }

            DateTimeOffset ended = DateTimeOffset.UtcNow;

            Console.WriteLine("Loading blocks\t{0}", blocksLoaded - started);
            long execActionsTotalMilliseconds = (long)(ended - blocksLoaded).TotalMilliseconds;

            Console.WriteLine("Executing actions\t{0}ms", execActionsTotalMilliseconds);
            Console.WriteLine("Average per block\t{0}ms", execActionsTotalMilliseconds / blockHashes.Length);
            Console.WriteLine("Average per tx\t{0}ms", execActionsTotalMilliseconds / txs);
            Console.WriteLine("Average per action\t{0}ms", execActionsTotalMilliseconds / actions);
            Console.WriteLine("Total elapsed\t{0}", ended - started);
        }
Beispiel #23
0
        public async Task GetNextBlockDifficultyWithAuthorizedMinersState()
        {
            var adminPrivateKey = new PrivateKey();
            var adminAddress = adminPrivateKey.ToAddress();
            var miner = new PrivateKey().ToAddress();
            var miners = new[] { miner };

            var blockPolicySource = new BlockPolicySource(Logger.None);
            IBlockPolicy<PolymorphicAction<ActionBase>> policy = blockPolicySource.GetPolicy(4096, 100);
            Block<PolymorphicAction<ActionBase>> genesis = MakeGenesisBlock(
                adminAddress,
                ImmutableHashSet<Address>.Empty,
                new AuthorizedMinersState(miners, 2, 6)
            );
            using var store = new DefaultStore(null);
            using var stateStore = new TrieStateStore(new DefaultKeyValueStore(null), new DefaultKeyValueStore(null));
            var blockChain = new BlockChain<PolymorphicAction<ActionBase>>(
                policy,
                store,
                stateStore,
                genesis,
                renderers: new[] { blockPolicySource.BlockRenderer }
            );

            if (policy is BlockPolicy bp)
            {
                bp.AuthorizedMinersState = new AuthorizedMinersState(
                    (Dictionary)blockChain.GetState(AuthorizedMinersState.Address)
                    );
            }

            var dateTimeOffset = DateTimeOffset.MinValue;

            // Index 1
            Assert.Equal(4096, policy.GetNextBlockDifficulty(blockChain));

            dateTimeOffset += TimeSpan.FromSeconds(1);
            await blockChain.MineBlock(miner, dateTimeOffset);

            // Index 2, target index
            Assert.Equal(4096, policy.GetNextBlockDifficulty(blockChain));

            dateTimeOffset += TimeSpan.FromSeconds(1);
            await blockChain.MineBlock(miner, dateTimeOffset);

            // Index 3
            Assert.Equal(4096, policy.GetNextBlockDifficulty(blockChain));

            dateTimeOffset += TimeSpan.FromSeconds(1);
            await blockChain.MineBlock(miner, dateTimeOffset);

            // Index 4, target index
            Assert.Equal(4096, policy.GetNextBlockDifficulty(blockChain));

            dateTimeOffset += TimeSpan.FromSeconds(1);
            await blockChain.MineBlock(miner, dateTimeOffset);

            // Index 5
            Assert.Equal(4096, policy.GetNextBlockDifficulty(blockChain));

            dateTimeOffset += TimeSpan.FromSeconds(1);
            await blockChain.MineBlock(miner, dateTimeOffset);

            // Index 6, target index
            Assert.Equal(4096, policy.GetNextBlockDifficulty(blockChain));

            dateTimeOffset += TimeSpan.FromSeconds(1);
            await blockChain.MineBlock(miner, dateTimeOffset);

            // Index 7
            Assert.Equal(4098, policy.GetNextBlockDifficulty(blockChain));

            dateTimeOffset += TimeSpan.FromSeconds(1);
            await blockChain.MineBlock(miner, dateTimeOffset);

            // Index 8
            Assert.Equal(4100, policy.GetNextBlockDifficulty(blockChain));

            dateTimeOffset += TimeSpan.FromSeconds(1);
            await blockChain.MineBlock(miner, dateTimeOffset);

            // Index 9
            Assert.Equal(4102, policy.GetNextBlockDifficulty(blockChain));

            dateTimeOffset += TimeSpan.FromSeconds(1);
            await blockChain.MineBlock(miner, dateTimeOffset);

            // Index 10
            Assert.Equal(4104, policy.GetNextBlockDifficulty(blockChain));

            dateTimeOffset += TimeSpan.FromSeconds(1);
            await blockChain.MineBlock(miner, dateTimeOffset);

            // Index 11
            Assert.Equal(4106, policy.GetNextBlockDifficulty(blockChain));

            dateTimeOffset += TimeSpan.FromSeconds(20);
            await blockChain.MineBlock(miner, dateTimeOffset);

            // Index 12
            Assert.Equal(4104, policy.GetNextBlockDifficulty(blockChain));
        }
Beispiel #24
0
        public async Task ValidateNextBlockTx()
        {
            var adminPrivateKey = new PrivateKey();
            var adminAddress    = adminPrivateKey.ToAddress();

            var blockPolicySource = new BlockPolicySource(Logger.None);
            IBlockPolicy <PolymorphicAction <ActionBase> > policy = blockPolicySource.GetPolicy(
                10_000, null, null, null, null, null, null, null);
            IStagePolicy <PolymorphicAction <ActionBase> > stagePolicy =
                new VolatileStagePolicy <PolymorphicAction <ActionBase> >();
            Block <PolymorphicAction <ActionBase> > genesis = MakeGenesisBlock(
                adminAddress,
                ImmutableHashSet.Create(adminAddress)
                );

            using var store      = new DefaultStore(null);
            using var stateStore = new TrieStateStore(new DefaultKeyValueStore(null));
            var blockChain = new BlockChain <PolymorphicAction <ActionBase> >(
                policy,
                stagePolicy,
                store,
                stateStore,
                genesis,
                renderers: new[] { blockPolicySource.BlockRenderer }
                );
            Transaction <PolymorphicAction <ActionBase> > txByStranger =
                Transaction <PolymorphicAction <ActionBase> > .Create(
                    0,
                    new PrivateKey(),
                    genesis.Hash,
                    new PolymorphicAction <ActionBase>[] { }
                    );

            // New private key which is not in activated addresses list is blocked.
            Assert.NotNull(policy.ValidateNextBlockTx(blockChain, txByStranger));

            var newActivatedPrivateKey = new PrivateKey();
            var newActivatedAddress    = newActivatedPrivateKey.ToAddress();

            // Activate with admin account.
            blockChain.MakeTransaction(
                adminPrivateKey,
                new PolymorphicAction <ActionBase>[] { new AddActivatedAccount(newActivatedAddress) }
                );
            await blockChain.MineBlock(adminPrivateKey);

            Transaction <PolymorphicAction <ActionBase> > txByNewActivated =
                Transaction <PolymorphicAction <ActionBase> > .Create(
                    0,
                    newActivatedPrivateKey,
                    genesis.Hash,
                    new PolymorphicAction <ActionBase>[] { }
                    );

            // Test success because the key is activated.
            Assert.Null(policy.ValidateNextBlockTx(blockChain, txByNewActivated));

            var singleAction = new PolymorphicAction <ActionBase>[]
            {
                new DailyReward(),
            };
            var manyActions = new PolymorphicAction <ActionBase>[]
            {
                new DailyReward(),
                new DailyReward(),
            };
            Transaction <PolymorphicAction <ActionBase> > txWithSingleAction =
                Transaction <PolymorphicAction <ActionBase> > .Create(
                    0,
                    newActivatedPrivateKey,
                    genesis.Hash,
                    singleAction
                    );

            Transaction <PolymorphicAction <ActionBase> > txWithManyActions =
                Transaction <PolymorphicAction <ActionBase> > .Create(
                    0,
                    newActivatedPrivateKey,
                    genesis.Hash,
                    manyActions
                    );

            // Transaction with more than two actions is rejected.
            Assert.Null(policy.ValidateNextBlockTx(blockChain, txWithSingleAction));
            Assert.NotNull(policy.ValidateNextBlockTx(blockChain, txWithManyActions));
        }
Beispiel #25
0
        public void ValidateNextBlockWithManyTransactionsPerSigner()
        {
            var adminPrivateKey   = new PrivateKey();
            var adminPublicKey    = adminPrivateKey.PublicKey;
            var blockPolicySource = new BlockPolicySource(Logger.None);
            IBlockPolicy <PolymorphicAction <ActionBase> > policy = blockPolicySource.GetPolicy(
                minimumDifficulty: 10_000,
                hashAlgorithmTypePolicy: null,
                maxBlockBytesPolicy: null,
                minTransactionsPerBlockPolicy: null,
                maxTransactionsPerBlockPolicy: MaxTransactionsPerBlockPolicy
                .Default
                .Add(new SpannedSubPolicy <int>(0, null, null, 10)),
                maxTransactionsPerSignerPerBlockPolicy: MaxTransactionsPerSignerPerBlockPolicy
                .Default
                .Add(new SpannedSubPolicy <int>(2, null, null, 5)),
                authorizedMinersPolicy: null,
                permissionedMinersPolicy: null);
            IStagePolicy <PolymorphicAction <ActionBase> > stagePolicy =
                new VolatileStagePolicy <PolymorphicAction <ActionBase> >();
            Block <PolymorphicAction <ActionBase> > genesis =
                MakeGenesisBlock(adminPublicKey.ToAddress(), ImmutableHashSet <Address> .Empty);

            using var store = new DefaultStore(null);
            var stateStore = new TrieStateStore(new MemoryKeyValueStore());
            var blockChain = new BlockChain <PolymorphicAction <ActionBase> >(
                policy,
                stagePolicy,
                store,
                stateStore,
                genesis
                );

            int nonce = 0;

            List <Transaction <PolymorphicAction <ActionBase> > > GenerateTransactions(int count)
            {
                var list = new List <Transaction <PolymorphicAction <ActionBase> > >();

                for (int i = 0; i < count; i++)
                {
                    list.Add(Transaction <PolymorphicAction <ActionBase> > .Create(
                                 nonce++,
                                 adminPrivateKey,
                                 genesis.Hash,
                                 new PolymorphicAction <ActionBase>[] { }
                                 ));
                }

                return(list);
            }

            Assert.Equal(1, blockChain.Count);
            Block <PolymorphicAction <ActionBase> > block1 = new BlockContent <PolymorphicAction <ActionBase> >
            {
                Index           = 1,
                Difficulty      = policy.GetNextBlockDifficulty(blockChain),
                TotalDifficulty = blockChain.Tip.Difficulty + policy.GetNextBlockDifficulty(blockChain),
                PublicKey       = adminPublicKey,
                PreviousHash    = blockChain.Tip.Hash,
                Timestamp       = DateTimeOffset.MinValue,
                Transactions    = GenerateTransactions(10),
            }.Mine(policy.GetHashAlgorithm(1)).Evaluate(adminPrivateKey, blockChain);

            // Should be fine since policy hasn't kicked in yet.
            blockChain.Append(block1);
            Assert.Equal(2, blockChain.Count);
            Assert.True(blockChain.ContainsBlock(block1.Hash));

            Block <PolymorphicAction <ActionBase> > block2 = new BlockContent <PolymorphicAction <ActionBase> >
            {
                Index           = 2,
                Difficulty      = policy.GetNextBlockDifficulty(blockChain),
                TotalDifficulty = blockChain.Tip.Difficulty + policy.GetNextBlockDifficulty(blockChain),
                PublicKey       = adminPublicKey,
                PreviousHash    = blockChain.Tip.Hash,
                Timestamp       = DateTimeOffset.MinValue,
                Transactions    = GenerateTransactions(10),
            }.Mine(policy.GetHashAlgorithm(2)).Evaluate(adminPrivateKey, blockChain);

            // Subpolicy kicks in.
            Assert.Throws <InvalidBlockTxCountPerSignerException>(() => blockChain.Append(block2));
            Assert.Equal(2, blockChain.Count);
            Assert.False(blockChain.ContainsBlock(block2.Hash));
            // Since failed, roll back nonce.
            nonce -= 10;

            // Limit should also pass.
            Block <PolymorphicAction <ActionBase> > block3 = new BlockContent <PolymorphicAction <ActionBase> >
            {
                Index           = 2,
                Difficulty      = policy.GetNextBlockDifficulty(blockChain),
                TotalDifficulty = blockChain.Tip.Difficulty + policy.GetNextBlockDifficulty(blockChain),
                PublicKey       = adminPublicKey,
                PreviousHash    = blockChain.Tip.Hash,
                Timestamp       = DateTimeOffset.MinValue,
                Transactions    = GenerateTransactions(5),
            }.Mine(policy.GetHashAlgorithm(2)).Evaluate(adminPrivateKey, blockChain);

            blockChain.Append(block3);
            Assert.Equal(3, blockChain.Count);
            Assert.True(blockChain.ContainsBlock(block3.Hash));
        }
Beispiel #26
0
        public void Inspect(
            [Argument("STORE-TYPE",
                      Description = "Store type of RocksDb (rocksdb or monorocksdb).")]
            StoreType storeType,
            [Argument("STORE-PATH",
                      Description = "Store path to inspect.")]
            string storePath,
            [Argument("OFFSET",
                      Description = "Offset of block index.")]
            int?offset = null,
            [Argument("LIMIT",
                      Description = "Limit of block count.")]
            int?limit = null)
        {
            if (!Directory.Exists(storePath))
            {
                throw new CommandExitedException($"The given STORE-PATH, {storePath} seems not existed.", -1);
            }

            IStagePolicy <NCAction> stagePolicy = new VolatileStagePolicy <PolymorphicAction <ActionBase> >();
            IBlockPolicy <NCAction> blockPolicy = new BlockPolicySource(Logger.None).GetPolicy();
            IStore           store        = storeType.CreateStore(storePath);
            var              stateStore   = new TrieStateStore(new DefaultKeyValueStore(null));
            Block <NCAction> genesisBlock = store.GetGenesisBlock <NCAction>(blockPolicy.GetHashAlgorithm);

            if (!(store.GetCanonicalChainId() is { } chainId))
            {
                throw new CommandExitedException($"There is no canonical chain: {storePath}", -1);
            }

            if (!(store.IndexBlockHash(chainId, 0) is { } gHash))
            {
                throw new CommandExitedException($"There is no genesis block: {storePath}", -1);
            }

            BlockChain <NCAction> chain = new BlockChain <NCAction>(
                blockPolicy,
                stagePolicy,
                store,
                stateStore,
                genesisBlock);

            long height = chain.Tip.Index;

            if (offset + limit > (int)height)
            {
                throw new CommandExitedException(
                          $"The sum of the offset and limit is greater than the chain tip index: {height}",
                          -1);
            }

            _console.Out.WriteLine("Block Index," +
                                   "Mining Time (sec)," +
                                   "Total Tx #," +
                                   "HAS #," +
                                   "RankingBattle #," +
                                   "Mimisbrunnr #");

            var typeOfActionTypeAttribute = typeof(ActionTypeAttribute);

            foreach (var item in
                     store.IterateIndexes(chain.Id, offset + 1 ?? 1, limit).Select((value, i) => new { i, value }))
            {
                var block         = store.GetBlock <NCAction>(blockPolicy.GetHashAlgorithm, item.value);
                var previousBlock = store.GetBlock <NCAction>(
                    blockPolicy.GetHashAlgorithm,
                    block.PreviousHash ?? block.Hash
                    );

                var miningTime             = block.Timestamp - previousBlock.Timestamp;
                var txCount                = 0;
                var hackAndSlashCount      = 0;
                var rankingBattleCount     = 0;
                var mimisbrunnrBattleCount = 0;
                foreach (var tx in block.Transactions)
                {
                    txCount++;
                    foreach (var action in tx.Actions)
                    {
                        var actionTypeAttribute =
                            Attribute.GetCustomAttribute(action.InnerAction.GetType(), typeOfActionTypeAttribute)
                            as ActionTypeAttribute;
                        if (actionTypeAttribute is null)
                        {
                            continue;
                        }

                        var typeIdentifier = actionTypeAttribute.TypeIdentifier;
                        if (typeIdentifier.StartsWith("hack_and_slash"))
                        {
                            hackAndSlashCount++;
                        }
                        else if (typeIdentifier.StartsWith("ranking_battle"))
                        {
                            rankingBattleCount++;
                        }
                        else if (typeIdentifier.StartsWith("mimisbrunnr_battle"))
                        {
                            mimisbrunnrBattleCount++;
                        }
                    }
                }

                _console.Out.WriteLine($"{block.Index}," +
                                       $"{miningTime:s\\.ff}," +
                                       $"{txCount}," +
                                       $"{hackAndSlashCount}," +
                                       $"{rankingBattleCount}," +
                                       $"{mimisbrunnrBattleCount}");
            }

            (store as IDisposable)?.Dispose();
        }
Beispiel #27
0
        public async Task MixedMiningPolicy()
        {
            var nonce = new byte[] { 0x00, 0x01, 0x02, 0x03 };
            var authorizedMinerKey   = new PrivateKey();
            var permissionedMinerKey = new PrivateKey();
            var someMinerKey         = new PrivateKey();
            var addresses            = new Address[]
            {
                authorizedMinerKey.ToAddress(),
                permissionedMinerKey.ToAddress(),
                someMinerKey.ToAddress(),
            };
            var pendingActivations = new[]
            {
                authorizedMinerKey,
                permissionedMinerKey,
                someMinerKey,
            }.Select(key => ActivationKey.Create(key, nonce).Item2).ToArray();
            var action = new TransferAsset(
                new PrivateKey().ToAddress(),
                new PrivateKey().ToAddress(),
                new FungibleAssetValue(_currency, 0, 0));

            // This creates genesis with _privateKey as its miner.
            Block <PolymorphicAction <ActionBase> > genesis = MakeGenesisBlock(
                default(Address),
                ImmutableHashSet <Address> .Empty,
                pendingActivations: pendingActivations);

            using var store      = new DefaultStore(null);
            using var stateStore = new TrieStateStore(new DefaultKeyValueStore(null));
            var blockPolicySource = new BlockPolicySource(Logger.None);
            var blockChain        = new BlockChain <PolymorphicAction <ActionBase> >(
                blockPolicySource.GetPolicy(
                    minimumDifficulty: 10_000,
                    hashAlgorithmTypePolicy: null,
                    maxBlockBytesPolicy: null,
                    minTransactionsPerBlockPolicy: null,
                    maxTransactionsPerBlockPolicy: null,
                    maxTransactionsPerSignerPerBlockPolicy: null,
                    authorizedMinersPolicy: AuthorizedMinersPolicy
                    .Default
                    .Add(new SpannedSubPolicy <ImmutableHashSet <Address> >(
                             startIndex: 0,
                             endIndex: 6,
                             filter: index => index % 2 == 0,
                             value: new Address[] { authorizedMinerKey.ToAddress() }
                             .ToImmutableHashSet())),
                    permissionedMinersPolicy: PermissionedMinersPolicy
                    .Default
                    .Add(new SpannedSubPolicy <ImmutableHashSet <Address> >(
                             startIndex: 2,
                             endIndex: 10,
                             filter: index => index % 3 == 0,
                             value: new Address[] { permissionedMinerKey.ToAddress() }
                             .ToImmutableHashSet()))),
                new VolatileStagePolicy <PolymorphicAction <ActionBase> >(),
                store,
                stateStore,
                genesis,
                renderers: new[] { blockPolicySource.BlockRenderer }
                );

            Transaction <PolymorphicAction <ActionBase> > proof;

            // Index 1: Anyone can mine.
            await blockChain.MineBlock(someMinerKey);

            // Index 2: Only authorized miner can mine.
            await Assert.ThrowsAsync <BlockPolicyViolationException>(
                () => blockChain.MineBlock(permissionedMinerKey));

            await Assert.ThrowsAsync <BlockPolicyViolationException>(
                () => blockChain.MineBlock(someMinerKey));

            await blockChain.MineBlock(authorizedMinerKey);

            // Index 3: Only permissioned miner can mine.
            await Assert.ThrowsAsync <BlockPolicyViolationException>(
                () => blockChain.MineBlock(authorizedMinerKey));

            await Assert.ThrowsAsync <BlockPolicyViolationException>(
                () => blockChain.MineBlock(someMinerKey));

            await blockChain.MineBlock(permissionedMinerKey);

            // Index 4: Only authorized miner can mine.
            await Assert.ThrowsAsync <BlockPolicyViolationException>(
                () => blockChain.MineBlock(permissionedMinerKey));

            await Assert.ThrowsAsync <BlockPolicyViolationException>(
                () => blockChain.MineBlock(someMinerKey));

            await blockChain.MineBlock(authorizedMinerKey);

            // Index 5: Anyone can mine again.
            await blockChain.MineBlock(someMinerKey);

            // Index 6: In case both authorized mining and permissioned mining apply,
            // only authorized miner can mine.
            await Assert.ThrowsAsync <BlockPolicyViolationException>(
                () => blockChain.MineBlock(permissionedMinerKey));

            await blockChain.MineBlock(authorizedMinerKey);

            // Index 7, 8, 9: Check authorized mining ended.
            await blockChain.MineBlock(someMinerKey);

            await blockChain.MineBlock(someMinerKey);

            await Assert.ThrowsAsync <BlockPolicyViolationException>(
                () => blockChain.MineBlock(someMinerKey));

            proof = blockChain.MakeTransaction(
                permissionedMinerKey,
                new PolymorphicAction <ActionBase>[] { action });
            await blockChain.MineBlock(permissionedMinerKey);

            // Index 10, 11, 12: Check permissioned mining ended.
            await blockChain.MineBlock(someMinerKey);

            await blockChain.MineBlock(someMinerKey);

            await blockChain.MineBlock(someMinerKey);

            // Index 13, 14: Check authorized miner and permissioned miner can also mine
            // when policy is allowed for all miners.
            await blockChain.MineBlock(authorizedMinerKey);

            await blockChain.MineBlock(permissionedMinerKey);
        }
Beispiel #28
0
        public async Task ValidateNextBlockWithAuthorizedMinersState()
        {
            var adminPrivateKey = new PrivateKey();
            var adminAddress    = adminPrivateKey.ToAddress();
            var minerKeys       = new[] { new PrivateKey(), new PrivateKey() };

            Address[] miners   = minerKeys.Select(AddressExtensions.ToAddress).ToArray();
            var       stranger = new Address(
                new byte[]
            {
                0x03, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00,
            }
                );

            var blockPolicySource = new BlockPolicySource(Logger.None);
            IBlockPolicy <PolymorphicAction <ActionBase> > policy = blockPolicySource.GetPolicy(
                10000,
                100,
                ignoreHardcodedIndicesForBackwardCompatibility: true
                );
            IStagePolicy <PolymorphicAction <ActionBase> > stagePolicy =
                new VolatileStagePolicy <PolymorphicAction <ActionBase> >();
            Block <PolymorphicAction <ActionBase> > genesis = MakeGenesisBlock(
                adminAddress,
                ImmutableHashSet <Address> .Empty,
                new AuthorizedMinersState(miners, 2, 4)
                );

            using var store      = new DefaultStore(null);
            using var stateStore = new TrieStateStore(new DefaultKeyValueStore(null), new DefaultKeyValueStore(null));
            var blockChain = new BlockChain <PolymorphicAction <ActionBase> >(
                policy,
                stagePolicy,
                store,
                stateStore,
                genesis,
                renderers: new[] { blockPolicySource.BlockRenderer }
                );

            if (policy is BlockPolicy bp)
            {
                bp.AuthorizedMinersState = new AuthorizedMinersState(
                    (Dictionary)blockChain.GetState(AuthorizedMinersState.Address)
                    );
            }

            await blockChain.MineBlock(stranger);

            await Assert.ThrowsAsync <InvalidMinerException>(async() =>
            {
                await blockChain.MineBlock(stranger);
            });

            new Miner(blockChain, null, minerKeys[0], true).StageProofTransaction();
            await blockChain.MineBlock(miners[0]);

            // it's okay because next block index is 3
            await blockChain.MineBlock(stranger);

            // it isn't :(
            await Assert.ThrowsAsync <InvalidMinerException>(async() =>
            {
                await blockChain.MineBlock(stranger);
            });

            // the authorization block should be proved by a proof tx
            await Assert.ThrowsAsync <InvalidMinerException>(
                async() => await blockChain.MineBlock(miners[1])
                );

            // the proof tx should be signed by the same authorized miner
            var othersProof = Transaction <PolymorphicAction <ActionBase> > .Create(
                blockChain.GetNextTxNonce(miners[0]),
                minerKeys[0],
                blockChain.Genesis.Hash,
                new PolymorphicAction <ActionBase> [0]
                );

            blockChain.StageTransaction(othersProof);
            await Assert.ThrowsAsync <InvalidMinerException>(
                async() => await blockChain.MineBlock(miners[1])
                );

            // the proof tx should be no-op
            var action = new PolymorphicAction <ActionBase>(
                new TransferAsset(miners[1], miners[0], new Currency("FOO", 0, miners[1]) * 1)
                );
            var nonEmptyProof = Transaction <PolymorphicAction <ActionBase> > .Create(
                blockChain.GetNextTxNonce(miners[1]),
                minerKeys[1],
                blockChain.Genesis.Hash,
                new[] { action }
                );

            blockChain.StageTransaction(nonEmptyProof);
            await Assert.ThrowsAsync <InvalidMinerException>(
                async() => await blockChain.MineBlock(miners[1])
                );

            new Miner(blockChain, null, minerKeys[1], true).StageProofTransaction();
            await blockChain.MineBlock(miners[1]);

            // it's okay because block index exceeds limitations.
            await blockChain.MineBlock(stranger);
        }
        public NineChroniclesNodeService(
            PrivateKey?minerPrivateKey,
            LibplanetNodeServiceProperties <NCAction> properties,
            Progress <PreloadState>?preloadProgress = null,
            bool ignoreBootstrapFailure             = false,
            bool ignorePreloadFailure = false,
            bool strictRendering      = false,
            bool authorizedMiner      = false,
            bool isDev          = false,
            int blockInterval   = 10000,
            int reorgInterval   = 0,
            TimeSpan txLifeTime = default,
            int minerCount      = 1
            )
        {
            MinerPrivateKey = minerPrivateKey;
            Properties      = properties;

            LogEventLevel logLevel          = LogEventLevel.Debug;
            var           blockPolicySource = new BlockPolicySource(Log.Logger, logLevel);
            // BlockPolicy shared through Lib9c.
            IBlockPolicy <NCAction>?blockPolicy = null;
            // Policies for dev mode.
            IBlockPolicy <NCAction>?easyPolicy  = null;
            IBlockPolicy <NCAction>?hardPolicy  = null;
            IStagePolicy <NCAction> stagePolicy =
                txLifeTime == default
                    ? new VolatileStagePolicy <NCAction>()
                    : new VolatileStagePolicy <NCAction>(txLifeTime);

            if (isDev)
            {
                easyPolicy = new ReorgPolicy(new RewardGold(), 1);
                hardPolicy = new ReorgPolicy(new RewardGold(), 2);
            }
            else
            {
                blockPolicy = blockPolicySource.GetPolicy(properties.MinimumDifficulty, properties.MaximumTransactions);
            }

            BlockRenderer      = blockPolicySource.BlockRenderer;
            ActionRenderer     = blockPolicySource.ActionRenderer;
            ExceptionRenderer  = new ExceptionRenderer();
            NodeStatusRenderer = new NodeStatusRenderer();
            var renderers      = new List <IRenderer <NCAction> >();
            var strictRenderer = new StrictRenderer(onError: exc =>
                                                    ExceptionRenderer.RenderException(
                                                        RPCException.InvalidRenderException,
                                                        exc.Message.Split("\n")[0]
                                                        )
                                                    );

            if (Properties.Render)
            {
                renderers.Add(blockPolicySource.BlockRenderer);
                renderers.Add(blockPolicySource.LoggedActionRenderer);
            }
            else if (Properties.LogActionRenders)
            {
                renderers.Add(blockPolicySource.BlockRenderer);
                // The following "nullRenderer" does nothing.  It's just for filling
                // the LoggedActionRenderer<T>() constructor's parameter:
                IActionRenderer <NCAction> nullRenderer =
                    new AnonymousActionRenderer <NCAction>();
                renderers.Add(
                    new LoggedActionRenderer <NCAction>(
                        nullRenderer,
                        Log.Logger,
                        logLevel
                        )
                    );
            }
            else
            {
                renderers.Add(blockPolicySource.LoggedBlockRenderer);
            }

            if (strictRendering)
            {
                Log.Debug(
                    $"Strict rendering is on. Add {nameof(StrictRenderer)}.");
                renderers.Add(strictRenderer);
            }

            async Task minerLoopAction(
                BlockChain <NCAction> chain,
                Swarm <NCAction> swarm,
                PrivateKey privateKey,
                CancellationToken cancellationToken)
            {
                var miner = new Miner(chain, swarm, privateKey, authorizedMiner);

                Log.Debug("Miner called.");
                while (!cancellationToken.IsCancellationRequested)
                {
                    try
                    {
                        long nextBlockIndex = chain.Tip.Index + 1;
                        bool authBlock      = blockPolicy is BlockPolicy bp
                                              // Copied from https://git.io/JLxNd
                                              && nextBlockIndex > 0 &&
                                              nextBlockIndex <= bp.AuthorizedMinersState?.ValidUntil &&
                                              nextBlockIndex % bp.AuthorizedMinersState?.Interval == 0;
                        if (swarm.Running && ((authorizedMiner && authBlock) || (!authorizedMiner && !authBlock)))
                        {
                            Log.Debug("Start mining.");

                            IEnumerable <Task <Block <NCAction> > > miners = Enumerable
                                                                             .Range(0, minerCount)
                                                                             .Select(_ => miner.MineBlockAsync(properties.MaximumTransactions, cancellationToken));
                            await Task.WhenAll(miners);
                        }
                        else
                        {
                            await Task.Delay(1000, cancellationToken);
                        }
                    }
                    catch (Exception ex)
                    {
                        Log.Error(ex, "Exception occurred.");
                    }
                }
            }

            async Task devMinerLoopAction(
                Swarm <NCAction> mainSwarm,
                Swarm <NCAction> subSwarm,
                PrivateKey privateKey,
                CancellationToken cancellationToken)
            {
                var miner = new ReorgMiner(mainSwarm, subSwarm, privateKey, reorgInterval);

                Log.Debug("Miner called.");
                while (!cancellationToken.IsCancellationRequested)
                {
                    try
                    {
                        if (mainSwarm.Running)
                        {
                            Log.Debug("Start mining.");
                            await miner.MineBlockAsync(properties.MaximumTransactions, cancellationToken);

                            await Task.Delay(blockInterval, cancellationToken);
                        }
                        else
                        {
                            await Task.Delay(1000, cancellationToken);
                        }
                    }
                    catch (Exception ex)
                    {
                        Log.Error(ex, "Exception occurred.");
                    }
                }
            }

            if (isDev)
            {
                NodeService = new DevLibplanetNodeService <NCAction>(
                    Properties,
                    easyPolicy,
                    hardPolicy,
                    stagePolicy,
                    renderers,
                    devMinerLoopAction,
                    preloadProgress,
                    (code, msg) =>
                {
                    ExceptionRenderer.RenderException(code, msg);
                    Log.Error(msg);
                },
                    isPreloadStarted => { NodeStatusRenderer.PreloadStatus(isPreloadStarted); },
                    ignoreBootstrapFailure
                    );
            }
            else
            {
                NodeService = new LibplanetNodeService <NCAction>(
                    Properties,
                    blockPolicy,
                    stagePolicy,
                    renderers,
                    minerLoopAction,
                    preloadProgress,
                    (code, msg) =>
                {
                    ExceptionRenderer.RenderException(code, msg);
                    Log.Error(msg);
                },
                    isPreloadStarted =>
                {
                    NodeStatusRenderer.PreloadStatus(isPreloadStarted);
                },
                    ignoreBootstrapFailure,
                    ignorePreloadFailure
                    );
            }

            strictRenderer.BlockChain = NodeService.BlockChain ?? throw new Exception("BlockChain is null.");
            if (NodeService.BlockChain?.GetState(AuthorizedMinersState.Address) is Dictionary ams &&
                blockPolicy is BlockPolicy bp)
            {
                bp.AuthorizedMinersState = new AuthorizedMinersState(ams);
            }

            if (authorizedMiner && blockPolicy is BlockPolicy {
                AuthorizedMinersState : null
            })
Beispiel #30
0
        static void Main(string[] args)
        {
            if (args.Length < 2)
            {
                Console.Error.WriteLine("Too few arguments.");
                Environment.Exit(1);
                return;
            }

            string storePath = args[0];
            int    limit     = int.Parse(args[1]);
            int    offset    = 0;

            if (args.Length >= 3)
            {
                offset = int.Parse(args[2]);
            }

            if (limit < 0)
            {
                Console.Error.WriteLine("Limit value must be greater than 0. Entered value: {0}", limit);
                Environment.Exit(1);
                return;
            }

            if (offset < 0)
            {
                Console.Error.WriteLine("Offset value must be greater than 0. Entered value: {0}", offset);
                Environment.Exit(1);
                return;
            }

            Log.Logger = new LoggerConfiguration().MinimumLevel.Verbose().WriteTo.Console().CreateLogger();
            Libplanet.Crypto.CryptoConfig.CryptoBackend = new Secp256K1CryptoBackend <SHA256>();
            var policySource = new BlockPolicySource(Log.Logger, LogEventLevel.Verbose);
            IBlockPolicy <NCAction> policy =
                policySource.GetPolicy(
                    // Explicitly set to lowest possible difficulty.
                    minimumDifficulty: BlockPolicySource.DifficultyStability,
                    maxBlockBytesPolicy: null,
                    minTransactionsPerBlockPolicy: null,
                    maxTransactionsPerBlockPolicy: null,
                    maxTransactionsPerSignerPerBlockPolicy: null,
                    authorizedMinersPolicy: null,
                    permissionedMinersPolicy: null);
            IStagePolicy <NCAction> stagePolicy = new VolatileStagePolicy <NCAction>();
            var store = new RocksDBStore(storePath);

            if (!(store.GetCanonicalChainId() is Guid chainId))
            {
                Console.Error.WriteLine("There is no canonical chain: {0}", storePath);
                Environment.Exit(1);
                return;
            }

            if (!(store.IndexBlockHash(chainId, 0) is { } gHash))
            {
                Console.Error.WriteLine("There is no genesis block: {0}", storePath);
                Environment.Exit(1);
                return;
            }

            DateTimeOffset   started            = DateTimeOffset.UtcNow;
            Block <NCAction> genesis            = store.GetBlock <NCAction>(policy.GetHashAlgorithm, gHash);
            IKeyValueStore   stateKeyValueStore = new RocksDBKeyValueStore(Path.Combine(storePath, "states"));
            var  stateStore = new TrieStateStore(stateKeyValueStore);
            var  chain      = new BlockChain <NCAction>(policy, stagePolicy, store, stateStore, genesis);
            long height     = chain.Tip.Index;

            if (offset + limit > (int)height)
            {
                Console.Error.WriteLine(
                    "The sum of the offset and limit is greater than the chain tip index: {0}", height);
                Environment.Exit(1);
                return;
            }

            BlockHash[] blockHashes = store.IterateIndexes(chain.Id, offset, limit).Select((value, i) => value).ToArray();
            Console.Error.WriteLine(
                "Executing {0} blocks: {1}-{2} (inclusive).",
                blockHashes.Length,
                blockHashes[0],
                blockHashes.Last()
                );
            Block <NCAction>[] blocks       = blockHashes.Select(h => chain[h]).ToArray();
            DateTimeOffset     blocksLoaded = DateTimeOffset.UtcNow;
            long txs     = 0;
            long actions = 0;

            foreach (Block <NCAction> block in blocks)
            {
                Console.Error.WriteLine(
                    "Block #{0} {1}; {2} txs",
                    block.Index,
                    block.Hash,
                    block.Transactions.Count()
                    );

                IEnumerable <ActionEvaluation> blockEvals =
                    chain.ExecuteActions(block, StateCompleterSet <NCAction> .Reject);
                SetStates(
                    chain.Id,
                    store,
                    stateStore,
                    block,
                    blockEvals.ToArray(),
                    buildStateReferences: true
                    );
                txs     += block.Transactions.LongCount();
                actions += block.Transactions.Sum(tx => tx.Actions.LongCount()) + 1;
            }

            DateTimeOffset ended = DateTimeOffset.UtcNow;

            Console.WriteLine("Loading blocks\t{0}", blocksLoaded - started);
            long execActionsTotalMilliseconds = (long)(ended - blocksLoaded).TotalMilliseconds;

            Console.WriteLine("Executing actions\t{0}ms", execActionsTotalMilliseconds);
            Console.WriteLine("Average per block\t{0}ms", execActionsTotalMilliseconds / blockHashes.Length);
            Console.WriteLine("Average per tx\t{0}ms", execActionsTotalMilliseconds / txs);
            Console.WriteLine("Average per action\t{0}ms", execActionsTotalMilliseconds / actions);
            Console.WriteLine("Total elapsed\t{0}", ended - started);
        }