public void AddValidator(Address from)
        {
            Runtime.Expect(IsWitness(from), "witness failed");

            var count = _validatorList.Count();
            var max   = GetMaxValidators();

            Runtime.Expect(count < max, "no open validators spots");

            var requiredStake = GetRequiredStake();
            var stakedAmount  = (BigInteger)Runtime.CallContext("energy", "GetStake", from);

            Runtime.Expect(stakedAmount >= requiredStake, "not enough stake");

            _validatorList.Add(from);

            var entry = new ValidatorEntry()
            {
                address      = from,
                joinDate     = Runtime.Time,
                lastActivity = Runtime.Time,
                slashes      = 0
            };

            _validatorMap.Set(from, entry);

            Runtime.Notify(EventKind.ValidatorAdd, Runtime.Chain.Address, from);
        }
Exemple #2
0
        public void AddValidator(Address from)
        {
            Runtime.Expect(from.IsUser, "must be user address");
            Runtime.Expect(IsWitness(from), "witness failed");

            var count = _validatorList.Count();

            if (count > 0)
            {
                var max = Runtime.GetGovernanceValue(ActiveValidatorCountTag);
                Runtime.Expect(count < max, "no open validators spots");

                var pollName     = ConsensusContract.SystemPoll + ValidatorPollTag;
                var hasConsensus = (bool)Runtime.CallContext("consensus", "HasRank", pollName, from, max);
                Runtime.Expect(hasConsensus, "no consensus for electing this address");
            }

            var requiredStake = EnergyContract.MasterAccountThreshold;
            var stakedAmount  = (BigInteger)Runtime.CallContext("energy", "GetStake", from);

            Runtime.Expect(stakedAmount >= requiredStake, "not enough stake");

            _validatorList.Add(from);

            var entry = new ValidatorEntry()
            {
                address  = from,
                election = Runtime.Time,
            };

            _validatorMap.Set(from, entry);

            Runtime.Notify(EventKind.ValidatorAdd, Runtime.Chain.Address, from);
        }
        public ValidatorEntry[] GetValidators()
        {
            var totalValidators = (int)Runtime.GetGovernanceValue(ValidatorCountTag);
            var result          = new ValidatorEntry[totalValidators];

            for (int i = 0; i < totalValidators; i++)
            {
                result[i] = GetValidatorByIndex(i);
            }
            return(result);
        }
        // NOTE - witness not required, as anyone should be able to call this, permission is granted based on consensus
        public void SetValidator(Address from, BigInteger index, ValidatorType type)
        {
            Runtime.Expect(from.IsUser, "must be user address");
            Runtime.Expect(type != ValidatorType.Invalid, "invalid validator type");

            var primaryValidators   = GetValidatorCount(ValidatorType.Primary);
            var secondaryValidators = GetValidatorCount(ValidatorType.Secondary);

            Runtime.Expect(index >= 0, "invalid index");

            var totalValidators = GetMaxTotalValidators();

            Runtime.Expect(index < totalValidators, "invalid index");

            if (primaryValidators > 1)
            {
                var pollName     = ConsensusContract.SystemPoll + ValidatorPollTag;
                var obtainedRank = Runtime.CallContext("consensus", "GetRank", pollName, from).AsNumber();
                Runtime.Expect(obtainedRank >= 0, "no consensus for electing this address");
                Runtime.Expect(obtainedRank == index, "this address was elected at a different index");
            }
            else
            if (primaryValidators == 1)
            {
                var firstValidator = GetValidatorByIndex(0).address;
                Runtime.Expect(IsWitness(firstValidator), "invalid witness");
            }
            else
            if (primaryValidators == 0)
            {
                Runtime.Expect(IsWitness(Runtime.Nexus.GenesisAddress), "invalid witness");
            }

            var expectedType = index < GetMaxPrimaryValidators() ? ValidatorType.Primary : ValidatorType.Secondary;

            Runtime.Expect(type == expectedType, "unexpected validator type");

            var requiredStake = Runtime.CallContext(Nexus.StakeContractName, "GetMasterThreshold", from).AsNumber();
            var stakedAmount  = Runtime.CallContext(Nexus.StakeContractName, "GetStake", from).AsNumber();

            Runtime.Expect(stakedAmount >= requiredStake, "not enough stake");

            if (index > 0)
            {
                var isPreviousSet = _validators.ContainsKey <BigInteger>(index - 1);
                Runtime.Expect(isPreviousSet, "previous validator slot is not set");
            }

            var entry = new ValidatorEntry()
            {
                address  = from,
                election = Runtime.Time,
                type     = type,
            };

            _validators.Set <BigInteger, ValidatorEntry>(index, entry);

            if (type == ValidatorType.Primary)
            {
                var newValidators = GetValidatorCount(ValidatorType.Primary);
                Runtime.Expect(newValidators > primaryValidators, "number of primary validators did not change");
            }
            else
            if (type == ValidatorType.Secondary)
            {
                var newValidators = GetValidatorCount(ValidatorType.Secondary);
                Runtime.Expect(newValidators > secondaryValidators, "number of secondary validators did not change");
            }

            Runtime.Notify(EventKind.ValidatorAdd, Runtime.Chain.Address, from);
        }