Beispiel #1
0
        public ExecutionStatus KeyGenCommit(UInt256 cycle, byte[] commitment, byte[][] encryptedRows,
                                            SystemContractExecutionFrame frame)
        {
            Logger.LogDebug(
                $"KeyGenCommit({commitment.ToHex()}, [{string.Join(", ", encryptedRows.Select(r => r.ToHex()))}])");
            if (cycle.ToBigInteger() != GetConsensusGeneration(frame))
            {
                Logger.LogWarning($"Invalid cycle: {cycle}, now is {GetConsensusGeneration(frame)}");
                return(ExecutionStatus.Ok);
            }

            try
            {
                var c = Commitment.FromBytes(commitment);
                if (!c.IsValid())
                {
                    throw new Exception();
                }
                var n = _nextValidators.Get().Length / CryptoUtils.PublicKeyLength;
                if (c.Degree != (n - 1) / 3)
                {
                    throw new Exception();
                }
                if (encryptedRows.Length != n)
                {
                    throw new Exception();
                }
            }
            catch
            {
                Logger.LogError("GovernanceContract is halted in KeyGenCommit");
                return(ExecutionStatus.ExecutionHalted);
            }

            Emit(GovernanceInterface.EventKeygenCommit, commitment, encryptedRows);
            frame.ReturnValue = new byte[] { };
            frame.UseGas(GasMetering.KeygenCommitCost);
            return(ExecutionStatus.Ok);
        }
        public ulong GetLastSuccessfulKeygenBlock()
        {
            var storageVariable = new StorageVariable(
                ContractRegisterer.GovernanceContract,
                _stateManager.LastApprovedSnapshot.Storage,
                new BigInteger(8).ToUInt256()
                );
            var rawValue = storageVariable.Get();

            if (rawValue.Length == 0)
            {
                return(0);
            }
            return((ulong)rawValue.ToUInt256().ToBigInteger());
        }
Beispiel #3
0
        private int?GetPlayersCount()
        {
            var count = _playersCount.Get();

            Logger.LogTrace($"Players count: {count.ToHex()}");
            if (count.Length == 0)
            {
                return(null);
            }
            try
            {
                return(count.AsReadOnlySpan().ToInt32());
            }
            catch (Exception)
            {
                return(null);
            }
        }
Beispiel #4
0
        private PublicKey GetTpkeKey()
        {
            var tpkePublicKey = _tpkeKey.Get();

            return(PublicKey.FromBytes(tpkePublicKey));
        }
Beispiel #5
0
        private Money GetCollectedFees()
        {
            var fees = _collectedFees.Get();

            return(fees.ToUInt256().ToMoney());
        }
Beispiel #6
0
        private PublicKeySet GetTSKeys()
        {
            var tsKeys = _tsKeys.Get();

            return(PublicKeySet.FromBytes(tsKeys));
        }
Beispiel #7
0
        private UInt256 GetBlockReward()
        {
            var reward = _blockReward.Get();

            return(reward.ToUInt256());
        }
Beispiel #8
0
        // Every time a node starts, it first tries to build the genesis block
        public bool TryBuildGenesisBlock()
        {
            // genesis block is built from the config.json file
            // genesis block mints tokens to the validators for the first cycle
            var genesisBlock = _genesisBuilder.Build();

            // if genesis block can already be found, we return immediately
            if (_stateManager.LastApprovedSnapshot.Blocks.GetBlockByHeight(0) != null)
            {
                return(false);
            }
            var snapshot      = _stateManager.NewSnapshot();
            var genesisConfig = _configManager.GetConfig <GenesisConfig>("genesis");

            if (genesisConfig is null)
            {
                return(false);
            }
            genesisConfig.ValidateOrThrow();
            var initialConsensusState = new ConsensusState(
                genesisConfig.ThresholdEncryptionPublicKey.HexToBytes(),
                genesisConfig.Validators.Select(v => new ValidatorCredentials
                                                (
                                                    v.EcdsaPublicKey.HexToBytes().ToPublicKey(),
                                                    v.ThresholdSignaturePublicKey.HexToBytes()
                                                )).ToArray()
                );

            snapshot.Validators.SetConsensusState(initialConsensusState);

            // stake delegation happens even before genesis block
            // stake delegation means - some other address stakes for the validators
            // config.json keeps the stakerAddress and the stakeAmount for each of the validators

            // init system contracts storage
            var dummyStakerPub = new string('f', CryptoUtils.PublicKeyLength * 2).HexToBytes();

            snapshot.Storage.SetRawValue(
                ContractRegisterer.StakingContract,
                new BigInteger(6).ToUInt256().Buffer,
                dummyStakerPub
                );

            // TODO: get rid of explicit numbering of fields
            var initialVrfSeed = Encoding.ASCII.GetBytes("test");

            snapshot.Storage.SetRawValue(
                ContractRegisterer.StakingContract,
                new BigInteger(7).ToUInt256().Buffer,
                initialVrfSeed
                );

            var initialBlockReward = Money.Parse(genesisConfig.BlockReward).ToUInt256().ToBytes();

            snapshot.Storage.SetRawValue(
                ContractRegisterer.GovernanceContract,
                new BigInteger(3).ToUInt256().Buffer,
                initialBlockReward
                );

            var initialBasicGasPrice = Money.Parse(genesisConfig.BasicGasPrice).ToUInt256().ToBytes();

            snapshot.Storage.SetRawValue(
                ContractRegisterer.GovernanceContract,
                new BigInteger(8).ToUInt256().Buffer,
                initialBasicGasPrice
                );

            // The followings are the variables used in stakingContract
            // This variables are stored in the storage snapshot and is a part of the chain
            // To understand the what each variables represent, refer to StakingContract.cs

            // We do the stake delegation even before the execution of genesis block

            var _userToStake = new StorageMapping(
                ContractRegisterer.StakingContract,
                snapshot.Storage,
                new BigInteger(3).ToUInt256()
                );
            var _stakers = new StorageVariable(
                ContractRegisterer.StakingContract,
                snapshot.Storage,
                new BigInteger(6).ToUInt256()
                );
            var _userToPubKey = new StorageMapping(
                ContractRegisterer.StakingContract,
                snapshot.Storage,
                new BigInteger(2).ToUInt256()
                );
            var _pubKeyToStaker = new StorageMapping(
                ContractRegisterer.StakingContract,
                snapshot.Storage,
                new BigInteger(12).ToUInt256()
                );
            var _userToStartCycle = new StorageMapping(
                ContractRegisterer.StakingContract,
                snapshot.Storage,
                new BigInteger(4).ToUInt256()
                );

            foreach (var validator in genesisConfig.Validators)
            {
                if (validator.StakeAmount == null || validator.StakerAddress == null)
                {
                    continue;
                }
                var validatorPublicKey = validator.EcdsaPublicKey.HexToBytes();
                var validatorAddress   = Hepler.PublicKeyToAddress(validatorPublicKey).ToBytes();
                var stakerAddress      = validator.StakerAddress.HexToBytes();

                // add balance to staking contract
                var stakeAmount = Money.Parse(validator.StakeAmount);
                snapshot.Balances.AddBalance(ContractRegisterer.StakingContract, stakeAmount, true);
                // set stake value
                _userToStake.SetValue(validatorAddress, stakeAmount.ToUInt256().ToBytes());
                // update stakers list
                var stakers = _stakers.Get();
                _stakers.Set(stakers.Concat(validatorPublicKey).ToArray());
                // user to public key and public key to staker
                _userToPubKey.SetValue(validatorAddress, validatorPublicKey);
                _pubKeyToStaker.SetValue(validatorPublicKey, stakerAddress);
                // set start cycle
                _userToStartCycle.SetValue(validatorAddress, BitConverter.GetBytes(0));
            }

            _stateManager.Approve();

            // emulate and execute the genesis block
            var(error, removeTransactions, stateHash, relayTransactions) =
                Emulate(genesisBlock.Block, genesisBlock.Transactions);
            if (error != OperatingError.Ok)
            {
                throw new InvalidBlockException(error);
            }
            if (removeTransactions.Count != 0)
            {
                throw new InvalidBlockException(OperatingError.InvalidTransaction);
            }
            if (relayTransactions.Count != 0)
            {
                throw new InvalidBlockException(OperatingError.InvalidTransaction);
            }
            genesisBlock.Block.Header.StateHash = stateHash;
            genesisBlock.Block.Hash             = genesisBlock.Block.Header.Keccak();

            error = Execute(genesisBlock.Block, genesisBlock.Transactions, commit: true, checkStateHash: true);
            if (error != OperatingError.Ok)
            {
                throw new InvalidBlockException(error);
            }
            _stateManager.Commit();
            BlockPersisted(genesisBlock.Block);
            return(true);
        }