Ejemplo n.º 1
0
        public void Init()
        {
            if (_authorizerInstances != null)
            {
                throw new InvalidOperationException("Already initialized.");
            }

            _authorizers = new Dictionary <BlockTypes, string>();
            _authorizers.Add(BlockTypes.SendTransfer, "SendTransferAuthorizer");
            _authorizers.Add(BlockTypes.LyraTokenGenesis, "GenesisAuthorizer");
            _authorizers.Add(BlockTypes.ReceiveFee, "ReceiveTransferAuthorizer");
            _authorizers.Add(BlockTypes.OpenAccountWithReceiveFee, "NewAccountAuthorizer");
            _authorizers.Add(BlockTypes.OpenAccountWithReceiveTransfer, "NewAccountAuthorizer");
            _authorizers.Add(BlockTypes.OpenAccountWithImport, "NewAccountWithImportAuthorizer");
            _authorizers.Add(BlockTypes.ReceiveTransfer, "ReceiveTransferAuthorizer");
            _authorizers.Add(BlockTypes.ImportAccount, "ImportAccountAuthorizer");
            _authorizers.Add(BlockTypes.TokenGenesis, "NewTokenAuthorizer");
            _authorizers.Add(BlockTypes.Consolidation, "ConsolidationBlockAuthorizer");
            _authorizers.Add(BlockTypes.NullTransaction, "NullTransactionAuthorizer");
            _authorizers.Add(BlockTypes.Service, "ServiceAuthorizer");

            _authorizerInstances = new Dictionary <BlockTypes, IAuthorizer>();
            foreach (var kvp in _authorizers)
            {
                var authorizer = (IAuthorizer)Activator.CreateInstance(Type.GetType("Lyra.Core.Authorizers." + kvp.Value));
                _authorizerInstances.Add(kvp.Key, authorizer);
            }

            Singleton = this;
        }
Ejemplo n.º 2
0
        private async Task <bool> SyncDatabaseAsync(ILyraAPI client)
        {
            var consensusClient = client;

            BlockAPIResult seedSvcGen = null;

            for (int i = 0; i < 10; i++)
            {
                seedSvcGen = await consensusClient.GetServiceGenesisBlockAsync();

                if (seedSvcGen.ResultCode == APIResultCodes.Success)
                {
                    break;
                }

                await Task.Delay(10 * 1000);

                _log.LogInformation("Recreate aggregated client...");
                //await client.InitAsync();
            }


            var localDbState = await GetNodeStatusAsync();

            if (localDbState.totalBlockCount == 0)
            {
                LocalDbSyncState.Remove();
            }
            else
            {
                var oldState = LocalDbSyncState.Load();

                if (oldState.svcGenHash != seedSvcGen.GetBlock().Hash)
                {
                    LocalDbSyncState.Remove();
                }

                //if(oldState.databaseVersion > 0 && oldState.databaseVersion < LyraGlobal.DatabaseVersion)
                //{
                //    // should upgrade database or resync completely
                //    _sys.Storage.Delete(true);
                //    LocalDbSyncState.Remove();
                //    localDbState = await GetNodeStatusAsync();
                //}
            }

            var localState = LocalDbSyncState.Load();

            if (localState.svcGenHash == null)
            {
                localState.svcGenHash      = seedSvcGen.GetBlock().Hash;
                localState.databaseVersion = LyraGlobal.DatabaseVersion;
            }

            var lastCons = (await consensusClient.GetLastConsolidationBlockAsync()).GetBlock() as ConsolidationBlock;

            if (lastCons == null)
            {
                return(false);
            }

            bool IsSuccess    = true;
            var  _authorizers = new AuthorizersFactory();

            while (true)
            {
                try
                {
                    var remoteConsQuery = await consensusClient.GetConsolidationBlocksAsync(_sys.PosWallet.AccountId, null, localState.lastVerifiedConsHeight + 1, 1);

                    if (remoteConsQuery.ResultCode == APIResultCodes.Success)
                    {
                        var remoteConsBlocks = remoteConsQuery.GetBlocks();
                        if (remoteConsBlocks.Any())
                        {
                            foreach (var block in remoteConsBlocks)
                            {
                                var consTarget = block as ConsolidationBlock;
                                _log.LogInformation($"SyncDatabase: Sync consolidation block {consTarget.Height} of total {lastCons.Height}.");
                                if (await SyncAndVerifyConsolidationBlockAsync(consensusClient, consTarget))
                                {
                                    _log.LogInformation($"Consolidation block {consTarget.Height} is OK.");

                                    localState.lastVerifiedConsHeight = consTarget.Height;
                                    LocalDbSyncState.Save(localState);
                                }
                                else
                                {
                                    throw new Exception($"Consolidation block {consTarget.Height} is failure.");
                                }
                            }
                        }
                        else
                        {
                            IsSuccess = true;
                            break;
                        }
                    }
                    else if (remoteConsQuery.ResultCode == APIResultCodes.APIRouteFailed)
                    {
                        _log.LogWarning("Got inconsistant result from network. retry later.");
                        throw new Exception("Failed to sync. reason: " + remoteConsQuery.ResultCode);
                    }
                    else
                    {
                        _log.LogWarning($"Unexpected error {remoteConsQuery.ResultCode}: {remoteConsQuery.ResultMessage}. retry later.");
                        throw new Exception($"Failed to sync. reason: {remoteConsQuery.ResultCode}: {remoteConsQuery.ResultMessage}");
                    }
                }
                catch (Exception ex)
                {
                    _log.LogWarning("SyncDatabase Exception: " + ex.Message);
                    await Task.Delay(30000);

                    IsSuccess = false;
                    break;
                }
            }

            return(IsSuccess);
        }
        public void Init()
        {
            if (_authorizerInstances != null)
            {
                return;
            }
            //throw new InvalidOperationException("Already initialized.");

            _authorizers         = new Dictionary <BlockTypes, Type>();
            _authorizerInstances = new Dictionary <BlockTypes, IAuthorizer>();

            var exporters = typeof(BaseAuthorizer)
                            .Assembly.GetTypes()
                            .Where(t => t.IsSubclassOf(typeof(BaseAuthorizer)) && !t.IsAbstract)
                            .Select(t => new
            {
                b = (IAuthorizer)Activator.CreateInstance(t),
                t
            });

            foreach (var entry in exporters)
            {
                BlockTypes bt;
                try
                {
                    bt = entry.b.GetBlockType();
                    //Console.WriteLine($"{bt}: {entry.t.Name}");
                    if (bt != BlockTypes.Null)
                    {
                        Register(bt, entry.t);
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"Error register authorizer: {entry.t}");
                }
            }

            var depreteds = new[]
            {
                BlockTypes.Null,
                BlockTypes.Sync,
                BlockTypes.OpenAccountWithReceiveFee,
                BlockTypes.OpenAccountWithImport,
                BlockTypes.ReceiveFee,
                BlockTypes.ImportAccount,
                BlockTypes.ReceiveMultipleFee,
                BlockTypes.ReceiveAuthorizerFee,
                BlockTypes.TradeOrder,
                BlockTypes.Trade,
                BlockTypes.ExecuteTradeOrder,
                BlockTypes.CancelTradeOrder,
            };

            // make sure every blocktype has an authrorizer
            foreach (var t in Enum.GetValues(typeof(BlockTypes)))
            {
                if (depreteds.Any(a => a == (BlockTypes)t))
                {
                    continue;
                }

                if (!_authorizers.ContainsKey((BlockTypes)t))
                {
                    Console.WriteLine($"Authorizers Missing {t}");
                }
            }

            /*
             * _authorizers.Add(BlockTypes.SendTransfer, typeof(SendTransferAuthorizer));
             *
             * _authorizers.Add(BlockTypes.ReceiveFee, typeof(ReceiveTransferAuthorizer));
             * //_authorizers.Add(BlockTypes.ReceiveNodeProfit, "ReceiveNodeProfitAuthorizer");
             * _authorizers.Add(BlockTypes.OpenAccountWithReceiveFee, typeof(NewAccountAuthorizer));
             * _authorizers.Add(BlockTypes.OpenAccountWithReceiveTransfer, typeof(NewAccountAuthorizer));
             * //_authorizers.Add(BlockTypes.OpenAccountWithImport, "NewAccountWithImportAuthorizer");
             * _authorizers.Add(BlockTypes.ReceiveTransfer, typeof(ReceiveTransferAuthorizer));
             * //_authorizers.Add(BlockTypes.ImportAccount, "ImportAccountAuthorizer");
             * _authorizers.Add(BlockTypes.Consolidation, typeof(ConsolidationBlockAuthorizer));
             * _authorizers.Add(BlockTypes.Service, typeof(ServiceAuthorizer));
             * _authorizers.Add(BlockTypes.TradeOrder, typeof(TradeOrderAuthorizer));
             * _authorizers.Add(BlockTypes.Trade, typeof(TradeAuthorizer));
             * _authorizers.Add(BlockTypes.CancelTradeOrder, typeof(CancelTradeOrderAuthorizer)); //HACK: wait for code check in
             * _authorizers.Add(BlockTypes.ExecuteTradeOrder, typeof(ExecuteTradeOrderAuthorizer));
             * _authorizers.Add(BlockTypes.PoolFactory, typeof(PoolFactoryAuthorizer));
             *
             * // pool, not needed
             * //_authorizers.Add(BlockTypes.PoolGenesis, "PoolGenesisAuthorizer");
             * //_authorizers.Add(BlockTypes.PoolDeposit, "PoolDepositAuthorizer");
             * //_authorizers.Add(BlockTypes.PoolWithdraw, "PoolWithdrawAuthorizer");
             * //_authorizers.Add(BlockTypes.PoolSwapIn, "PoolSwapInAuthorizer");
             * //_authorizers.Add(BlockTypes.PoolSwapOut, "PoolSwapOutAuthorizer");
             *
             * //_authorizers.Add(BlockTypes.ProfitingGenesis, "ProfitingGenesisAuthorizer");
             * //_authorizers.Add(BlockTypes.Profiting, "ProfitingAuthorizer");
             * //_authorizers.Add(BlockTypes.Benefiting, "BenefitingAuthorizer");
             *
             * //_authorizers.Add(BlockTypes.StakingGenesis, "StakingGenesisAuthorizer");
             * //_authorizers.Add(BlockTypes.Staking, "StakingAuthorizer");
             * //_authorizers.Add(BlockTypes.UnStaking, "UnStakingAuthorizer");
             *
             *
             * _authorizers.Add(BlockTypes.ReceiveAsFee, typeof(ReceiveAsFeeAuthorizer));
             * _authorizers.Add(BlockTypes.LyraTokenGenesis, typeof(LyraGenesisAuthorizer));
             * _authorizers.Add(BlockTypes.TokenGenesis, typeof(TokenGenesisAuthorizer));
             *
             * // DEX
             * //_authorizers.Add(BlockTypes.DexWalletGenesis, "DexWalletGenesisAuthorizer");
             * //_authorizers.Add(BlockTypes.DexTokenMint, "DexTokenMintAuthorizer");
             * //_authorizers.Add(BlockTypes.DexTokenBurn, "DexTokenBurnAuthorizer");
             * //_authorizers.Add(BlockTypes.DexWithdrawToken, "DexWithdrawAuthorizer");
             * //_authorizers.Add(BlockTypes.DexSendToken, "DexSendAuthorizer");
             * //_authorizers.Add(BlockTypes.DexRecvToken, "DexReceiveAuthorizer");
             *
             * // DAO Note: not needed. dynamic work flow did this.
             * //_authorizers.Add(BlockTypes.Orgnization, "DaoAuthorizer");
             * //_authorizers.Add(BlockTypes.OrgnizationGenesis, "DaoGenesisAuthorizer");
             *
             * _authorizerInstances = new Dictionary<BlockTypes, IAuthorizer>();
             * foreach(var kvp in _authorizers)
             * {
             *  var authorizer = (IAuthorizer)Activator.CreateInstance(kvp.Value);
             *  _authorizerInstances.Add(kvp.Key, authorizer);
             * }
             *
             * //_wfAuthorizer = new TransactionAuthorizer(); */

            Singleton = this;
        }
        public ConsensusService(IActorRef localNode)
        {
            _localNode = localNode;
            _log       = new SimpleLogger("ConsensusService").Logger;

            _outOfOrderedMessages = new Dictionary <string, List <SourceSignedMessage> >();
            _activeConsensus      = new Dictionary <string, AuthState>();

            _authorizers = new AuthorizersFactory();
            while (BlockChain.Singleton == null)
            {
                Task.Delay(100).Wait();
            }

            _UIndexSeed = BlockChain.Singleton.GetBlockCount() + 1;
            Mode        = ConsensusWorkingMode.OutofSyncWaiting;

            Receive <Consolidate>((_) =>
            {
                _log.LogInformation("Doing Consolidate");
                OnNodeActive(NodeService.Instance.PosWallet.AccountId);     // update billboard

                if (Mode == ConsensusWorkingMode.Normal)
                {
                    BroadCastBillBoard();
                    GenerateConsolidateBlock();
                }
            });

            Receive <BillBoard>((bb) => {
                _board = bb;
            });

            Receive <AskForBillboard>((_) => Sender.Tell(_board));

            Receive <AuthorizingMsg>(async msg => {
                if (msg.Version != LyraGlobal.ProtocolVersion)
                {
                    Sender.Tell(null);
                }

                OnNodeActive(NodeService.Instance.PosWallet.AccountId);     // update billboard

                // first try auth locally
                var state           = CreateAuthringState(msg);
                var localAuthResult = LocalAuthorizingAsync(msg);
                state.AddAuthResult(localAuthResult);

                if (!localAuthResult.IsSuccess)
                {
                    state.Done.Set();
                    Sender.Tell(state);
                }
                else
                {
                    Send2P2pNetwork(msg);
                    Send2P2pNetwork(localAuthResult);

                    var sender = Context.Sender;

                    await Task.Run(() =>
                    {
                        _ = state.Done.WaitOne();
                    }).ConfigureAwait(false);

                    sender.Tell(state);
                }
            });

            Receive <SignedMessageRelay>(relayMsg =>
            {
                if (relayMsg.signedMessage.Version == LyraGlobal.ProtocolVersion)
                {
                    OnNextConsensusMessage(relayMsg.signedMessage);
                }
                else
                {
                    _log.LogWarning("Protocol Version Mismatch. Do nothing.");
                }
            });

            Receive <BlockChainSynced>(_ =>
            {
                Mode        = ConsensusWorkingMode.Normal;
                _UIndexSeed = BlockChain.Singleton.GetBlockCount() + 1;

                // declare to the network
                var msg = new ChatMsg
                {
                    From    = NodeService.Instance.PosWallet.AccountId,
                    MsgType = ChatMessageType.NodeUp,
                    Text    = "Staking with () Lyra"
                };

                Send2P2pNetwork(msg);
            });

            Task.Run(async() => {
                while (true)
                {
                    StateClean();
                    await Task.Delay(1000).ConfigureAwait(false);
                }
            });
        }