private Swarm <DumbAction> CreateSwarm( PrivateKey privateKey = null, AppProtocolVersion?appProtocolVersion = null, string host = null, int?listenPort = null, IEnumerable <IceServer> iceServers = null, DifferentAppProtocolVersionEncountered differentAppProtocolVersionEncountered = null, IEnumerable <PublicKey> trustedAppProtocolVersionSigners = null, SwarmOptions options = null, IBlockPolicy <DumbAction> policy = null, Block <DumbAction> genesis = null) { policy = policy ?? new BlockPolicy <DumbAction>(new MinerReward(1)); var fx = new MemoryStoreFixture(policy.BlockAction); var blockchain = MakeBlockChain( policy, fx.Store, fx.StateStore, genesisBlock: genesis ); return(CreateSwarm( blockchain, privateKey, appProtocolVersion, host, listenPort, iceServers, differentAppProtocolVersionEncountered, trustedAppProtocolVersionSigners, options)); }
public BlockPolicyTest(ITestOutputHelper output) { _fx = new DefaultStoreFixture(); _output = output; _policy = new BlockPolicy <DumbAction>( null, TimeSpan.FromHours(3), 1024, 128); _chain = new BlockChain <DumbAction>( _policy, _fx.Store, _fx.StateStore, _fx.GenesisBlock); _emptyTransaction = new List <Transaction <DumbAction> >(); _genesis = _chain.Genesis; _validNext = Block <DumbAction> .Mine( 1, 1024, _genesis.TotalDifficulty, _genesis.Miner.Value, _genesis.Hash, _genesis.Timestamp.AddSeconds(1), _emptyTransaction); }
public void DoesTransactionFollowsPolicyWithEmpty() { var adminPrivateKey = new PrivateKey(); var adminAddress = new Address(adminPrivateKey.PublicKey); var blockPolicySource = new BlockPolicySource(Logger.None); IBlockPolicy<PolymorphicAction<ActionBase>> policy = blockPolicySource.GetPolicy(10000, 100); Block<PolymorphicAction<ActionBase>> genesis = MakeGenesisBlock(adminAddress, ImmutableHashSet<Address>.Empty); using var store = new DefaultStore(null); using var stateStore = new TrieStateStore(new DefaultKeyValueStore(null), new DefaultKeyValueStore(null)); var blockChain = new BlockChain<PolymorphicAction<ActionBase>>( policy, store, stateStore, genesis, renderers: new[] { blockPolicySource.BlockRenderer } ); Transaction<PolymorphicAction<ActionBase>> tx = Transaction<PolymorphicAction<ActionBase>>.Create( 0, new PrivateKey(), genesis.Hash, new PolymorphicAction<ActionBase>[] { }); Assert.True(policy.DoesTransactionFollowsPolicy(tx, blockChain)); }
public DevLibplanetNodeService( LibplanetNodeServiceProperties <T> properties, IBlockPolicy <T> easyPolicy, IBlockPolicy <T> hardPolicy, IStagePolicy <T> stagePolicy, IEnumerable <IRenderer <T> > renderers, Func <Swarm <T>, Swarm <T>, PrivateKey, CancellationToken, Task> minerLoopAction, Progress <PreloadState> preloadProgress, Action <RPCException, string> exceptionHandlerAction, Action <bool> preloadStatusHandlerAction, bool ignoreBootstrapFailure = false ) : base(properties, easyPolicy, stagePolicy, renderers, null, preloadProgress, exceptionHandlerAction, preloadStatusHandlerAction, ignoreBootstrapFailure) { if (easyPolicy is null) { throw new ArgumentNullException(nameof(easyPolicy)); } if (hardPolicy is null) { throw new ArgumentNullException(nameof(hardPolicy)); } Log.Debug("Initializing node service."); var genesisBlock = LoadGenesisBlock(properties); var iceServers = properties.IceServers; (SubStore, SubStateStore) = LoadStore( properties.StorePath is null ? null : Path.Combine(properties.StorePath, "sub"), properties.StoreType, properties.StoreStatesCacheSize); SubChain = new BlockChain <T>( policy: hardPolicy, stagePolicy: stagePolicy, store: SubStore, stateStore: SubStateStore, genesisBlock: genesisBlock ); _minerLoopAction = minerLoopAction; var subSwarmPrivateKey = new PrivateKey(); Log.Debug( "Address of sub-swarm is: {address}", subSwarmPrivateKey.ToAddress()); SubSwarm = new Swarm <T>( SubChain, subSwarmPrivateKey, properties.AppProtocolVersion, trustedAppProtocolVersionSigners: properties.TrustedAppProtocolVersionSigners, host: "localhost", listenPort: properties.Port + 1, iceServers: iceServers, workers: properties.Workers ); }
internal BlockChain(IBlockPolicy <T> policy, IStore store, string @namespace) : this( policy, store, @namespace is null ? Guid.NewGuid() : Guid.Parse(@namespace) ) { }
public BlockChain(IBlockPolicy <T> policy, IStore store) : this( policy, store, store.GetCanonicalNamespace() ) { }
public BlockChain(IBlockPolicy <T> policy, IStore store) : this( policy, store, store.GetCanonicalChainId() ?? Guid.NewGuid() ) { }
public void ValidateNextBlockTxWithAuthorizedMiners() { var adminPrivateKey = new PrivateKey(); var adminAddress = adminPrivateKey.ToAddress(); var authorizedMinerPrivateKey = new PrivateKey(); (ActivationKey ak, PendingActivationState ps) = ActivationKey.Create( new PrivateKey(), new byte[] { 0x00, 0x01 } ); var blockPolicySource = new BlockPolicySource(Logger.None); IBlockPolicy <PolymorphicAction <ActionBase> > policy = blockPolicySource.GetPolicy( minimumDifficulty: 10_000, hashAlgorithmTypePolicy: null, maxBlockBytesPolicy: null, minTransactionsPerBlockPolicy: null, maxTransactionsPerBlockPolicy: null, maxTransactionsPerSignerPerBlockPolicy: null, authorizedMinersPolicy: AuthorizedMinersPolicy .Default .Add(new SpannedSubPolicy <ImmutableHashSet <Address> >( startIndex: 0, endIndex: 10, filter: index => index % 5 == 0, value: new Address[] { authorizedMinerPrivateKey.ToAddress() } .ToImmutableHashSet())), permissionedMinersPolicy: null); IStagePolicy <PolymorphicAction <ActionBase> > stagePolicy = new VolatileStagePolicy <PolymorphicAction <ActionBase> >(); Block <PolymorphicAction <ActionBase> > genesis = MakeGenesisBlock( adminAddress, ImmutableHashSet.Create(adminAddress), pendingActivations: new[] { ps } ); using var store = new DefaultStore(null); using var stateStore = new TrieStateStore(new DefaultKeyValueStore(null)); var blockChain = new BlockChain <PolymorphicAction <ActionBase> >( policy, stagePolicy, store, stateStore, genesis, renderers: new[] { blockPolicySource.BlockRenderer } ); Transaction <PolymorphicAction <ActionBase> > txFromAuthorizedMiner = Transaction <PolymorphicAction <ActionBase> > .Create( 0, authorizedMinerPrivateKey, genesis.Hash, new PolymorphicAction <ActionBase>[] { ak.CreateActivateAccount(new byte[] { 0x00, 0x01 }) } ); // Deny tx even if contains valid activation key. Assert.NotNull(policy.ValidateNextBlockTx(blockChain, txFromAuthorizedMiner)); }
public async Task DoesTransactionFollowsPolicy() { var adminPrivateKey = new PrivateKey(); var adminAddress = adminPrivateKey.ToAddress(); var activatedPrivateKey = new PrivateKey(); var activatedAddress = activatedPrivateKey.ToAddress(); IBlockPolicy <PolymorphicAction <ActionBase> > policy = BlockPolicy.GetPolicy(10000); IRenderer <PolymorphicAction <ActionBase> > renderer = BlockPolicy.GetRenderer(); Block <PolymorphicAction <ActionBase> > genesis = MakeGenesisBlock( adminAddress, ImmutableHashSet.Create(activatedAddress).Add(adminAddress) ); using var store = new DefaultStore(null); var blockChain = new BlockChain <PolymorphicAction <ActionBase> >( policy, store, store, genesis, renderers: new[] { renderer } ); Transaction <PolymorphicAction <ActionBase> > txByStranger = Transaction <PolymorphicAction <ActionBase> > .Create( 0, new PrivateKey(), genesis.Hash, new PolymorphicAction <ActionBase>[] { } ); // 새로 만든 키는 활성화 유저 리스트에 없기 때문에 차단됩니다. Assert.False(policy.DoesTransactionFollowsPolicy(txByStranger)); var newActivatedPrivateKey = new PrivateKey(); var newActivatedAddress = newActivatedPrivateKey.ToAddress(); // 관리자 계정으로 활성화 시킵니다. 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>[] { } ); // 활성화 된 계정이기 때문에 테스트에 성공합니다. Assert.True(policy.DoesTransactionFollowsPolicy(txByNewActivated)); }
public BlockChain(IBlockPolicy <T> policy, IStore store, Guid id) { _id = id; Policy = policy; Store = store; Blocks = new BlockSet <T>(store, _id.ToString()); Transactions = new TransactionSet <T>(store, _id.ToString()); Addresses = new AddressTransactionSet <T>(store, _id.ToString()); Store.InitNamespace(_id.ToString()); }
internal Block <NullAction> GetGenesisBlock(IBlockPolicy <NullAction> policy) { var uri = new Uri(GenesisBlockPath); using (var client = new WebClient()) { var serialized = client.DownloadData(uri); var dict = (Bencodex.Types.Dictionary)Codec.Decode(serialized); return(BlockMarshaler.UnmarshalBlock <NullAction>(policy.GetHashAlgorithm, dict)); } }
public BlockChain(IBlockPolicy <T> policy, IStore store, Guid id) { Id = id; Policy = policy; Store = store; Blocks = new BlockSet <T>(store); Transactions = new TransactionSet <T>(store); _rwlock = new ReaderWriterLockSlim( LockRecursionPolicy.SupportsRecursion); }
public static (BlockChain <NCAction> Chain, IStore Store) GetBlockChain( ILogger logger, string storePath, bool monorocksdb = false, Guid?chainId = null ) { var policySource = new BlockPolicySource(logger); IBlockPolicy <NCAction> policy = policySource.GetPolicy(); IStagePolicy <NCAction> stagePolicy = new VolatileStagePolicy <NCAction>(); IStore store = monorocksdb ? (IStore) new MonoRocksDBStore(storePath) : new RocksDBStore(storePath); IKeyValueStore stateKeyValueStore = new RocksDBKeyValueStore(Path.Combine(storePath, "states")); IStateStore stateStore = new TrieStateStore(stateKeyValueStore); Guid chainIdValue = chainId ?? store.GetCanonicalChainId() ?? throw new CommandExitedException( "No canonical chain ID. Available chain IDs:\n " + string.Join("\n ", store.ListChainIds()), 1); BlockHash genesisBlockHash; try { genesisBlockHash = store.IterateIndexes(chainIdValue).First(); } catch (InvalidOperationException) { throw new CommandExitedException( $"The chain {chainIdValue} seems empty; try with another chain ID:\n " + string.Join("\n ", store.ListChainIds()), 1 ); } Block <NCAction> genesis = store.GetBlock <NCAction>( policy.GetHashAlgorithm, genesisBlockHash ); BlockChain <NCAction> chain = new BlockChain <NCAction>( policy, stagePolicy, store, stateStore, genesis ); return(chain, store); }
public async void EarnMiningGoldWhenSuccessMining() { var adminPrivateKey = new PrivateKey(); var adminAddress = adminPrivateKey.ToAddress(); var authorizedMinerPrivateKey = new PrivateKey(); (ActivationKey ak, PendingActivationState ps) = ActivationKey.Create( new PrivateKey(), new byte[] { 0x00, 0x01 } ); var blockPolicySource = new BlockPolicySource(Logger.None); IBlockPolicy <PolymorphicAction <ActionBase> > policy = blockPolicySource.GetPolicy( 10_000, null, null, null, null, null, null, null); IStagePolicy <PolymorphicAction <ActionBase> > stagePolicy = new VolatileStagePolicy <PolymorphicAction <ActionBase> >(); Block <PolymorphicAction <ActionBase> > genesis = MakeGenesisBlock( adminAddress, ImmutableHashSet.Create(adminAddress), new AuthorizedMinersState( new[] { authorizedMinerPrivateKey.ToAddress() }, 5, 10 ), pendingActivations: new[] { ps } ); using var store = new DefaultStore(null); using var stateStore = new TrieStateStore(new DefaultKeyValueStore(null)); var blockChain = new BlockChain <PolymorphicAction <ActionBase> >( policy, stagePolicy, store, stateStore, genesis, renderers: new[] { blockPolicySource.BlockRenderer } ); blockChain.MakeTransaction( adminPrivateKey, new PolymorphicAction <ActionBase>[] { new DailyReward(), } ); await blockChain.MineBlock(adminPrivateKey); FungibleAssetValue actualBalance = blockChain.GetBalance(adminAddress, _currency); FungibleAssetValue expectedBalance = new FungibleAssetValue(_currency, 10, 0); Assert.True(expectedBalance.Equals(actualBalance)); }
public async Task BroadcastIgnoreFromDifferentGenesisHash() { var receiverKey = new PrivateKey(); Swarm <DumbAction> receiverSwarm = CreateSwarm(receiverKey); BlockChain <DumbAction> receiverChain = receiverSwarm.BlockChain; var seedStateStore = new TrieStateStore(new MemoryKeyValueStore()); IBlockPolicy <DumbAction> policy = receiverChain.Policy; Block <DumbAction> mismatchedGenesis = new BlockContent <DumbAction> { PublicKey = receiverKey.PublicKey, Timestamp = DateTimeOffset.MinValue, } .Mine(policy.GetHashAlgorithm(0)) .Evaluate(receiverKey, policy.BlockAction, seedStateStore); BlockChain <DumbAction> seedChain = TestUtils.MakeBlockChain( policy, new DefaultStore(path: null), seedStateStore, genesisBlock: mismatchedGenesis); var seedMiner = new PrivateKey(); Swarm <DumbAction> seedSwarm = CreateSwarm(seedChain, seedMiner); try { await StartAsync(receiverSwarm); await StartAsync(seedSwarm); await receiverSwarm.AddPeersAsync(new[] { seedSwarm.AsPeer }, null); Block <DumbAction> block = await seedChain.MineBlock(seedMiner); seedSwarm.BroadcastBlock(block); while (!((NetMQTransport)receiverSwarm.Transport).MessageHistory .Any(msg => msg is BlockHeaderMessage)) { await Task.Delay(100); } await Task.Delay(100); Assert.NotEqual(seedChain.Tip, receiverChain.Tip); } finally { await StopAsync(seedSwarm); await StopAsync(receiverSwarm); seedSwarm.Dispose(); } }
public BlockPolicyTest(ITestOutputHelper output) { _fx = new MemoryStoreFixture(); _output = output; _policy = new BlockPolicy <DumbAction>( blockAction: null, blockInterval: TimeSpan.FromMilliseconds(3 * 60 * 60 * 1000)); _stagePolicy = new VolatileStagePolicy <DumbAction>(); _chain = new BlockChain <DumbAction>( _policy, _stagePolicy, _fx.Store, _fx.StateStore, _fx.GenesisBlock); }
public BlockPolicyTest(ITestOutputHelper output) { _fx = new DefaultStoreFixture(); _output = output; _policy = new BlockPolicy <DumbAction>( null, TimeSpan.FromHours(3), 1024, 128); _chain = new BlockChain <DumbAction>( _policy, _fx.Store, _fx.StateStore, _fx.GenesisBlock); }
public void DoesTransactionFollowsPolicyWithAuthorizedMiners() { var adminPrivateKey = new PrivateKey(); var adminAddress = adminPrivateKey.ToAddress(); var authorizedMinerPrivateKey = new PrivateKey(); (ActivationKey ak, PendingActivationState ps) = ActivationKey.Create( new PrivateKey(), new byte[] { 0x00, 0x01 } ); var blockPolicySource = new BlockPolicySource(Logger.None); IBlockPolicy <PolymorphicAction <ActionBase> > policy = blockPolicySource.GetPolicy(10000, 100); IStagePolicy <PolymorphicAction <ActionBase> > stagePolicy = new VolatileStagePolicy <PolymorphicAction <ActionBase> >(); Block <PolymorphicAction <ActionBase> > genesis = MakeGenesisBlock( adminAddress, ImmutableHashSet.Create(adminAddress), new AuthorizedMinersState( new[] { authorizedMinerPrivateKey.ToAddress() }, 5, 10 ), pendingActivations: new[] { ps } ); using var store = new DefaultStore(null); using var stateStore = new TrieStateStore(new DefaultKeyValueStore(null), new DefaultKeyValueStore(null)); var blockChain = new BlockChain <PolymorphicAction <ActionBase> >( policy, stagePolicy, store, stateStore, genesis, renderers: new[] { blockPolicySource.BlockRenderer } ); Transaction <PolymorphicAction <ActionBase> > txFromAuthorizedMiner = Transaction <PolymorphicAction <ActionBase> > .Create( 0, authorizedMinerPrivateKey, genesis.Hash, new PolymorphicAction <ActionBase>[] { ak.CreateActivateAccount(new byte[] { 0x00, 0x01 }) } ); // Deny tx even if contains valid activation key. Assert.False(policy.DoesTransactionFollowsPolicy(txFromAuthorizedMiner, blockChain)); }
public LibplanetNodeService( LibplanetNodeServiceProperties <T> properties, IBlockPolicy <T> blockPolicy, Func <BlockChain <T>, Swarm <T>, PrivateKey, CancellationToken, Task> minerLoopAction, Progress <PreloadState> preloadProgress, bool ignoreBootstrapFailure = false ) { _properties = properties; var genesisBlock = LoadGenesisBlock(properties); var iceServers = _properties.IceServers; Store = LoadStore( _properties.StorePath, _properties.StoreType, _properties.StoreStatesCacheSize); var chainIds = Store.ListChainIds().ToList(); Log.Debug($"Number of chain ids: {chainIds.Count()}"); foreach (var chainId in chainIds) { Log.Debug($"chainId: {chainId}"); } BlockChain = new BlockChain <T>(blockPolicy, Store, genesisBlock, _properties.Render); _minerLoopAction = minerLoopAction; Swarm = new Swarm <T>( BlockChain, _properties.PrivateKey, _properties.AppProtocolVersion, trustedAppProtocolVersionSigners: _properties.TrustedAppProtocolVersionSigners, host: _properties.Host, listenPort: _properties.Port, iceServers: iceServers, workers: 50, differentAppProtocolVersionEncountered: _properties.DifferentAppProtocolVersionEncountered ); PreloadEnded = new AsyncManualResetEvent(); BootstrapEnded = new AsyncManualResetEvent(); _preloadProgress = preloadProgress; _ignoreBootstrapFailure = ignoreBootstrapFailure; }
internal BlockChain(IBlockPolicy <T> policy, IStore store, Guid id) { Id = id; Policy = policy; Store = store; Blocks = new BlockSet <T>(store); Transactions = new TransactionSet <T>(store); _rwlock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion); _txLock = new object(); if (Store.GetCanonicalChainId() is null) { Store.SetCanonicalChainId(Id); } }
public static BlockChain <T> MakeBlockChain <T>( IBlockPolicy <T> policy, IStore store, IEnumerable <T> actions = null, PrivateKey privateKey = null, DateTimeOffset?timestamp = null, IEnumerable <IRenderer <T> > renderers = null, IStateStore stateStore = null, Block <T> genesisBlock = null ) where T : IAction, new() { actions = actions ?? ImmutableArray <T> .Empty; privateKey = privateKey ?? new PrivateKey( new byte[] { 0xcf, 0x36, 0xec, 0xf9, 0xe4, 0x7c, 0x87, 0x9a, 0x0d, 0xbf, 0x46, 0xb2, 0xec, 0xd8, 0x3f, 0xd2, 0x76, 0x18, 0x2a, 0xde, 0x02, 0x65, 0x82, 0x5e, 0x3b, 0x8c, 0x6b, 0xa2, 0x14, 0x46, 0x7b, 0x76, } ); var tx = Transaction <T> .Create( 0, privateKey, null, actions, timestamp : timestamp ?? DateTimeOffset.MinValue); genesisBlock = genesisBlock ?? new Block <T>( 0, 0, 0, new Nonce(new byte[] { 0x01, 0x00, 0x00, 0x00 }), GenesisMinerAddress, null, timestamp ?? DateTimeOffset.MinValue, new[] { tx, }); return(new BlockChain <T>( policy, store, stateStore ?? store as IStateStore, genesisBlock, renderers: renderers ?? new[] { new ValidatingActionRenderer <T>() } )); }
public static BlockChain <NCAction> MakeBlockChain( BlockRenderer[] blockRenderers, IBlockPolicy <NCAction> policy = null, IStagePolicy <NCAction> stagePolicy = null, IStore store = null, IStateStore stateStore = null) { PrivateKey adminPrivateKey = new PrivateKey(); policy ??= new BlockPolicy <NCAction>(); stagePolicy ??= new VolatileStagePolicy <NCAction>(); store ??= new DefaultStore(null); stateStore ??= new TrieStateStore(new DefaultKeyValueStore(null)); Block <NCAction> genesis = MakeGenesisBlock(adminPrivateKey.ToAddress(), ImmutableHashSet <Address> .Empty); return(new BlockChain <NCAction>(policy, stagePolicy, store, stateStore, genesis, renderers: blockRenderers)); }
public void MustNotIncludeBlockActionAtTransaction() { var adminPrivateKey = new PrivateKey(); var adminAddress = adminPrivateKey.ToAddress(); var authorizedMinerPrivateKey = new PrivateKey(); (ActivationKey ak, PendingActivationState ps) = ActivationKey.Create( new PrivateKey(), new byte[] { 0x00, 0x01 } ); var blockPolicySource = new BlockPolicySource(Logger.None); IBlockPolicy <PolymorphicAction <ActionBase> > policy = blockPolicySource.GetPolicy( 10_000, null, null, null, null, null, null, null); IStagePolicy <PolymorphicAction <ActionBase> > stagePolicy = new VolatileStagePolicy <PolymorphicAction <ActionBase> >(); Block <PolymorphicAction <ActionBase> > genesis = MakeGenesisBlock( adminAddress, ImmutableHashSet.Create(adminAddress), new AuthorizedMinersState( new[] { authorizedMinerPrivateKey.ToAddress() }, 5, 10 ), pendingActivations: new[] { ps } ); using var store = new DefaultStore(null); using var stateStore = new TrieStateStore(new DefaultKeyValueStore(null)); var blockChain = new BlockChain <PolymorphicAction <ActionBase> >( policy, stagePolicy, store, stateStore, genesis, renderers: new[] { blockPolicySource.BlockRenderer } ); Assert.Throws <MissingActionTypeException>(() => { blockChain.MakeTransaction( adminPrivateKey, new PolymorphicAction <ActionBase>[] { new RewardGold() } ); }); }
public BlockPolicyTest(ITestOutputHelper output) { _output = output; _blocks = new List <Block <DumbAction> >(); _policy = new BlockPolicy <DumbAction>( TimeSpan.FromMilliseconds(5000), 1024, 128); _emptyTransaction = new List <Transaction <DumbAction> >(); _genesis = TestUtils.MineGenesis <DumbAction>(); _validNext = Block <DumbAction> .Mine( 1, 1024, _genesis.Miner.Value, _genesis.Hash, _genesis.Timestamp.AddSeconds(1), _emptyTransaction); }
public IntegerSet( IReadOnlyList <BigInteger?> initialStates, IBlockPolicy <Arithmetic> policy = null, IEnumerable <IRenderer <Arithmetic> > renderers = null ) { PrivateKeys = initialStates.Select(_ => new PrivateKey()).ToImmutableArray(); Addresses = PrivateKeys.Select(AddressExtensions.ToAddress).ToImmutableArray(); Txs = initialStates .Select((state, index) => new { State = state, Key = PrivateKeys[index] }) .Where(pair => !(pair.State is null)) .Select(pair => new { State = (BigInteger)pair.State, pair.Key }) .Select(pair => new { Action = Arithmetic.Add(pair.State), pair.Key }) .Select(pair => Transaction <Arithmetic> .Create( 0, pair.Key, null, new[] { pair.Action }, ImmutableHashSet <Address> .Empty.Add(pair.Key.ToAddress()) ) ) .ToImmutableArray(); Miner = new PrivateKey(); policy = policy ?? new NullBlockPolicy <Arithmetic>(); Store = new MemoryStore(); KVStore = new MemoryKeyValueStore(); StateStore = new TrieStateStore(KVStore); Genesis = new BlockContent <Arithmetic> { PublicKey = Miner.PublicKey, Timestamp = DateTimeOffset.UtcNow, Transactions = Txs, }.Mine(policy.GetHashAlgorithm(0)).Evaluate(Miner, policy.BlockAction, StateStore); Chain = new BlockChain <Arithmetic>( policy, new VolatileStagePolicy <Arithmetic>(), Store, StateStore, Genesis, renderers ); }
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)); }
/// <summary> /// Checks if <paramref name="blocks"/> are invalid, and if that /// returns the reason. /// <para>Note that it returns <c>null</c> when blocks are /// <em>valid</em>.</para> /// </summary> /// <param name="policy"><see cref="IBlockPolicy{T}"/> to used for /// validation <paramref name="blocks"/>.</param> /// <param name="blocks">Consecutive <see cref="Block{T}"/>s to /// validate.</param> /// <param name="currentTime">The current time to be used to validate /// of <see cref="Block{T}.Timestamp"/>s. /// Usually <see cref="DateTimeOffset.UtcNow"/> is used.</param> /// <returns>The reason why the given <paramref name="blocks"/> are /// <em>invalid</em>, or <c>null</c> if <paramref name="blocks"/> are /// <em>valid</em>.</returns> /// <typeparam name="T">An <see cref="IAction"/> type. It should match /// to <see cref="Block{T}"/>'s type parameter.</typeparam> /// <seealso cref="IBlockPolicy{T}"/> /// <seealso cref="IBlockPolicy{T}.ValidateNextBlock"/> public static InvalidBlockException ValidateBlocks <T>( this IBlockPolicy <T> policy, IReadOnlyList <Block <T> > blocks, DateTimeOffset currentTime) where T : IAction, new() { var tempBlocks = new List <Block <T> >(); foreach (Block <T> block in blocks) { InvalidBlockException exception = policy.ValidateNextBlock(tempBlocks, block); if (!(exception is null)) { return(exception); } tempBlocks.Add(block); } return(null); }
public NineChroniclesNodeService( PrivateKey?minerPrivateKey, LibplanetNodeServiceProperties <NCAction> properties, Progress <PreloadState>?preloadProgress = null, bool ignoreBootstrapFailure = false, bool ignorePreloadFailure = false, bool strictRendering = false, bool authorizedMiner = false, bool isDev = false, int blockInterval = 10000, int reorgInterval = 0, TimeSpan txLifeTime = default, int minerCount = 1 ) { MinerPrivateKey = minerPrivateKey; Properties = properties; LogEventLevel logLevel = LogEventLevel.Debug; var blockPolicySource = new BlockPolicySource(Log.Logger, logLevel); // BlockPolicy shared through Lib9c. IBlockPolicy <NCAction>?blockPolicy = null; // Policies for dev mode. IBlockPolicy <NCAction>?easyPolicy = null; IBlockPolicy <NCAction>?hardPolicy = null; IStagePolicy <NCAction> stagePolicy = txLifeTime == default ? new VolatileStagePolicy <NCAction>() : new VolatileStagePolicy <NCAction>(txLifeTime); if (isDev) { easyPolicy = new ReorgPolicy(new RewardGold(), 1); hardPolicy = new ReorgPolicy(new RewardGold(), 2); } else { blockPolicy = blockPolicySource.GetPolicy(properties.MinimumDifficulty, properties.MaximumTransactions); } BlockRenderer = blockPolicySource.BlockRenderer; ActionRenderer = blockPolicySource.ActionRenderer; ExceptionRenderer = new ExceptionRenderer(); NodeStatusRenderer = new NodeStatusRenderer(); var renderers = new List <IRenderer <NCAction> >(); var strictRenderer = new StrictRenderer(onError: exc => ExceptionRenderer.RenderException( RPCException.InvalidRenderException, exc.Message.Split("\n")[0] ) ); if (Properties.Render) { renderers.Add(blockPolicySource.BlockRenderer); renderers.Add(blockPolicySource.LoggedActionRenderer); } else if (Properties.LogActionRenders) { renderers.Add(blockPolicySource.BlockRenderer); // The following "nullRenderer" does nothing. It's just for filling // the LoggedActionRenderer<T>() constructor's parameter: IActionRenderer <NCAction> nullRenderer = new AnonymousActionRenderer <NCAction>(); renderers.Add( new LoggedActionRenderer <NCAction>( nullRenderer, Log.Logger, logLevel ) ); } else { renderers.Add(blockPolicySource.LoggedBlockRenderer); } if (strictRendering) { Log.Debug( $"Strict rendering is on. Add {nameof(StrictRenderer)}."); renderers.Add(strictRenderer); } async Task minerLoopAction( BlockChain <NCAction> chain, Swarm <NCAction> swarm, PrivateKey privateKey, CancellationToken cancellationToken) { var miner = new Miner(chain, swarm, privateKey, authorizedMiner); Log.Debug("Miner called."); while (!cancellationToken.IsCancellationRequested) { try { long nextBlockIndex = chain.Tip.Index + 1; bool authBlock = blockPolicy is BlockPolicy bp // Copied from https://git.io/JLxNd && nextBlockIndex > 0 && nextBlockIndex <= bp.AuthorizedMinersState?.ValidUntil && nextBlockIndex % bp.AuthorizedMinersState?.Interval == 0; if (swarm.Running && ((authorizedMiner && authBlock) || (!authorizedMiner && !authBlock))) { Log.Debug("Start mining."); IEnumerable <Task <Block <NCAction> > > miners = Enumerable .Range(0, minerCount) .Select(_ => miner.MineBlockAsync(properties.MaximumTransactions, cancellationToken)); await Task.WhenAll(miners); } else { await Task.Delay(1000, cancellationToken); } } catch (Exception ex) { Log.Error(ex, "Exception occurred."); } } } async Task devMinerLoopAction( Swarm <NCAction> mainSwarm, Swarm <NCAction> subSwarm, PrivateKey privateKey, CancellationToken cancellationToken) { var miner = new ReorgMiner(mainSwarm, subSwarm, privateKey, reorgInterval); Log.Debug("Miner called."); while (!cancellationToken.IsCancellationRequested) { try { if (mainSwarm.Running) { Log.Debug("Start mining."); await miner.MineBlockAsync(properties.MaximumTransactions, cancellationToken); await Task.Delay(blockInterval, cancellationToken); } else { await Task.Delay(1000, cancellationToken); } } catch (Exception ex) { Log.Error(ex, "Exception occurred."); } } } if (isDev) { NodeService = new DevLibplanetNodeService <NCAction>( Properties, easyPolicy, hardPolicy, stagePolicy, renderers, devMinerLoopAction, preloadProgress, (code, msg) => { ExceptionRenderer.RenderException(code, msg); Log.Error(msg); }, isPreloadStarted => { NodeStatusRenderer.PreloadStatus(isPreloadStarted); }, ignoreBootstrapFailure ); } else { NodeService = new LibplanetNodeService <NCAction>( Properties, blockPolicy, stagePolicy, renderers, minerLoopAction, preloadProgress, (code, msg) => { ExceptionRenderer.RenderException(code, msg); Log.Error(msg); }, isPreloadStarted => { NodeStatusRenderer.PreloadStatus(isPreloadStarted); }, ignoreBootstrapFailure, ignorePreloadFailure ); } strictRenderer.BlockChain = NodeService.BlockChain ?? throw new Exception("BlockChain is null."); if (NodeService.BlockChain?.GetState(AuthorizedMinersState.Address) is Dictionary ams && blockPolicy is BlockPolicy bp) { bp.AuthorizedMinersState = new AuthorizedMinersState(ams); } if (authorizedMiner && blockPolicy is BlockPolicy { AuthorizedMinersState : null })
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 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)); }