Пример #1
0
        public void QuickStartGenesis()
        {
            var quickStartParameters = _quickStartParameterOptions.CurrentValue;

            _logger.LogWarning(0, "Mocked quick start with genesis time {GenesisTime} and {ValidatorCount} validators.",
                               quickStartParameters.GenesisTime, quickStartParameters.ValidatorCount);

            var miscellaneousParameters = _miscellaneousParameterOptions.CurrentValue;
            var gweiValues            = _gweiValueOptions.CurrentValue;
            var initialValues         = _initialValueOptions.CurrentValue;
            var timeParameters        = _timeParameterOptions.CurrentValue;
            var stateListLengths      = _stateListLengthOptions.CurrentValue;
            var maxOperationsPerBlock = _maxOperationsPerBlockOptions.CurrentValue;
            var signatureDomains      = _signatureDomainOptions.CurrentValue;

            // Fixed amount
            var amount = gweiValues.MaximumEffectiveBalance;

            // Build deposits
            var depositDataList = new List <DepositData>();
            var deposits        = new List <Deposit>();

            for (var validatorIndex = 0uL; validatorIndex < quickStartParameters.ValidatorCount; validatorIndex++)
            {
                var privateKey = GeneratePrivateKey(validatorIndex);

                // Public Key
                var blsParameters = new BLSParameters()
                {
                    PrivateKey = privateKey
                };
                using var bls = BLS.Create(blsParameters);
                var publicKeyBytes = new Span <byte>(new byte[BlsPublicKey.Length]);
                bls.TryExportBLSPublicKey(publicKeyBytes, out var publicKeybytesWritten);
                var publicKey = new BlsPublicKey(publicKeyBytes);

                // Withdrawal Credentials
                var withdrawalCredentialBytes = _cryptographyService.Hash(publicKey.AsSpan()).AsSpan().ToArray();
                withdrawalCredentialBytes[0] = initialValues.BlsWithdrawalPrefix;
                var withdrawalCredentials = new Hash32(withdrawalCredentialBytes);

                // Build deposit data
                var depositData = new DepositData(publicKey, withdrawalCredentials, amount);

                // Sign deposit data
                var depositDataSigningRoot = depositData.SigningRoot();
                var domain      = _beaconChainUtility.ComputeDomain(signatureDomains.Deposit);
                var destination = new Span <byte>(new byte[96]);
                bls.TrySignHash(depositDataSigningRoot.AsSpan(), destination, out var bytesWritten, domain.AsSpan());
                var depositDataSignature = new BlsSignature(destination);
                depositData.SetSignature(depositDataSignature);

                // Deposit

                // TODO: This seems a very inefficient way (copied from tests) as it recalculates the merkle tree each time
                // (you only need to add one node)

                // TODO: Add some tests around quick start, then improve

                var index = depositDataList.Count;
                depositDataList.Add(depositData);
                var root        = depositDataList.HashTreeRoot((ulong)1 << _chainConstants.DepositContractTreeDepth);
                var allLeaves   = depositDataList.Select(x => x.HashTreeRoot());
                var tree        = CalculateMerkleTreeFromLeaves(allLeaves);
                var merkleProof = GetMerkleProof(tree, index, 32);
                var proof       = new List <Hash32>(merkleProof);
                var indexBytes  = new Span <byte>(new byte[32]);
                BitConverter.TryWriteBytes(indexBytes, (ulong)index + 1);
                if (!BitConverter.IsLittleEndian)
                {
                    indexBytes.Slice(0, 8).Reverse();
                }
                var indexHash = new Hash32(indexBytes);
                proof.Add(indexHash);
                var leaf = depositData.HashTreeRoot();
                _beaconChainUtility.IsValidMerkleBranch(leaf, proof, _chainConstants.DepositContractTreeDepth + 1, (ulong)index, root);
                var deposit = new Deposit(proof, depositData);

                _logger.LogDebug("Quick start adding deposit for mocked validator {ValidatorIndex} with public key {PublicKey}.",
                                 validatorIndex, publicKey);

                deposits.Add(deposit);
            }

            var genesisState = _beaconChain.InitializeBeaconStateFromEth1(quickStartParameters.Eth1BlockHash, quickStartParameters.Eth1Timestamp, deposits);

            // We use the state directly, and don't test IsValid
            genesisState.SetGenesisTime(quickStartParameters.GenesisTime);
            var store = _forkChoice.GetGenesisStore(genesisState);

            _logger.LogDebug("Quick start genesis store created with genesis time {GenesisTime}.", store.GenesisTime);
        }
Пример #2
0
        public void QuickStartGenesis()
        {
            QuickStartParameters quickStartParameters = _quickStartParameterOptions.CurrentValue;

            if (_logger.IsWarn())
            {
                Log.MockedQuickStart(_logger, quickStartParameters.GenesisTime, quickStartParameters.ValidatorCount, null);
            }

            GweiValues       gweiValues       = _gweiValueOptions.CurrentValue;
            InitialValues    initialValues    = _initialValueOptions.CurrentValue;
            SignatureDomains signatureDomains = _signatureDomainOptions.CurrentValue;

            // Fixed amount
            Gwei amount = gweiValues.MaximumEffectiveBalance;

            // Build deposits
            List <DepositData> depositDataList = new List <DepositData>();
            List <Deposit>     deposits        = new List <Deposit>();

            for (ulong validatorIndex = 0uL; validatorIndex < quickStartParameters.ValidatorCount; validatorIndex++)
            {
                byte[] privateKey = GeneratePrivateKey(validatorIndex);

                // Public Key
                BLSParameters blsParameters = new BLSParameters()
                {
                    PrivateKey = privateKey
                };
                using BLS bls = BLS.Create(blsParameters);
                byte[] publicKeyBytes = new byte[BlsPublicKey.Length];
                bls.TryExportBLSPublicKey(publicKeyBytes, out int publicKeyBytesWritten);
                BlsPublicKey publicKey = new BlsPublicKey(publicKeyBytes);

                // Withdrawal Credentials
                byte[] withdrawalCredentialBytes = _cryptographyService.Hash(publicKey.AsSpan()).AsSpan().ToArray();
                withdrawalCredentialBytes[0] = initialValues.BlsWithdrawalPrefix;
                Hash32 withdrawalCredentials = new Hash32(withdrawalCredentialBytes);

                // Build deposit data
                DepositData depositData = new DepositData(publicKey, withdrawalCredentials, amount);

                // Sign deposit data
                Hash32 depositDataSigningRoot = _cryptographyService.SigningRoot(depositData);
                Domain domain      = _beaconChainUtility.ComputeDomain(signatureDomains.Deposit);
                byte[] destination = new byte[96];
                bls.TrySignHash(depositDataSigningRoot.AsSpan(), destination, out int bytesWritten, domain.AsSpan());
                BlsSignature depositDataSignature = new BlsSignature(destination);
                depositData.SetSignature(depositDataSignature);

                // Deposit

                // TODO: This seems a very inefficient way (copied from tests) as it recalculates the merkle tree each time
                // (you only need to add one node)

                // TODO: Add some tests around quick start, then improve

                int index = depositDataList.Count;
                depositDataList.Add(depositData);
                //int depositDataLength = (ulong) 1 << _chainConstants.DepositContractTreeDepth;
                Hash32 root = _cryptographyService.HashTreeRoot(depositDataList);
                IEnumerable <Hash32>    allLeaves = depositDataList.Select(x => _cryptographyService.HashTreeRoot(x));
                IList <IList <Hash32> > tree      = CalculateMerkleTreeFromLeaves(allLeaves);


                IList <Hash32> merkleProof = GetMerkleProof(tree, index, 32);
                List <Hash32>  proof       = new List <Hash32>(merkleProof);
                Span <byte>    indexBytes  = new Span <byte>(new byte[32]);
                BitConverter.TryWriteBytes(indexBytes, (ulong)index + 1);
                if (!BitConverter.IsLittleEndian)
                {
                    indexBytes.Slice(0, 8).Reverse();
                }

                Hash32 indexHash = new Hash32(indexBytes);
                proof.Add(indexHash);
                Hash32 leaf = _cryptographyService.HashTreeRoot(depositData);
                _beaconChainUtility.IsValidMerkleBranch(leaf, proof, _chainConstants.DepositContractTreeDepth + 1, (ulong)index, root);
                Deposit deposit = new Deposit(proof, depositData);

                if (_logger.IsEnabled(LogLevel.Debug))
                {
                    LogDebug.QuickStartAddValidator(_logger, validatorIndex, publicKey.ToString().Substring(0, 12),
                                                    null);
                }

                deposits.Add(deposit);
            }

            BeaconState genesisState = _beaconChain.InitializeBeaconStateFromEth1(quickStartParameters.Eth1BlockHash, quickStartParameters.Eth1Timestamp, deposits);

            // We use the state directly, and don't test IsValid
            genesisState.SetGenesisTime(quickStartParameters.GenesisTime);
            IStore store = _forkChoice.GetGenesisStore(genesisState);

            if (_logger.IsEnabled(LogLevel.Debug))
            {
                LogDebug.QuickStartStoreCreated(_logger, store.GenesisTime, null);
            }
        }