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);
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() } ); }); }
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); }
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)); }
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(); }
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),
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); }
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); }
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(); }
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); }
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)); }
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)); }
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)); }
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); }
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)); } } }
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); }
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)); }
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)); }
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 )); } }
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]); }
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()); }
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())); }
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)); }
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 )); } }
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)); }
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); }