private async Task CheckRequestAsync(ViewChangeRequestMessage req)
        {
            //_log.LogInformation($"CheckRequestAsync from {req.From.Shorten()} for view {req.ViewID} Signature {req.requestSignature.Shorten()}");

            // make sure all request from all voters
            if (!_context.Board.AllVoters.Contains(req.From))
            {
                return;
            }

            if (reqMsgs.Values.Any(a => a.msg.From == req.From))
            {
                reqMsgs.TryRemove(req.From, out _);
            }

            var lastSb = await _sys.Storage.GetLastServiceBlockAsync();

            var lastCons = await _sys.Storage.GetLastConsolidationBlockAsync();

            if (Signatures.VerifyAccountSignature($"{lastSb.Hash}|{lastCons.Hash}", req.From, req.requestSignature))
            {
                if (reqMsgs.TryAdd(req.From, new VCReqWithTime(req)))
                {
                    await CheckAllStatsAsync();
                }
            }
            //else
            //    _log.LogWarning($"ViewChangeRequest signature verification failed from {req.From.Shorten()}");
        }
        /// <summary>
        /// two ways to begin view changing: either one third of all voters requested, or local requested.
        ///
        /// </summary>
        /// <returns></returns>
        internal async Task BeginChangeViewAsync(ViewChangeReason reason)
        {
            _log.LogInformation($"BeginChangeViewAsync: VID: {ViewId} Req: {reqMsgs.Count} Reply: {replyMsgs.Count} Commit: {commitMsgs.Count} Votes {commitMsgs.Count}/{LyraGlobal.GetMajority(_context.Board.AllVoters.Count)}/{_context.Board.AllVoters.Count} Replyed: {replySent} Commited: {commitSent}");

            _reason = reason;
            var lastSb = await _sys.Storage.GetLastServiceBlockAsync();

            if (lastSb == null)
            {
                // genesis?
                _log.LogCritical($"BeginChangeViewAsync has null service block. should not happend. error.");
                return;
            }

            _isViewChanging = true;

            ShiftView(lastSb.Height + 1);
            selectedSuccess = false;

            _log.LogInformation($"View change for ViewId {ViewId} begin at {TimeStarted}");

            CalculateLeaderCandidate();

            var lastCons = await _sys.Storage.GetLastConsolidationBlockAsync();

            var req = new ViewChangeRequestMessage
            {
                From             = _sys.PosWallet.AccountId,
                ViewID           = ViewId,
                prevViewID       = lastSb.Height,
                requestSignature = Signatures.GetSignature(_sys.PosWallet.PrivateKey,
                                                           $"{lastSb.Hash}|{lastCons.Hash}", _sys.PosWallet.AccountId),
            };

            _context.Send2P2pNetwork(req);
            await CheckRequestAsync(req);
        }
 public VCReqWithTime(ViewChangeRequestMessage Message)
 {
     msg = Message;
 }