Ejemplo n.º 1
0
        private void Run()
        {
            try
            {
                const ulong checkInterval          = 1000;
                var         lastCheckedBlockHeight = (ulong)0;
                var         passingCycle           = -1;
                Logger.LogInformation($"Validator status manager started, {_withdrawTriggered}, {_stakeSize}, {_stopRequested}");

                while (!_withdrawTriggered)
                {
                    if (_stopRequested)
                    {
                        break;
                    }
                    if (lastCheckedBlockHeight == _stateManager.LastApprovedSnapshot.Blocks.GetTotalBlockHeight() ||
                        GetCurrentCycle() == passingCycle)
                    {
                        Thread.Sleep(TimeSpan.FromMilliseconds(checkInterval));
                        continue;
                    }

                    lastCheckedBlockHeight = _stateManager.LastApprovedSnapshot.Blocks.GetTotalBlockHeight();
                    Logger.LogInformation($"Check {lastCheckedBlockHeight} height");

                    if (_sendingTxHash != null)
                    {
                        if (_stateManager.LastApprovedSnapshot.Transactions.GetTransactionByHash(_sendingTxHash) ==
                            null)
                        {
                            Logger.LogInformation(
                                $"Transaction {_sendingTxHash.ToHex()} submitted, waiting for including in block");
                            Thread.Sleep(TimeSpan.FromMilliseconds(checkInterval));
                            continue;
                        }

                        _sendingTxHash = null;
                    }

                    var stake = _systemContractReader.GetStake().ToBigInteger();
                    Logger.LogInformation($"Stake size is {stake}");
                    var isStaker = !stake.IsZero;

                    if (!isStaker)
                    {
                        var coverFeesAmount = new BigInteger(10) * BigInteger.Pow(10, 18);
                        Logger.LogInformation($"Trying to become staker");
                        var balance =
                            _stateManager.CurrentSnapshot.Balances.GetBalance(_systemContractReader.NodeAddress());
                        Logger.LogInformation($"Balance is {balance.ToWei()}");
                        if (_stakeSize is null)
                        {
                            Logger.LogInformation("Stake size is null, cannot become staker");
                            continue;
                        }
                        Logger.LogInformation($"Stake size is {_stakeSize}");
                        var isEnoughBalance = balance.ToWei() > _stakeSize.Value + coverFeesAmount;
                        if (isEnoughBalance)
                        {
                            var rolls = _stakeSize.Value / StakingContract.TokenUnitsInRoll;
                            Logger.LogInformation($"Sending transaction to become staker for {rolls} rolls");
                            BecomeStaker(rolls * StakingContract.TokenUnitsInRoll);
                            _stakeSize = null;
                            continue;
                        }

                        Logger.LogInformation($"Not enough balance to become staker");
                        continue;
                    }

                    var requestCycle = _systemContractReader.GetWithdrawRequestCycle();
                    Logger.LogInformation($"Request cycle is {requestCycle}");
                    if (requestCycle != 0)
                    {
                        Logger.LogInformation(
                            $"Stake withdrawal triggered externally in cycle {requestCycle}. Processing withdrawal...");
                        _withdrawTriggered = true;
                        continue;
                    }

                    if (_systemContractReader.IsAttendanceDetectionPhase() &&
                        _systemContractReader.IsPreviousValidator() && !_systemContractReader.IsCheckedIn())
                    {
                        Logger.LogInformation(
                            $"The node is previous validator. Trying to submit attendance detection.");
                        SubmitAttendanceDetection();
                        continue;
                    }

                    if (_systemContractReader.IsNextValidator())
                    {
                        Logger.LogDebug($"The node chosen as next validator. Nothing to do.");
                        passingCycle = GetCurrentCycle();
                        continue;
                    }

                    if (!_systemContractReader.IsAbleToBeValidator() || !_systemContractReader.IsVrfSubmissionPhase())
                    {
                        Logger.LogInformation($"Current submission phase missed. Waiting for the next one.");
                        passingCycle = GetCurrentCycle();
                        continue;
                    }

                    var(isWinner, proof) = GetVrfProof(stake);
                    if (isWinner)
                    {
                        Logger.LogDebug(
                            $"The node won the VRF lottery. Submitting transaction to become the next cycle validator");
                        SubmitVrf(proof);
                        continue;
                    }

                    Logger.LogInformation($"The node didn't win the VRF lottery. Waiting for the next cycle.");
                    passingCycle = GetCurrentCycle();
                }

                lastCheckedBlockHeight = 0;
                passingCycle           = -1;

                // Try to withdraw stake
                while (!_systemContractReader.GetStake().IsZero())
                {
                    if (_stopRequested)
                    {
                        break;
                    }
                    if (_sendingTxHash != null)
                    {
                        if (_stateManager.LastApprovedSnapshot.Transactions.GetTransactionByHash(_sendingTxHash) ==
                            null)
                        {
                            Logger.LogInformation(
                                $"Transaction {_sendingTxHash.ToHex()} submitted, waiting for including in block");
                            Thread.Sleep(TimeSpan.FromMilliseconds(checkInterval));
                            continue;
                        }

                        _sendingTxHash = null;
                    }

                    if (lastCheckedBlockHeight == _stateManager.LastApprovedSnapshot.Blocks.GetTotalBlockHeight() ||
                        GetCurrentCycle() == passingCycle)
                    {
                        Thread.Sleep(TimeSpan.FromMilliseconds(checkInterval));
                        continue;
                    }

                    Logger.LogWarning($"Trying to withdraw stake");

                    lastCheckedBlockHeight = _stateManager.LastApprovedSnapshot.Blocks.GetTotalBlockHeight();

                    if (_systemContractReader.IsAttendanceDetectionPhase() &&
                        _systemContractReader.IsPreviousValidator() && !_systemContractReader.IsCheckedIn())
                    {
                        Logger.LogInformation(
                            $"The node is previous validator. Trying to submit attendance detection.");
                        SubmitAttendanceDetection();
                        continue;
                    }

                    var requestCycle = _systemContractReader.GetWithdrawRequestCycle();
                    if (requestCycle == 0)
                    {
                        if (IsNextValidator())
                        {
                            Logger.LogWarning($"Stake reserved for the next cycle. Waiting for the next cycle.");
                            passingCycle = GetCurrentCycle();
                            continue;
                        }

                        RequestStakeWithdrawal();
                        passingCycle = GetCurrentCycle();
                        Logger.LogWarning($"Submitted withdrawal stake request. Waiting for the next cycle.");
                        continue;
                    }

                    if (GetCurrentCycle() <= requestCycle)
                    {
                        Logger.LogInformation(
                            $"Stake withdrawal request in cycle {requestCycle}, current cycle is {GetCurrentCycle()}. " +
                            $"Waiting for the next cycle to withdraw stake..."
                            );
                        passingCycle = GetCurrentCycle();
                        continue;
                    }

                    if (!IsWithdrawalPhase())
                    {
                        Logger.LogWarning($"Waiting for withdrawal phase...");
                        continue;
                    }

                    WithdrawStakeTx();
                    Logger.LogWarning(
                        $"Stake withdrawal transaction submitted. Waiting for the next block to ensure withdrawal succeeded.");
                }

                _started = false;
                Logger.LogWarning($"Stake withdrawn. Validator status manager stopped.");
            }
            catch (Exception e)
            {
                Logger.LogCritical($"Fatal error in validator status manager, exiting: {e}");
                Environment.Exit(1);
            }
        }
Ejemplo n.º 2
0
        private JObject GetAccount(string?address = null)
        {
            address ??= _systemContractReader.NodeAddress().ToHex();
            var publicKey      = _systemContractReader.NodePublicKey().ToHex();
            var addressUint160 = address.HexToBytes().ToUInt160();
            var balance        =
                _stateManager.LastApprovedSnapshot.Balances.GetBalance(addressUint160);

            var staked             = _systemContractReader.GetStake(addressUint160).ToMoney();
            var staking            = _systemContractReader.GetStakerTotalStake(addressUint160).ToMoney();
            var penalty            = _systemContractReader.GetPenalty(addressUint160).ToMoney();
            var isCurrentValidator = _stateManager.CurrentSnapshot.Validators
                                     .GetValidatorsPublicKeys().Any(pk =>
                                                                    pk.Buffer.ToByteArray().SequenceEqual(_systemContractReader.NodePublicKey()));
            var isNextValidator     = _systemContractReader.IsNextValidator();
            var isPreviousValidator = _systemContractReader.IsPreviousValidator();
            var isAbleToBeValidator = _systemContractReader.IsAbleToBeValidator();
            var isStaker            = !_systemContractReader.GetStake().IsZero();
            var isAbleToBeStaker    = balance.ToWei() > StakingContract.TokenUnitsInRoll;

            var isWalletLocked = _privateWallet.IsLocked();

            var withdrawTriggered = _validatorStatusManager.IsWithdrawTriggered();
            var isValidatorStatusManagerActive = _validatorStatusManager.IsStarted();
            var withdrawRequestCycle           = _systemContractReader.GetWithdrawRequestCycle();

            string state;

            if (isValidatorStatusManagerActive && withdrawTriggered)
            {
                if (isNextValidator)
                {
                    state = "StakeReserved";
                }
                else if (withdrawRequestCycle == 0)
                {
                    state = "SubmittingWithdrawRequest";
                }
                else
                {
                    state = "WaitingForTheNextCycleToWithdraw";
                }
            }
            else if (isCurrentValidator)
            {
                state = "Validator";
            }
            else if (isNextValidator)
            {
                state = "NextValidator";
            }
            else if (isAbleToBeValidator)
            {
                state = "AbleToBeValidator";
            }
            else if (isPreviousValidator)
            {
                state = "PreviousValidator";
            }
            else if (isAbleToBeStaker)
            {
                state = "AbleToBeStaker";
            }
            else
            {
                state = "Newbie";
            }

            return(new JObject
            {
                ["address"] = address,
                ["publicKey"] = publicKey,
                ["balance"] = balance.ToString(),
                ["staked"] = staked.ToString(),
                ["staking"] = staking.ToString(),
                ["penalty"] = penalty.ToString(),
                ["state"] = state,
                ["online"] = isStaker,
                ["isWalletLocked"] = isWalletLocked,
            });
        }
Ejemplo n.º 3
0
        public JObject GetValidatorInfo(string publicKeyStr)
        {
            var publicKey      = publicKeyStr.HexToBytes();
            var addressUint160 = Crypto.ComputeAddress(publicKey).ToUInt160();

            var balance = _stateManager.CurrentSnapshot.Balances.GetBalance(addressUint160);

            var stake   = _systemContractReader.GetStake(addressUint160).ToMoney();
            var penalty = _systemContractReader.GetPenalty(addressUint160).ToMoney();

            var isNextValidator     = _systemContractReader.IsNextValidator(publicKey);
            var isAbleToBeValidator = _systemContractReader.IsAbleToBeValidator(addressUint160);
            var isPreviousValidator = _systemContractReader.IsPreviousValidator(publicKey);
            var isCurrentValidator  = _stateManager.CurrentSnapshot.Validators
                                      .GetValidatorsPublicKeys().Any(pk =>
                                                                     pk.Buffer.ToByteArray().SequenceEqual(publicKey));

            var isAbleToBeStaker = balance.ToWei() > StakingContract.TokenUnitsInRoll;
            var isStaker         = !_systemContractReader.GetStake(addressUint160).IsZero();

            bool stakeDelegated = !isStaker && isCurrentValidator;

            string state;

            if (isCurrentValidator)
            {
                state = "Validator";
            }
            else if (isNextValidator)
            {
                state = "NextValidator";
            }
            else if (isAbleToBeValidator)
            {
                state = "AbleToBeValidator";
            }
            else if (isPreviousValidator)
            {
                state = "PreviousValidator";
            }
            else if (isAbleToBeStaker)
            {
                state = "AbleToBeStaker";
            }
            else
            {
                state = "Newbie";
            }

            return(new JObject
            {
                ["address"] = addressUint160.ToHex(),
                ["publicKey"] = publicKey.ToHex(),
                ["balance"] = balance.ToString(),
                ["stake"] = stake.ToString(),
                ["penalty"] = penalty.ToString(),
                ["state"] = state,
                ["stakeDelegated"] = stakeDelegated.ToString(),
                ["staker"] = isStaker
            });
        }