コード例 #1
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);
            }

            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));
        }
コード例 #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();
        }
コード例 #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);
            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), new DefaultKeyValueStore(null));
            var blockChain = new BlockChain <PolymorphicAction <ActionBase> >(
                policy,
                stagePolicy,
                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));
        }
コード例 #4
0
 public StagePolicy(TimeSpan txLifeTime, int quotaPerSigner)
 {
     _txs            = new ConcurrentDictionary <Address, SortedList <Transaction <NCAction>, TxId> >();
     _quotaPerSigner = quotaPerSigner;
     _impl           = (txLifeTime == default)
         ? new VolatileStagePolicy <NCAction>()
         : new VolatileStagePolicy <NCAction>(txLifeTime);
 }
コード例 #5
0
ファイル: BlockPolicyTest.cs プロジェクト: planetarium/lib9c
        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));
        }
コード例 #6
0
ファイル: Utils.cs プロジェクト: boscohyun/lib9c
        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);
        }
コード例 #7
0
        public void Evaluate()
        {
            Address address     = _contents.Tx0InBlock1.Signer;
            var     blockAction = new SetStatesAtBlock(address, (Bencodex.Types.Integer) 123, 0);
            var     policy      = new BlockPolicy <Arithmetic>(
                blockAction: blockAction,
                blockInterval: TimeSpan.FromMilliseconds(3 * 60 * 60 * 1000),
                minimumDifficulty: 2,
                difficultyStability: 1
                );
            var stagePolicy = new VolatileStagePolicy <Arithmetic>();

            PreEvaluationBlock <Arithmetic> preEvalGenesis =
                _contents.Genesis.Mine(policy.GetHashAlgorithm(0));

            using (var fx = new DefaultStoreFixture())
            {
                Block <Arithmetic> genesis =
                    preEvalGenesis.Evaluate(_contents.GenesisKey, blockAction, fx.StateStore);
                AssertPreEvaluationBlocksEqual(preEvalGenesis, genesis);
                _output.WriteLine("#1: {0}", genesis);

                var blockChain = new BlockChain <Arithmetic>(
                    policy,
                    stagePolicy,
                    fx.Store,
                    fx.StateStore,
                    genesis
                    );
                AssertBencodexEqual((Bencodex.Types.Integer) 123, blockChain.GetState(address));

                HashDigest <SHA256> identicalGenesisStateRootHash =
                    preEvalGenesis.DetermineStateRootHash(blockChain);
                AssertBytesEqual(genesis.StateRootHash, identicalGenesisStateRootHash);

                BlockContent <Arithmetic> content1 = _contents.Block1;
                content1.PreviousHash = genesis.Hash;
                content1.Difficulty   = 2;
                content1.Transactions = new[] { _contents.Tx0InBlock1 };
                PreEvaluationBlock <Arithmetic> preEval1 = content1.Mine(policy.GetHashAlgorithm(1));

                Block <Arithmetic> block1 = preEval1.Evaluate(_contents.Block1Key, blockChain);
                AssertPreEvaluationBlocksEqual(preEval1, block1);
                _output.WriteLine("#1: {0}", block1);

                HashDigest <SHA256> identicalBlock1StateRootHash =
                    preEval1.DetermineStateRootHash(blockChain);
                AssertBytesEqual(block1.StateRootHash, identicalBlock1StateRootHash);

                blockChain.Append(block1);
                AssertBencodexEqual((Bencodex.Types.Integer) 158, blockChain.GetState(address));
            }
        }
コード例 #8
0
ファイル: StagePolicy.cs プロジェクト: planetarium/lib9c
        public StagePolicy(TimeSpan txLifeTime, int quotaPerSigner)
        {
            if (quotaPerSigner < 1)
            {
                throw new ArgumentOutOfRangeException(
                          $"{nameof(quotaPerSigner)} must be positive: ${quotaPerSigner}");
            }

            _txs            = new ConcurrentDictionary <Address, SortedList <Transaction <NCAction>, TxId> >();
            _quotaPerSigner = quotaPerSigner;
            _impl           = (txLifeTime == default)
                ? new VolatileStagePolicy <NCAction>()
                : new VolatileStagePolicy <NCAction>(txLifeTime);
        }
コード例 #9
0
ファイル: BlockPolicyTest.cs プロジェクト: planetarium/lib9c
        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));
        }
コード例 #10
0
        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);
        }
コード例 #11
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));
        }
コード例 #12
0
ファイル: BlockPolicyTest.cs プロジェクト: planetarium/lib9c
        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() }
                    );
            });
        }
コード例 #13
0
ファイル: BlockPolicyTest.cs プロジェクト: planetarium/lib9c
        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));
        }
コード例 #14
0
ファイル: BlockPolicyTest.cs プロジェクト: planetarium/lib9c
        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);
        }
コード例 #15
0
        public async Task GetNextBlockDifficultyWithAuthorizedMinersState()
        {
            var adminPrivateKey = new PrivateKey();
            var adminAddress    = adminPrivateKey.ToAddress();
            var minerKey        = new PrivateKey();
            var miner           = minerKey.ToAddress();
            var miners          = new[] { miner };

            var blockPolicySource = new BlockPolicySource(Logger.None);
            IBlockPolicy <PolymorphicAction <ActionBase> > policy      = blockPolicySource.GetPolicy(4096, 100);
            IStagePolicy <PolymorphicAction <ActionBase> > stagePolicy =
                new VolatileStagePolicy <PolymorphicAction <ActionBase> >();
            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,
                stagePolicy,
                store,
                stateStore,
                genesis,
                renderers: new[] { blockPolicySource.BlockRenderer }
                );
            var minerObj = new Miner(blockChain, null, minerKey, true);

            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));

            minerObj.StageProofTransaction();
            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));

            minerObj.StageProofTransaction();
            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));

            minerObj.StageProofTransaction();
            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));
        }
コード例 #16
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);
            IStagePolicy <PolymorphicAction <ActionBase> > stagePolicy =
                new VolatileStagePolicy <PolymorphicAction <ActionBase> >();
            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,
                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 = 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));
        }
コード例 #17
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();
        }
コード例 #18
0
ファイル: Program.cs プロジェクト: GunnerJnr/lib9c
        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);
        }
コード例 #19
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);
        }
コード例 #20
0
ファイル: BlockPolicyTest.cs プロジェクト: planetarium/lib9c
        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));
        }
コード例 #21
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);
        }
コード例 #22
0
ファイル: BlockPolicyTest.cs プロジェクト: planetarium/lib9c
        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));
        }
コード例 #23
0
ファイル: Program.cs プロジェクト: planetarium/libplanet
        public async Task Run(
            [Option(
                 "store-path",
                 new[] { 'P' },
                 Description = @"The path of the blockchain store. If omitted (default)
in memory version is used.")]
            string storePath,
            [Option(
                 "store-type",
                 new[] { 'T' },
                 Description = @"The type of the blockchain store. If omitted (default)
in DefaultStore is used.")]
            string storeType,
            [Option(
                 "genesis-block",
                 new[] { 'G' },
                 Description = "The path of the genesis block. It should be absolute or http url.")]
            string genesisBlockPath,
            [Option("debug", new[] { 'd' }, Description = "Print logs for debugging as well.")]
            bool debug = false,
            [Option("host", new[] { 'H' }, Description = "The host address to listen.")]
            string host = "0.0.0.0",
            [Option("port", new[] { 'p' }, Description = "The port number to listen.")]
            int port = 5000,
            [Option(
                 "block-interval",
                 new[] { 'i' },
                 Description = @"An appropriate interval in milliseconds between
consecutive blocks.")]
            int blockIntervalMilliseconds = 5000,
            [Option(
                 "minimum-difficulty",
                 new[] { 'm' },
                 Description = "Allowed minimum difficulty for mining blocks.")]
            long minimumDifficulty = 1024L,
            [Option(
                 "difficulty-bound-divisor",
                 new[] { 'D' },
                 Description = "A bound divisor to determine precision of block difficulties.")]
            int difficultyBoundDivisor = 128,
            [Option(
                 "workers",
                 new[] { 'W' },
                 Description = "The number of swarm workers.")]
            int workers = 50,
            [Option(
                 "app-protocol-version",
                 new[] { 'V' },
                 Description = "An app protocol version token.")]
            string appProtocolVersionToken = null,
            [Option(
                 "mysql-server",
                 Description = "A hostname of MySQL server.")]
            string mysqlServer = null,
            [Option(
                 "mysql-port",
                 Description = "A port of MySQL server.")]
            uint?mysqlPort = null,
            [Option(
                 "mysql-username",
                 Description = "The name of MySQL user.")]
            string mysqlUsername = null,
            [Option(
                 "mysql-password",
                 Description = "The password of MySQL user.")]
            string mysqlPassword = null,
            [Option(
                 "mysql-database",
                 Description = "The name of MySQL database to use.")]
            string mysqlDatabase = null,
            [Option(
                 "max-transactions-per-block",
                 Description = @"The number of maximum transactions able to be included
in a block.")]
            int maxTransactionsPerBlock = 100,
            [Option(
                 "max-block-bytes",
                 Description = @"The number of maximum bytes size of blocks except
for genesis block.")]
            int maxBlockBytes = 100 * 1024,
            [Option(
                 "max-genesis-bytes",
                 Description = "The number of maximum bytes size of the genesis block.")]
            int maxGenesisBytes = 1024 * 1024,
            [Option(
                 "seed",
                 new[] { 's' },
                 Description = @"Seed nodes to join to the network as a node. The format of each
seed is a comma-separated triple of a peer's hexadecimal public key, host, and port number.
E.g., `02ed49dbe0f2c34d9dff8335d6dd9097f7a3ef17dfb5f048382eebc7f451a50aa1,example.com,31234'.
If omitted (default) explorer only the local blockchain store.")]
            string[] seedStrings = null,
            [Option(
                 "ice-server",
                 new[] { 'I' },
                 Description = "URL to ICE server (TURN/STUN) to work around NAT.")]
            string iceServerUrl = null
            )
        {
            Options options = new Options(
                debug,
                host,
                port,
                blockIntervalMilliseconds,
                minimumDifficulty,
                difficultyBoundDivisor,
                workers,
                appProtocolVersionToken,
                mysqlServer,
                mysqlPort,
                mysqlUsername,
                mysqlPassword,
                mysqlDatabase,
                maxTransactionsPerBlock,
                maxBlockBytes,
                maxGenesisBytes,
                seedStrings,
                iceServerUrl,
                storePath,
                storeType,
                genesisBlockPath);

            var loggerConfig = new LoggerConfiguration();

            loggerConfig = options.Debug
                ? loggerConfig.MinimumLevel.Debug()
                : loggerConfig.MinimumLevel.Information();
            loggerConfig = loggerConfig
                           .MinimumLevel.Override("Microsoft", LogEventLevel.Information)
                           .Enrich.FromLogContext()
                           .WriteTo.Console();
            Log.Logger = loggerConfig.CreateLogger();

            try
            {
                IRichStore  store      = LoadStore(options);
                IStateStore stateStore = new NoOpStateStore();

                IBlockPolicy <NullAction> policy =
                    new DumbBlockPolicy(LoadBlockPolicy <NullAction>(options));
                IStagePolicy <NullAction> stagePolicy =
                    new VolatileStagePolicy <NullAction>();
                var blockChain =
                    new BlockChain <NullAction>(
                        policy,
                        stagePolicy,
                        store,
                        stateStore,
                        options.GetGenesisBlock(policy));
                Startup.PreloadedSingleton  = false;
                Startup.BlockChainSingleton = blockChain;
                Startup.StoreSingleton      = store;

                IWebHost webHost = WebHost.CreateDefaultBuilder()
                                   .UseStartup <ExplorerStartup <NullAction, Startup> >()
                                   .UseSerilog()
                                   .UseUrls($"http://{options.Host}:{options.Port}/")
                                   .Build();

                Swarm <NullAction> swarm = null;
                if (!(options.Seeds is null))
                {
                    string aggregatedSeedStrings =
                        options.SeedStrings.Aggregate(string.Empty, (s, s1) => s + s1);
                    Console.Error.WriteLine(
                        $"Seeds are {aggregatedSeedStrings}");

                    // TODO: Take privateKey as a CLI option
                    // TODO: Take appProtocolVersion as a CLI option
                    // TODO: Take host as a CLI option
                    // TODO: Take listenPort as a CLI option
                    if (options.IceServer is null)
                    {
                        Console.Error.WriteLine(
                            "error: -s/--seed option requires -I/--ice-server as well."
                            );
                        Environment.Exit(1);
                        return;
                    }

                    Console.Error.WriteLine("Creating Swarm.");

                    var privateKey = new PrivateKey();

                    // FIXME: The appProtocolVersion should be fixed properly.
                    var swarmOptions = new SwarmOptions
                    {
                        MaxTimeout = TimeSpan.FromSeconds(10),
                    };

                    swarm = new Swarm <NullAction>(
                        blockChain,
                        privateKey,
                        options.AppProtocolVersionToken is string t
                            ? AppProtocolVersion.FromToken(t)
                            : default(AppProtocolVersion),
                        differentAppProtocolVersionEncountered: (p, pv, lv) => true,
                        workers: options.Workers,
                        iceServers: new[] { options.IceServer },
                        options: swarmOptions
                        );
                }

                using (var cts = new CancellationTokenSource())
                    using (swarm)
                    {
                        Console.CancelKeyPress += (sender, eventArgs) =>
                        {
                            eventArgs.Cancel = true;
                            cts.Cancel();
                        };

                        try
                        {
                            await Task.WhenAll(
                                webHost.RunAsync(cts.Token),
                                StartSwarmAsync(swarm, options.Seeds, cts.Token)
                                );
                        }
                        catch (OperationCanceledException)
                        {
                            await swarm?.StopAsync(waitFor : TimeSpan.FromSeconds(1))
                            .ContinueWith(_ => NetMQConfig.Cleanup(false));
                        }
                    }
            }
            catch (InvalidOptionValueException e)
            {
                string expectedValues = string.Join(", ", e.ExpectedValues);
                Console.Error.WriteLine($"Unexpected value given through '{e.OptionName}'\n"
                                        + $"  given value: {e.OptionValue}\n"
                                        + $"  expected values: {expectedValues}");
            }
        }