public NineChroniclesNodeService( LibplanetNodeServiceProperties <NineChroniclesActionType> properties, RpcNodeServiceProperties?rpcNodeServiceProperties, Progress <PreloadState> preloadProgress = null, bool ignoreBootstrapFailure = false, bool strictRendering = false, bool isDev = false, int blockInterval = 10000, int reorgInterval = 0 ) { Properties = properties; RpcProperties = rpcNodeServiceProperties; try { Libplanet.Crypto.CryptoConfig.CryptoBackend = new Secp256K1CryptoBackend <SHA256>(); Log.Debug("Secp256K1CryptoBackend initialized."); } catch (Exception e) { Log.Error("Secp256K1CryptoBackend initialize failed. Use default backend. {e}", e); } var blockPolicySource = new BlockPolicySource(Log.Logger, LogEventLevel.Debug); // BlockPolicy shared through Lib9c. IBlockPolicy <PolymorphicAction <ActionBase> > blockPolicy = null; // Policies for dev mode. IBlockPolicy <PolymorphicAction <ActionBase> > easyPolicy = null; IBlockPolicy <PolymorphicAction <ActionBase> > hardPolicy = null; if (isDev) { easyPolicy = new ReorgPolicy(new RewardGold(), 1); hardPolicy = new ReorgPolicy(new RewardGold(), 2); } else { blockPolicy = blockPolicySource.GetPolicy(properties.MinimumDifficulty, properties.MaximumTransactions); } BlockRenderer = blockPolicySource.BlockRenderer; ActionRenderer = blockPolicySource.ActionRenderer; ExceptionRenderer = new ExceptionRenderer(); NodeStatusRenderer = new NodeStatusRenderer(); var renderers = new List <IRenderer <NineChroniclesActionType> >(); var strictRenderer = new StrictRenderer(onError: exc => ExceptionRenderer.RenderException( RPCException.InvalidRenderException, exc.Message.Split("\n")[0] ) ); if (Properties.Render) { renderers.Add(blockPolicySource.BlockRenderer); renderers.Add(blockPolicySource.LoggedActionRenderer); } else { renderers.Add(blockPolicySource.LoggedBlockRenderer); } if (strictRendering) { Log.Debug( $"Strict rendering is on. Add {nameof(StrictRenderer)}."); renderers.Add(strictRenderer); } async Task minerLoopAction( BlockChain <NineChroniclesActionType> chain, Swarm <NineChroniclesActionType> swarm, PrivateKey privateKey, CancellationToken cancellationToken) { var miner = new Miner(chain, swarm, privateKey); Log.Debug("Miner called."); while (!cancellationToken.IsCancellationRequested) { try { if (swarm.Running) { Log.Debug("Start mining."); await miner.MineBlockAsync(properties.MaximumTransactions, cancellationToken); } else { await Task.Delay(1000, cancellationToken); } } catch (Exception ex) { Log.Error(ex, "Exception occurred."); } } } async Task devMinerLoopAction( Swarm <NineChroniclesActionType> mainSwarm, Swarm <NineChroniclesActionType> subSwarm, PrivateKey privateKey, CancellationToken cancellationToken) { var miner = new ReorgMiner(mainSwarm, subSwarm, privateKey, reorgInterval); Log.Debug("Miner called."); while (!cancellationToken.IsCancellationRequested) { try { if (mainSwarm.Running) { Log.Debug("Start mining."); await miner.MineBlockAsync(properties.MaximumTransactions, cancellationToken); await Task.Delay(blockInterval, cancellationToken); } else { await Task.Delay(1000, cancellationToken); } } catch (Exception ex) { Log.Error(ex, "Exception occurred."); } } } if (isDev) { NodeService = new DevLibplanetNodeService <NineChroniclesActionType>( Properties, easyPolicy, hardPolicy, renderers, devMinerLoopAction, preloadProgress, (code, msg) => { ExceptionRenderer.RenderException(code, msg); Log.Error(msg); }, isPreloadStarted => { NodeStatusRenderer.PreloadStatus(isPreloadStarted); }, ignoreBootstrapFailure ); } else { NodeService = new LibplanetNodeService <NineChroniclesActionType>( Properties, blockPolicy, renderers, minerLoopAction, preloadProgress, (code, msg) => { ExceptionRenderer.RenderException(code, msg); Log.Error(msg); }, isPreloadStarted => { NodeStatusRenderer.PreloadStatus(isPreloadStarted); }, ignoreBootstrapFailure ); } strictRenderer.BlockChain = NodeService?.BlockChain ?? throw new Exception("BlockChain is null."); if (NodeService?.BlockChain?.GetState(AuthorizedMinersState.Address) is Dictionary ams && blockPolicy is BlockPolicy bp) { bp.AuthorizedMinersState = new AuthorizedMinersState(ams); } }
public NineChroniclesNodeService( PrivateKey?minerPrivateKey, LibplanetNodeServiceProperties <NCAction> properties, 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 NineChroniclesNodeService( PrivateKey?minerPrivateKey, LibplanetNodeServiceProperties <NCAction> properties, IBlockPolicy <NCAction> blockPolicy, NetworkType networkType, Progress <PreloadState>?preloadProgress = null, bool ignoreBootstrapFailure = false, bool ignorePreloadFailure = false, bool strictRendering = false, bool authorizedMiner = false, bool isDev = false, int blockInterval = 10000, int reorgInterval = 0, TimeSpan txLifeTime = default, int minerCount = 1, int txQuotaPerSigner = 10 ) { MinerPrivateKey = minerPrivateKey; Properties = properties; LogEventLevel logLevel = LogEventLevel.Debug; var blockPolicySource = new BlockPolicySource(Log.Logger, logLevel); // Policies for dev mode. IBlockPolicy <NCAction>?easyPolicy = null; IBlockPolicy <NCAction>?hardPolicy = null; IStagePolicy <NCAction> stagePolicy = new StagePolicy(txLifeTime, txQuotaPerSigner); if (isDev) { easyPolicy = new ReorgPolicy(new RewardGold(), 1); hardPolicy = new ReorgPolicy(new RewardGold(), 2); } BlockRenderer = blockPolicySource.BlockRenderer; ActionRenderer = blockPolicySource.ActionRenderer; ExceptionRenderer = new ExceptionRenderer(); NodeStatusRenderer = new NodeStatusRenderer(); var renderers = new List <IRenderer <NCAction> >(); var strictRenderer = new StrictRenderer(onError: exc => ExceptionRenderer.RenderException( RPCException.InvalidRenderException, exc.Message.Split("\n")[0] ) ); if (Properties.Render) { renderers.Add(blockPolicySource.BlockRenderer); renderers.Add(blockPolicySource.LoggedActionRenderer); } else if (Properties.LogActionRenders) { renderers.Add(blockPolicySource.BlockRenderer); // The following "nullRenderer" does nothing. It's just for filling // the LoggedActionRenderer<T>() constructor's parameter: IActionRenderer <NCAction> nullRenderer = new AnonymousActionRenderer <NCAction>(); renderers.Add( new LoggedActionRenderer <NCAction>( nullRenderer, Log.Logger, logLevel ) ); } else { renderers.Add(blockPolicySource.LoggedBlockRenderer); } if (strictRendering) { Log.Debug( $"Strict rendering is on. Add {nameof(StrictRenderer)}."); renderers.Add(strictRenderer); } async Task minerLoopAction( BlockChain <NCAction> chain, Swarm <NCAction> swarm, PrivateKey privateKey, CancellationToken cancellationToken) { var miner = new Miner(chain, swarm, privateKey, authorizedMiner); Log.Debug("Miner called."); while (!cancellationToken.IsCancellationRequested) { try { long nextBlockIndex = chain.Tip.Index + 1; if (swarm.Running) { Log.Debug("Start mining."); if (chain.Policy is BlockPolicy bp) { if (bp.IsAllowedToMine(privateKey.ToAddress(), chain.Count)) { IEnumerable <Task <Block <NCAction> > > miners = Enumerable .Range(0, minerCount) .Select(_ => miner.MineBlockAsync(cancellationToken)); await Task.WhenAll(miners); } else { Log.Debug( "Miner {MinerAddress} is not allowed to mine a block with index {Index} " + "under current policy.", privateKey.ToAddress(), chain.Count); await Task.Delay(1000, cancellationToken); } } else { Log.Error( "No suitable policy was found for chain {ChainId}.", chain.Id); await Task.Delay(1000, cancellationToken); } } else { await Task.Delay(1000, cancellationToken); } } catch (Exception ex) { Log.Error(ex, "Exception occurred."); } } } async Task devMinerLoopAction( Swarm <NCAction> mainSwarm, Swarm <NCAction> subSwarm, PrivateKey privateKey, CancellationToken cancellationToken) { var miner = new ReorgMiner(mainSwarm, subSwarm, privateKey, reorgInterval); Log.Debug("Miner called."); while (!cancellationToken.IsCancellationRequested) { try { if (mainSwarm.Running) { Log.Debug("Start mining."); await miner.MineBlockAsync(cancellationToken); await Task.Delay(blockInterval, cancellationToken); } else { await Task.Delay(1000, cancellationToken); } } catch (Exception ex) { Log.Error(ex, "Exception occurred."); } } } if (isDev) { NodeService = new DevLibplanetNodeService <NCAction>( Properties, easyPolicy, hardPolicy, stagePolicy, renderers, devMinerLoopAction, preloadProgress, (code, msg) => { ExceptionRenderer.RenderException(code, msg); Log.Error(msg); }, isPreloadStarted => { NodeStatusRenderer.PreloadStatus(isPreloadStarted); }, ignoreBootstrapFailure ); } else { NodeService = new LibplanetNodeService <NCAction>( Properties, blockPolicy, stagePolicy, renderers, minerLoopAction, preloadProgress, (code, msg) => { ExceptionRenderer.RenderException(code, msg); Log.Error(msg); }, isPreloadStarted => { NodeStatusRenderer.PreloadStatus(isPreloadStarted); }, ignoreBootstrapFailure, ignorePreloadFailure ); } strictRenderer.BlockChain = NodeService.BlockChain ?? throw new Exception("BlockChain is null."); }