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 #2
0
 public GovernanceContract(InvocationContext context)
 {
     Logger.LogDebug("ctor");
     _context        = context ?? throw new ArgumentNullException(nameof(context));
     _nextValidators = new StorageVariable(
         ContractRegisterer.GovernanceContract,
         context.Snapshot.Storage,
         BigInteger.One.ToUInt256()
         );
     _confirmations = new StorageMapping(
         ContractRegisterer.GovernanceContract,
         context.Snapshot.Storage,
         new BigInteger(2).ToUInt256()
         );
     _blockReward = new StorageVariable(
         ContractRegisterer.GovernanceContract,
         context.Snapshot.Storage,
         new BigInteger(3).ToUInt256()
         );
     _playersCount = new StorageVariable(
         ContractRegisterer.GovernanceContract,
         context.Snapshot.Storage,
         new BigInteger(4).ToUInt256()
         );
     _tsKeys = new StorageVariable(
         ContractRegisterer.GovernanceContract,
         context.Snapshot.Storage,
         new BigInteger(5).ToUInt256()
         );
     _tpkeKey = new StorageVariable(
         ContractRegisterer.GovernanceContract,
         context.Snapshot.Storage,
         new BigInteger(6).ToUInt256()
         );
     _collectedFees = new StorageVariable(
         ContractRegisterer.GovernanceContract,
         context.Snapshot.Storage,
         new BigInteger(7).ToUInt256()
         );
     _lastSuccessfulKeygenBlock = new StorageVariable(
         ContractRegisterer.GovernanceContract,
         context.Snapshot.Storage,
         new BigInteger(8).ToUInt256()
         );
 }
Beispiel #3
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);
        }