Beispiel #1
0
        public AuthState CreateAuthringState(AuthorizingMsg msg, bool sourceValid)
        {
            _log.LogInformation($"Consensus: CreateAuthringState Called: BlockIndex: {msg.Block.Height}");

            AuthState state;

            if (msg.Block is ServiceBlock sb)
            {
                _log.LogInformation($"AllVoters: {Board.AllVoters.Count}");
                state = new ServiceBlockAuthState(Worker_OnConsensusSuccessAsync, Board.AllVoters);
                msg.IsServiceBlock = true;
                state.SetView(Board.AllVoters);
            }
            else
            {
                state = new AuthState(Worker_OnConsensusSuccessAsync);
                msg.IsServiceBlock = false;
                state.SetView(Board.PrimaryAuthorizers);
            }
            state.InputMsg = msg;

            state.IsSourceValid = sourceValid;

            return(state);
        }
Beispiel #2
0
        public async Task LeaderSendBlockToConsensusAndForgetAsync(Block block)
        {
            if (block == null)
            {
                throw new ArgumentNullException();
            }

            if (Settings.Default.LyraNode.Lyra.NetworkId == "xtest")
            {
                _ = Task.Run(async() => { await OnNewBlock(block); }).ConfigureAwait(false);
            }
            else
            {
                await Task.Delay(1000);

                AuthorizingMsg msg = new AuthorizingMsg
                {
                    From      = _sys.PosWallet.AccountId,
                    Block     = block,
                    BlockHash = block.Hash,
                    MsgType   = ChatMessageType.AuthorizerPrePrepare
                };

                var state = CreateAuthringState(msg, true);

                await SubmitToConsensusAsync(state);
            }
        }
Beispiel #3
0
        private async Task <(ConsensusResult?, APIResultCodes errorCode)> SendBlockToConsensusAndWaitResultAsync(Block block, List <string> voters = null)        // default is genesus, 4 default
        {
            if (block == null)
            {
                throw new ArgumentNullException();
            }

            AuthorizingMsg msg = new AuthorizingMsg
            {
                From      = _sys.PosWallet.AccountId,
                Block     = block,
                BlockHash = block.Hash,
                MsgType   = ChatMessageType.AuthorizerPrePrepare
            };

            var state = CreateAuthringState(msg, true);

            var sent = await SubmitToConsensusAsync(state);

            if (sent)
            {
                await state.WaitForCloseAsync();

                return(state.CommitConsensus, state.GetMajorErrorCode());
            }
            else
            {
                return(null, APIResultCodes.DoubleSpentDetected);
            }
        }
        private AuthorizedMsg LocalAuthorizingAsync(AuthorizingMsg item)
        {
            var authorizer = _authorizers[item.Block.BlockType];

            var localAuthResult = authorizer.Authorize(item.Block);
            var result          = new AuthorizedMsg
            {
                From      = NodeService.Instance.PosWallet.AccountId,
                MsgType   = ChatMessageType.AuthorizerPrepare,
                BlockHash = item.Block.Hash,
                Result    = localAuthResult.Item1,
                AuthSign  = localAuthResult.Item2
            };

            if (item.Block.BlockType == BlockTypes.Consolidation)
            {
                // do nothing. the UIndex has already take cared of.
            }
            else
            {
                result.BlockUIndex = Mode == ConsensusWorkingMode.Normal ? _UIndexSeed++ : 0;     // if seed out of sync, then others know
            }

            return(result);
        }
Beispiel #5
0
        private async Task <AuthState> PostToConsensusAsync(TransactionBlock block)
        {
            _log.LogInformation($"ApiService: PostToConsensusAsync Called: {block.BlockType}");

            //AuthorizingMsg msg = new AuthorizingMsg
            //{
            //    From = NodeService.Instance.PosWallet.AccountId,
            //    Block = block,
            //    MsgType = ChatMessageType.AuthorizerPrePrepare
            //};

            AuthorizingMsg msg = new AuthorizingMsg
            {
                From    = NodeService.Instance.PosWallet.AccountId,
                Block   = block,
                MsgType = ChatMessageType.AuthorizerPrePrepare
            };

            var state = new AuthState(true);

            state.SetView(await BlockChain.Singleton.GetLastServiceBlockAsync());
            state.InputMsg = msg;

            DagSystem.Singleton.Consensus.Tell(state);

            await state.Done.AsTask();

            state.Done.Close();
            state.Done = null;

            var ts1 = state.T1 == null ? "" : ((int)(DateTime.Now - state.T1).TotalMilliseconds).ToString();
            var ts2 = state.T2 == null ? "" : ((int)(DateTime.Now - state.T2).TotalMilliseconds).ToString();
            var ts3 = state.T3 == null ? "" : ((int)(DateTime.Now - state.T3).TotalMilliseconds).ToString();
            var ts4 = state.T4 == null ? "" : ((int)(DateTime.Now - state.T4).TotalMilliseconds).ToString();
            var ts5 = state.T5 == null ? "" : ((int)(DateTime.Now - state.T5).TotalMilliseconds).ToString();

            _log.LogInformation($"ApiService Timing:\n{ts1}\n{ts2}\n{ts3}\n{ts4}\n{ts5}\n");

            var resultMsg = state.OutputMsgs.Count > 0 ? state.OutputMsgs.First().Result.ToString() : "Unknown";

            _log.LogInformation($"ApiService: PostToConsensusAsync Exited: IsAuthoringSuccess: {state?.CommitConsensus == ConsensusResult.Yay} with {resultMsg}");

            if (state.CommitConsensus == ConsensusResult.Yay)
            {
                return(state);
            }
            else
            {
                return(null);
            }
        }
        private void OnPrePrepare(AuthorizingMsg item)
        {
            _log.LogInformation($"Consensus: OnPrePrepare Called: BlockUIndex: {item.Block.UIndex}");

            var state = CreateAuthringState(item);

            _ = Task.Run(() =>
            {
                var result = LocalAuthorizingAsync(item);

                Send2P2pNetwork(result);
                state.AddAuthResult(result);
                CheckAuthorizedAllOk(state);
                _log.LogInformation($"Consensus: OnPrePrepare LocalAuthorized: {item.Block.UIndex}: {result.IsSuccess}");
            });
        }
        private async Task <AuthState> PostToConsensusAsync(TransactionBlock block)
        {
            _log.LogInformation($"ApiService: PostToConsensusAsync Called: {block.BlockType}");

            AuthorizingMsg msg = new AuthorizingMsg
            {
                From    = NodeService.Instance.PosWallet.AccountId,
                Block   = block,
                MsgType = ChatMessageType.AuthorizerPrePrepare
            };
            var result = await ConsensusSvc.Ask <AuthState>(msg).ConfigureAwait(false);

            var resultMsg = result.OutputMsgs.Count > 0 ? result.OutputMsgs.First().Result.ToString() : "Unknown";

            _log.LogInformation($"ApiService: PostToConsensusAsync Exited: IsAuthoringSuccess: {result?.IsConsensusSuccess == true} with {resultMsg}");
            return(result);
        }
        private AuthState CreateAuthringState(AuthorizingMsg item)
        {
            _log.LogInformation($"Consensus: CreateAuthringState Called: BlockUIndex: {item.Block.UIndex}");

            var ukey = item.Block.Hash;

            if (_activeConsensus.ContainsKey(ukey))
            {
                return(_activeConsensus[ukey]);
            }

            var state = new AuthState
            {
                HashOfFirstBlock = ukey,
                InputMsg         = item,
            };

            // add possible out of ordered messages belong to the block
            if (_outOfOrderedMessages.ContainsKey(item.Block.Hash))
            {
                var msgs = _outOfOrderedMessages[item.Block.Hash];
                _outOfOrderedMessages.Remove(item.Block.Hash);

                foreach (var msg in msgs)
                {
                    switch (msg)
                    {
                    case AuthorizedMsg authorized:
                        state.AddAuthResult(authorized);
                        break;

                    case AuthorizerCommitMsg committed:
                        state.AddCommitedResult(committed);
                        break;
                    }
                }
            }

            _activeConsensus.Add(ukey, state);
            return(state);
        }
        private void GenerateConsolidateBlock()
        {
            var authGenesis = BlockChain.Singleton.GetLastServiceBlock();
            var lastCons    = BlockChain.Singleton.GetSyncBlock();
            var consBlock   = new ConsolidationBlock
            {
                UIndex       = _UIndexSeed++,
                NetworkId    = authGenesis.NetworkId,
                ShardId      = authGenesis.ShardId,
                ServiceHash  = authGenesis.Hash,
                SvcAccountID = NodeService.Instance.PosWallet.AccountId
            };

            // use merkle tree to consolidate all previous blocks, from lastCons.UIndex to consBlock.UIndex -1
            var mt = new MerkleTree();

            for (var ndx = lastCons.UIndex; ndx < consBlock.UIndex; ndx++)      // TODO: handling "losing" block here
            {
                var block = BlockChain.Singleton.GetBlockByUIndex(ndx);
                if (block == null)
                {
                    // block lost
                    _log.LogError($"Block lost for No. {ndx}. Try to resync with other seeds...");

                    // triggering a resync
                    Mode = ConsensusWorkingMode.OutofSyncWaiting;
                    LyraSystem.Singleton.TheBlockchain.Tell(new BlockChain.NeedSync {
                        ToUIndex = ndx
                    });

                    return;
                }
                var mhash = MerkleHash.Create(block.UHash);
                mt.AppendLeaf(mhash);
            }
            consBlock.MerkelTreeHash = mt.BuildTree().ToString();

            consBlock.InitializeBlock(lastCons, NodeService.Instance.PosWallet.PrivateKey,
                                      authGenesis.NetworkId, authGenesis.ShardId,
                                      NodeService.Instance.PosWallet.AccountId);
            //consBlock.UHash = SignableObject.CalculateHash($"{consBlock.UIndex}|{consBlock.Index}|{consBlock.Hash}");
            //consBlock.Authorizations = new List<AuthorizationSignature>();
            //consBlock.Authorizations.Add(new AuthorizationSignature
            //{
            //    Key = NodeService.Instance.PosWallet.AccountId,
            //    Signature = Signatures.GetSignature(NodeService.Instance.PosWallet.PrivateKey, consBlock.Hash + consBlock.ServiceHash, NodeService.Instance.PosWallet.AccountId)
            //});

            //BlockChain.Singleton.AddBlock(consBlock);

            //// broadcast to whole network
            //var msg = new ChatMsg(NodeService.Instance.PosWallet.AccountId, JsonConvert.SerializeObject(consBlock));
            //msg.MsgType = ChatMessageType.BlockConsolidation;
            //Send2P2pNetwork(msg);

            // no, we do consensus
            AuthorizingMsg msg = new AuthorizingMsg
            {
                From    = NodeService.Instance.PosWallet.AccountId,
                Block   = consBlock,
                MsgType = ChatMessageType.AuthorizerPrePrepare
            };

            var state           = CreateAuthringState(msg);
            var localAuthResult = LocalAuthorizingAsync(msg);

            state.AddAuthResult(localAuthResult);

            if (!localAuthResult.IsSuccess)
            {
                _log.LogError("Fatal Error: Consolidate block local authorization failed.");
            }
            else
            {
                Send2P2pNetwork(msg);
                Send2P2pNetwork(localAuthResult);
            }
        }