示例#1
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);
示例#2
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(10000, 100);
            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,
                store,
                stateStore,
                genesis,
                renderers: new[] { blockPolicySource.BlockRenderer }
                );

            Assert.Throws <MissingActionTypeException>(() =>
            {
                blockChain.MakeTransaction(
                    adminPrivateKey,
                    new PolymorphicAction <ActionBase>[] { new RewardGold() }
                    );
            });
        }
示例#3
0
        public DefaultStoreFixture(bool memory = true, IAction blockAction = null)
            : base(blockAction)
        {
            if (memory)
            {
                Path = null;
            }
            else
            {
                Path = System.IO.Path.Combine(
                    System.IO.Path.GetTempPath(),
                    $"defaultstore_test_{Guid.NewGuid()}"
                    );
            }

            var store = new DefaultStore(Path, blockCacheSize: 2, txCacheSize: 2);

            Store      = store;
            StateStore = LoadTrieStateStore(Path);
        }
示例#4
0
        public void DoesTransactionFollowsPolicyWithEmpty()
        {
            var adminPrivateKey = new PrivateKey();
            var adminAddress    = new Address(adminPrivateKey.PublicKey);
            IBlockPolicy <PolymorphicAction <ActionBase> > policy  = BlockPolicy.GetPolicy(10000);
            Block <PolymorphicAction <ActionBase> >        genesis = MakeGenesisBlock(adminAddress, ImmutableHashSet <Address> .Empty);

            using var store = new DefaultStore(null);
            _ = new BlockChain <PolymorphicAction <ActionBase> >(
                policy,
                store,
                genesis
                );
            Transaction <PolymorphicAction <ActionBase> > tx = Transaction <PolymorphicAction <ActionBase> > .Create(
                0,
                new PrivateKey(),
                genesis.Hash,
                new PolymorphicAction <ActionBase>[] { });

            Assert.True(policy.DoesTransactionFollowsPolicy(tx));
        }
示例#5
0
        private void Init(PrivateKey privateKey, string path, IEnumerable <Peer> peers,
                          IEnumerable <IceServer> iceServers, string host, int?port)
        {
            var policy = new BlockPolicy <PolymorphicAction <ActionBase> >(
                null,
                BlockInterval,
                100000,
                2048);

            PrivateKey = privateKey;
            Address    = privateKey.PublicKey.ToAddress();
            _store     = new DefaultStore(path, flush: false);
            Block <PolymorphicAction <ActionBase> > genesis =
                Block <PolymorphicAction <ActionBase> > .FromBencodex(
                    File.ReadAllBytes(GenesisBlockPath)
                    );

            _blocks = new BlockChain <PolymorphicAction <ActionBase> >(
                policy,
                _store,
                genesis
                );

            if (!(host is null) || iceServers.Any())
            {
                _swarm = new Swarm <PolymorphicAction <ActionBase> >(
                    _blocks,
                    privateKey,
                    appProtocolVersion: 1,
                    host: host,
                    listenPort: port,
                    iceServers: iceServers,
                    differentVersionPeerEncountered: DifferentAppProtocolVersionPeerEncountered
                    );

                _seedPeers    = peers.Where(peer => peer.PublicKey != privateKey.PublicKey).ToImmutableList();
                _trustedPeers = _seedPeers.Select(peer => peer.Address).ToImmutableHashSet();
            }
            _cancellationTokenSource = new CancellationTokenSource();
        }
示例#6
0
        static void Main(string[] args)
        {
            var ds = DefaultStore.GetDeployerStore();

            var serializer = new ConfigurationContainer()
                             .Type <Device>().EnableReferences(x => x.Id)
                             .UseOptimizedNamespaces()
                             .Create();

            var serialized = serializer.Serialize(new XmlWriterSettings()
            {
                Indent = true
            }, ds);

            File.WriteAllText(OutputXml, serialized);

            var psi = new ProcessStartInfo(OutputXml)
            {
                UseShellExecute = true,
            };

            Process.Start(psi);
        }
        private void ValidateNextBlockInvalidStateRootHash()
        {
            IKeyValueStore stateKeyValueStore = new MemoryKeyValueStore();
            var            policy             = new BlockPolicy <DumbAction>(
                blockInterval: TimeSpan.FromMilliseconds(3 * 60 * 60 * 1000)
                );
            var stateStore   = new TrieStateStore(stateKeyValueStore);
            var store        = new DefaultStore(null);
            var genesisBlock = TestUtils.MineGenesis <DumbAction>(
                policy.GetHashAlgorithm,
                TestUtils.GenesisMiner.PublicKey
                ).Evaluate(TestUtils.GenesisMiner, policy.BlockAction, stateStore);

            store.PutBlock(genesisBlock);
            Assert.NotNull(store.GetStateRootHash(genesisBlock.Hash));

            var chain1 = new BlockChain <DumbAction>(
                policy,
                new VolatileStagePolicy <DumbAction>(),
                store,
                stateStore,
                genesisBlock
                );

            Block <DumbAction> block1 = new BlockContent <DumbAction>
            {
                Index           = 1,
                Difficulty      = 1024L,
                TotalDifficulty = genesisBlock.TotalDifficulty + 1024,
                PublicKey       = TestUtils.GenesisMiner.PublicKey,
                PreviousHash    = genesisBlock.Hash,
                Timestamp       = genesisBlock.Timestamp.AddSeconds(1),
                Transactions    = _emptyTransaction,
            }.Mine(policy.GetHashAlgorithm(1)).Evaluate(TestUtils.GenesisMiner, chain1);

            var policyWithBlockAction = new BlockPolicy <DumbAction>(
                new SetStatesAtBlock(default, (Text)"foo", 1),
示例#8
0
        public async void Evaluate()
        {
            var  privateKey = new PrivateKey();
            var  address    = privateKey.ToAddress();
            long blockIndex = 1;

            var action = new EvaluateTestAction();

            var store      = new DefaultStore(null);
            var stateStore = new TrieStateStore(new MemoryKeyValueStore());
            var chain      = TestUtils.MakeBlockChain <EvaluateTestAction>(
                policy: new BlockPolicy <EvaluateTestAction>(),
                store: store,
                stateStore: stateStore);
            var tx = Transaction <EvaluateTestAction> .Create(
                nonce : 0,
                privateKey : privateKey,
                genesisHash : chain.Genesis.Hash,
                actions : new[] { action });

            chain.StageTransaction(tx);
            var miner = new PrivateKey();
            await chain.MineBlock(miner);

            var evaluations = chain.ActionEvaluator.Evaluate(
                chain.Tip,
                StateCompleterSet <EvaluateTestAction> .Recalculate);

            Assert.False(evaluations[0].InputContext.BlockAction);
            Assert.Single(evaluations);
            Assert.Null(evaluations.Single().Exception);
            Assert.Equal(chain.GetState(action.SignerKey), (Text)address.ToHex());
            Assert.Equal(chain.GetState(action.MinerKey), (Text)miner.ToAddress().ToHex());
            var state = chain.GetState(action.BlockIndexKey);

            Assert.Equal((long)(Integer)state, blockIndex);
        }
示例#9
0
        public async void EvaluateWithException()
        {
            var privateKey = new PrivateKey();
            var address    = privateKey.ToAddress();

            var action = new ThrowException {
                ThrowOnRehearsal = false, ThrowOnExecution = true
            };

            var store      = new DefaultStore(null);
            var stateStore = new TrieStateStore(new MemoryKeyValueStore());
            var chain      = TestUtils.MakeBlockChain <ThrowException>(
                policy: new BlockPolicy <ThrowException>(),
                store: store,
                stateStore: stateStore);
            var tx = Transaction <ThrowException> .Create(
                nonce : 0,
                privateKey : privateKey,
                genesisHash : chain.Genesis.Hash,
                actions : new[] { action });

            chain.StageTransaction(tx);
            await chain.MineBlock(new PrivateKey());

            var evaluations = chain.ActionEvaluator.Evaluate(
                chain.Tip,
                StateCompleterSet <ThrowException> .Recalculate);

            Assert.False(evaluations[0].InputContext.BlockAction);
            Assert.Single(evaluations);
            Assert.NotNull(evaluations.Single().Exception);
            Assert.IsType <UnexpectedlyTerminatedActionException>(
                evaluations.Single().Exception);
            Assert.IsType <ThrowException.SomeException>(
                evaluations.Single().Exception.InnerException);
        }
示例#10
0
        public GraphQLTestBase(ITestOutputHelper output)
        {
            Log.Logger = new LoggerConfiguration().MinimumLevel.Debug().WriteTo.Console().CreateLogger();

            _output = output;

            var store      = new DefaultStore(null);
            var stateStore = new TrieStateStore(
                new DefaultKeyValueStore(null),
                new DefaultKeyValueStore(null)
                );
            var genesisBlock = BlockChain <PolymorphicAction <ActionBase> > .MakeGenesisBlock(blockAction : new RewardGold());

            var blockPolicy = new BlockPolicy <PolymorphicAction <ActionBase> >(blockAction: new RewardGold());
            var blockChain  = new BlockChain <PolymorphicAction <ActionBase> >(
                blockPolicy,
                store,
                stateStore,
                genesisBlock,
                renderers: new IRenderer <PolymorphicAction <ActionBase> >[] { new BlockRenderer(), new ActionRenderer() }
                );

            var tempKeyStorePath = Path.Join(Path.GetTempPath(), Path.GetRandomFileName());
            var keyStore         = new Web3KeyStore(tempKeyStorePath);

            StandaloneContextFx = new StandaloneContext
            {
                BlockChain = blockChain,
                KeyStore   = keyStore,
            };

            Schema = new StandaloneSchema(new TestServiceProvider(StandaloneContextFx));
            Schema.Subscription.As <StandaloneSubscription>().RegisterTipChangedSubscription();

            DocumentExecutor = new DocumentExecuter();
        }
示例#11
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);
        }
示例#12
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));
        }
示例#13
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));
        }
示例#14
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));
        }
示例#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);
        }
示例#16
0
        public static async Task Main(string[] args)
        {
            Options options = Options.Parse(args, Console.Error);

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

            bool readOnlyMode = options.Seeds is null;

            // Initialized DefaultStore.
            IStore store = new DefaultStore(
                path: options.StorePath,
                flush: false,
                readOnly: readOnlyMode
                );

            if (options.Seeds.Any())
            {
                // Warp up store.
                store = new RichStore(
                    store,
                    path: options.StorePath,
                    flush: false,
                    readOnly: readOnlyMode
                    );
            }

            IBlockPolicy <AppAgnosticAction> policy = new BlockPolicy <AppAgnosticAction>(
                null,
                blockIntervalMilliseconds: options.BlockIntervalMilliseconds,
                minimumDifficulty: options.MinimumDifficulty,
                difficultyBoundDivisor: options.DifficultyBoundDivisor);
            var blockChain = new BlockChain <AppAgnosticAction>(policy, store, options.GenesisBlock);

            Startup.BlockChainSingleton = blockChain;
            Startup.StoreSingleton      = store;

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

            Swarm <AppAgnosticAction> swarm = null;

            if (options.Seeds.Any())
            {
                Console.WriteLine(
                    $"Seeds are {options.SeedStrings.Aggregate(string.Empty, (s, s1) => s + s1)}");

                // 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.WriteLine("Creating Swarm.");

                var privateKey = new PrivateKey();

                // FIXME: The appProtocolVersion should be fixed properly.
                swarm = new Swarm <AppAgnosticAction>(
                    blockChain,
                    privateKey,
                    options.AppProtocolVersionToken is string t
                        ? AppProtocolVersion.FromToken(t)
                        : default(AppProtocolVersion),
                    differentAppProtocolVersionEncountered: (p, pv, lv) => true,
                    iceServers: new[] { options.IceServer }
                    );
            }

            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));
                    }
                }
        }
示例#17
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);
        }
示例#18
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));
        }
示例#19
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));
        }
示例#20
0
        private static IRichStore LoadStore(Options options)
        {
            bool   readOnlyMode = options.Seeds is null;
            IStore innerStore;

            switch (options.StoreType)
            {
            case "rocksdb":
                innerStore = new RocksDBStore.RocksDBStore(
                    options.StorePath,
                    maxTotalWalSize: 16 * 1024 * 1024,
                    keepLogFileNum: 1);
                break;

            case "monorocksdb":
                innerStore = new RocksDBStore.MonoRocksDBStore(
                    options.StorePath,
                    maxTotalWalSize: 16 * 1024 * 1024,
                    keepLogFileNum: 1);
                break;

            case "default":
                innerStore = new DefaultStore(
                    options.StorePath,
                    flush: false,
                    readOnly: readOnlyMode);
                break;

            default:
                // FIXME: give available store type as argument hint without code duplication.
                var          availableStoreTypes = new[] { "rocksdb", "default" };
                const string longOptionName      = "store-type";
                throw new InvalidOptionValueException(
                          "--" + longOptionName,
                          options.StoreType,
                          availableStoreTypes);
            }

            bool useMySQL = !string.IsNullOrEmpty(options.MySQLDatabase) &&
                            !string.IsNullOrEmpty(options.MySQLPassword) &&
                            !string.IsNullOrEmpty(options.MySQLServer) &&
                            !string.IsNullOrEmpty(options.MySQLUsername) &&
                            !(options.MySQLPort is null);

            if (useMySQL)
            {
                var mySqlOptions = new MySQLRichStoreOptions(
                    options.MySQLDatabase,
                    options.MySQLServer,
                    options.MySQLPort.Value,
                    options.MySQLUsername,
                    options.MySQLPassword);
                return(new MySQLRichStore(
                           innerStore,
                           mySqlOptions
                           ));
            }
            else
            {
                return(new LiteDBRichStore(
                           innerStore,
                           path: options.StorePath,
                           flush: false,
                           readOnly: readOnlyMode
                           ));
            }
        }
示例#21
0
        public void ListAllStateReferences()
        {
            Address address1 = Fx.Address1;
            Address address2 = Fx.Address2;
            Address address3 = Fx.Address3;

            var store = new DefaultStore(null);
            var chain = TestUtils.MakeBlockChain(new NullPolicy <DumbAction>(), store);

            var block1 = TestUtils.MineNext(chain.Genesis);
            var block2 = TestUtils.MineNext(block1);
            var block3 = TestUtils.MineNext(block2);

            Transaction <DumbAction> tx4 = Fx.MakeTransaction(
                new[]
            {
                new DumbAction(address1, "foo1"),
                new DumbAction(address2, "foo2"),
            }
                );
            Block <DumbAction> block4 = TestUtils.MineNext(
                block3,
                new[] { tx4 },
                blockInterval: TimeSpan.FromSeconds(10));

            Transaction <DumbAction> tx5 = Fx.MakeTransaction(
                new[]
            {
                new DumbAction(address1, "bar1"),
                new DumbAction(address3, "bar3"),
            }
                );
            Block <DumbAction> block5 = TestUtils.MineNext(
                block4,
                new[] { tx5 },
                blockInterval: TimeSpan.FromSeconds(10));

            Block <DumbAction> block6 = TestUtils.MineNext(
                block5,
                blockInterval: TimeSpan.FromSeconds(10));

            chain.Append(block1);
            chain.Append(block2);
            chain.Append(block3);
            chain.Append(block4);
            chain.Append(block5);
            chain.Append(block6);

            Guid chainId = chain.Id;
            IImmutableDictionary <Address, IImmutableList <HashDigest <SHA256> > > refs;

            refs = store.ListAllStateReferences(chainId);
            Assert.Equal(
                new HashSet <Address> {
                address1, address2, address3
            },
                refs.Keys.ToHashSet()
                );
            Assert.Equal(new[] { block4.Hash, block5.Hash }, refs[address1]);
            Assert.Equal(new[] { block4.Hash }, refs[address2]);
            Assert.Equal(new[] { block5.Hash }, refs[address3]);

            refs = store.ListAllStateReferences(chainId, lowestIndex: block4.Index + 1);
            Assert.Equal(new HashSet <Address> {
                address1, address3
            }, refs.Keys.ToHashSet());
            Assert.Equal(new[] { block5.Hash }, refs[address1]);
            Assert.Equal(new[] { block5.Hash }, refs[address3]);

            refs = store.ListAllStateReferences(chainId, highestIndex: block4.Index);
            Assert.Equal(new HashSet <Address> {
                address1, address2,
            }, refs.Keys.ToHashSet());
            Assert.Equal(new[] { block4.Hash }, refs[address1]);
            Assert.Equal(new[] { block4.Hash }, refs[address2]);
        }
示例#22
0
        public void EvaluateWithCriticalException()
        {
            var privateKey = new PrivateKey();
            var address    = privateKey.ToAddress();

            var action = new ThrowException
            {
                ThrowOnRehearsal     = false,
                ThrowOnExecution     = true,
                ExceptionTypeToThrow = typeof(OutOfMemoryException),
            };

            var store      = new DefaultStore(null);
            var stateStore =
                new TrieStateStore(new MemoryKeyValueStore());
            var chain = TestUtils.MakeBlockChain <ThrowException>(
                policy: new BlockPolicy <ThrowException>(),
                store: store,
                stateStore: stateStore);
            var genesis = chain.Genesis;
            // Evaluation is run with rehearsal true to get updated addresses on tx creation.
            var tx = Transaction <ThrowException> .Create(
                nonce : 0,
                privateKey : privateKey,
                genesisHash : genesis.Hash,
                actions : new[] { action });

            PreEvaluationBlock <ThrowException> block = new BlockContent <ThrowException>
            {
                Index           = 1,
                Difficulty      = 1,
                TotalDifficulty = genesis.TotalDifficulty + 1,
                PublicKey       = new PrivateKey().PublicKey,
                PreviousHash    = genesis.Hash,
                Timestamp       = DateTimeOffset.UtcNow,
                Transactions    = ImmutableArray.Create(tx),
            }.Mine(HashAlgorithmType.Of <SHA256>());
            IAccountStateDelta previousStates = genesis.ProtocolVersion > 0
                ? new AccountStateDeltaImpl(
                ActionEvaluator <DumbAction> .NullAccountStateGetter,
                ActionEvaluator <DumbAction> .NullAccountBalanceGetter,
                genesis.Miner)
                : new AccountStateDeltaImplV0(
                ActionEvaluator <DumbAction> .NullAccountStateGetter,
                ActionEvaluator <DumbAction> .NullAccountBalanceGetter,
                genesis.Miner);

            // ToList() is required for realization.
            chain.ActionEvaluator.EvaluateTx(
                block: block,
                tx: tx,
                previousStates: previousStates,
                rehearsal: true).ToList();
            Assert.Throws <OutOfMemoryException>(
                () => chain.ActionEvaluator.EvaluateTx(
                    block: block,
                    tx: tx,
                    previousStates: previousStates,
                    rehearsal: false).ToList());
            Assert.Throws <OutOfMemoryException>(
                () => chain.ActionEvaluator.Evaluate(
                    block: block,
                    stateCompleterSet: StateCompleterSet <ThrowException> .Recalculate).ToList());
        }
示例#23
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));
        }
 public Task <DeployerStore> Get()
 {
     return(Task.FromResult(DefaultStore.GetDeployerStore()));
 }
示例#25
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));
        }
示例#26
0
        private static IRichStore LoadStore(Options options)
        {
            // FIXME: This method basically does the same thing to Libplanet.Extensions.Cocona's
            // StoreCommand.LoadStoreFromUri() & StatsCommand.LoadStoreFromUri() methods.
            // The duplicate code should be extract to a shared common method.
            // https://github.com/planetarium/libplanet/issues/1573
            bool   readOnlyMode = options.Seeds is null;
            IStore innerStore;

            switch (options.StoreType)
            {
            case "rocksdb":
                innerStore = new RocksDBStore.RocksDBStore(
                    options.StorePath,
                    maxTotalWalSize: 16 * 1024 * 1024,
                    keepLogFileNum: 1);
                break;

            case "default":
                innerStore = new DefaultStore(
                    options.StorePath,
                    flush: false,
                    readOnly: readOnlyMode);
                break;

            default:
                // FIXME: give available store type as argument hint without code duplication.
                var          availableStoreTypes = new[] { "rocksdb", "default" };
                const string longOptionName      = "store-type";
                throw new InvalidOptionValueException(
                          "--" + longOptionName,
                          options.StoreType,
                          availableStoreTypes);
            }

            bool useMySQL = !string.IsNullOrEmpty(options.MySQLDatabase) &&
                            !string.IsNullOrEmpty(options.MySQLPassword) &&
                            !string.IsNullOrEmpty(options.MySQLServer) &&
                            !string.IsNullOrEmpty(options.MySQLUsername) &&
                            !(options.MySQLPort is null);

            if (useMySQL)
            {
                var mySqlOptions = new MySQLRichStoreOptions(
                    options.MySQLDatabase,
                    options.MySQLServer,
                    options.MySQLPort.Value,
                    options.MySQLUsername,
                    options.MySQLPassword);
                return(new MySQLRichStore(
                           innerStore,
                           mySqlOptions
                           ));
            }
            else
            {
                return(new LiteDBRichStore(
                           innerStore,
                           path: options.StorePath,
                           flush: false,
                           readOnly: readOnlyMode
                           ));
            }
        }
示例#27
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));
        }
示例#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);
        }