/// <summary> /// Prepare the state for the deposit, and create a deposit for the given validator, depositing the given amount. /// </summary> public static Deposit PrepareStateAndDeposit(IServiceProvider testServiceProvider, BeaconState state, ValidatorIndex validatorIndex, Gwei amount, Bytes32 withdrawalCredentials, bool signed) { ChainConstants chainConstants = testServiceProvider.GetService <ChainConstants>(); InitialValues initialValues = testServiceProvider.GetService <IOptions <InitialValues> >().Value; TimeParameters timeParameters = testServiceProvider.GetService <IOptions <TimeParameters> >().Value; BeaconChainUtility beaconChainUtility = testServiceProvider.GetService <BeaconChainUtility>(); BeaconStateAccessor beaconStateAccessor = testServiceProvider.GetService <BeaconStateAccessor>(); byte[][] privateKeys = TestKeys.PrivateKeys(timeParameters).ToArray(); BlsPublicKey[] publicKeys = TestKeys.PublicKeys(timeParameters).ToArray(); byte[] privateKey = privateKeys[(int)(ulong)validatorIndex]; BlsPublicKey publicKey = publicKeys[(int)(ulong)validatorIndex]; if (withdrawalCredentials == Bytes32.Zero) { // insecurely use pubkey as withdrawal key if no credentials provided byte[] withdrawalCredentialBytes = TestSecurity.Hash(publicKey.AsSpan()); withdrawalCredentialBytes[0] = initialValues.BlsWithdrawalPrefix; withdrawalCredentials = new Bytes32(withdrawalCredentialBytes); } List <DepositData> depositDataList = new List <DepositData>(); (Deposit deposit, Root depositRoot) = BuildDeposit(testServiceProvider, state, depositDataList, publicKey, privateKey, amount, withdrawalCredentials, signed); state.SetEth1DepositIndex(0); state.Eth1Data.SetDepositRoot(depositRoot); state.Eth1Data.SetDepositCount((ulong)depositDataList.Count); return(deposit); }
public bool BlsVerify(BlsPublicKey publicKey, Hash32 messageHash, BlsSignature signature, Domain domain) { var blsParameters = new BLSParameters() { PublicKey = publicKey.AsSpan().ToArray() }; using var signatureAlgorithm = SignatureAlgorithmFactory(blsParameters); return(signatureAlgorithm.VerifyHash(messageHash.AsSpan(), signature.AsSpan(), domain.AsSpan())); }
public bool BlsVerify(BlsPublicKey publicKey, Root signingRoot, BlsSignature signature) { BLSParameters blsParameters = new BLSParameters() { PublicKey = publicKey.AsSpan().ToArray() }; using BLS signatureAlgorithm = SignatureAlgorithmFactory(blsParameters); return(signatureAlgorithm.VerifyHash(signingRoot.AsSpan(), signature.AsSpan())); }
private DepositData BuildAndSignDepositData(ulong validatorIndex, Gwei amount, SignatureDomains signatureDomains) { InitialValues initialValues = _initialValueOptions.CurrentValue; 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 Bytes32 withdrawalCredentials = _crypto.Hash(publicKey.AsSpan()); withdrawalCredentials.Unwrap()[0] = initialValues.BlsWithdrawalPrefix; // Build deposit data DepositData depositData = new DepositData(publicKey, withdrawalCredentials, amount, BlsSignature.Zero); // Sign deposit data Domain domain = _beaconChainUtility.ComputeDomain(signatureDomains.Deposit); DepositMessage depositMessage = new DepositMessage( depositData.PublicKey, depositData.WithdrawalCredentials, depositData.Amount); Root depositMessageRoot = _crypto.HashTreeRoot(depositMessage); Root depositDataSigningRoot = _beaconChainUtility.ComputeSigningRoot(depositMessageRoot, domain); byte[] signatureBytes = new byte[96]; bls.TrySignData(depositDataSigningRoot.AsSpan(), signatureBytes, out int bytesWritten); BlsSignature depositDataSignature = new BlsSignature(signatureBytes); depositData.SetSignature(depositDataSignature); if (_logger.IsEnabled(LogLevel.Debug)) { LogDebug.QuickStartAddValidator(_logger, validatorIndex, publicKey.ToString().Substring(0, 12), null); } return(depositData); }
public static (IList <Deposit>, Root) PrepareGenesisDeposits(IServiceProvider testServiceProvider, int genesisValidatorCount, Gwei amount, bool signed) { ChainConstants chainConstants = testServiceProvider.GetService <ChainConstants>(); MiscellaneousParameters miscellaneousParameters = testServiceProvider.GetService <IOptions <MiscellaneousParameters> >().Value; InitialValues initialValues = testServiceProvider.GetService <IOptions <InitialValues> >().Value; TimeParameters timeParameters = testServiceProvider.GetService <IOptions <TimeParameters> >().Value; MaxOperationsPerBlock maxOperationsPerBlock = testServiceProvider.GetService <IOptions <MaxOperationsPerBlock> >().Value; BeaconChainUtility beaconChainUtility = testServiceProvider.GetService <BeaconChainUtility>(); BeaconStateAccessor beaconStateAccessor = testServiceProvider.GetService <BeaconStateAccessor>(); BeaconStateTransition beaconStateTransition = testServiceProvider.GetService <BeaconStateTransition>(); byte[][] privateKeys = TestKeys.PrivateKeys(timeParameters).ToArray(); BlsPublicKey[] publicKeys; if (signed) { publicKeys = TestKeys.PublicKeys(timeParameters).ToArray(); } else { publicKeys = privateKeys.Select(x => new BlsPublicKey(x)).ToArray(); } List <DepositData> depositDataList = new List <DepositData>(); List <Deposit> genesisDeposits = new List <Deposit>(); Root root = Root.Zero; for (int validatorIndex = 0; validatorIndex < genesisValidatorCount; validatorIndex++) { BlsPublicKey publicKey = publicKeys[validatorIndex]; byte[] privateKey = privateKeys[validatorIndex]; // insecurely use pubkey as withdrawal key if no credentials provided byte[] withdrawalCredentialBytes = TestSecurity.Hash(publicKey.AsSpan()); withdrawalCredentialBytes[0] = initialValues.BlsWithdrawalPrefix; Bytes32 withdrawalCredentials = new Bytes32(withdrawalCredentialBytes); (Deposit deposit, Root depositRoot) = BuildDeposit(testServiceProvider, null, depositDataList, publicKey, privateKey, amount, withdrawalCredentials, signed); root = depositRoot; genesisDeposits.Add(deposit); } return(genesisDeposits, root); }
public bool BlsVerify(BlsPublicKey publicKey, Root signingRoot, BlsSignature signature) { return(_bls.VerifyData(publicKey.AsSpan(), signingRoot.AsSpan(), signature.AsSpan())); }
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); }
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); } }
public static SszElement ToSszBasicVector(this BlsPublicKey item) { return(new SszBasicVector(item.AsSpan())); }
public Task <Eth1GenesisData> GetEth1GenesisDataAsync(CancellationToken cancellationToken) { QuickStartParameters quickStartParameters = _quickStartParameterOptions.CurrentValue; if (_logger.IsWarn()) { Log.MockedQuickStart(_logger, quickStartParameters.GenesisTime, quickStartParameters.ValidatorCount, null); } GweiValues gweiValues = _gweiValueOptions.CurrentValue; InitialValues initialValues = _initialValueOptions.CurrentValue; TimeParameters timeParameters = _timeParameterOptions.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; Bytes32 withdrawalCredentials = new Bytes32(withdrawalCredentialBytes); // Build deposit data DepositData depositData = new DepositData(publicKey, withdrawalCredentials, amount, BlsSignature.Zero); // Sign deposit data Domain domain = _beaconChainUtility.ComputeDomain(signatureDomains.Deposit); DepositMessage depositMessage = new DepositMessage(depositData.PublicKey, depositData.WithdrawalCredentials, depositData.Amount); Root depositMessageRoot = _cryptographyService.HashTreeRoot(depositMessage); Root depositDataSigningRoot = _beaconChainUtility.ComputeSigningRoot(depositMessageRoot, domain); byte[] destination = new byte[96]; bls.TrySignData(depositDataSigningRoot.AsSpan(), destination, out int bytesWritten); 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; Root root = _cryptographyService.HashTreeRoot(depositDataList); IEnumerable <Bytes32> allLeaves = depositDataList.Select(x => new Bytes32(_cryptographyService.HashTreeRoot((DepositData)x).AsSpan())); IList <IList <Bytes32> > tree = CalculateMerkleTreeFromLeaves(allLeaves); IList <Bytes32> merkleProof = GetMerkleProof(tree, index, 32); List <Bytes32> proof = new List <Bytes32>(merkleProof); byte[] indexBytes = new byte[32]; BinaryPrimitives.WriteInt32LittleEndian(indexBytes, index + 1); Bytes32 indexHash = new Bytes32(indexBytes); proof.Add(indexHash); Bytes32 leaf = new Bytes32(_cryptographyService.HashTreeRoot(depositData).AsSpan()); _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); } ulong eth1Timestamp = quickStartParameters.Eth1Timestamp; if (eth1Timestamp == 0) { eth1Timestamp = quickStartParameters.GenesisTime - (ulong)(1.5 * timeParameters.MinimumGenesisDelay); } else { ulong minimumEth1TimestampInclusive = quickStartParameters.GenesisTime - 2 * timeParameters.MinimumGenesisDelay; ulong maximumEth1TimestampInclusive = quickStartParameters.GenesisTime - timeParameters.MinimumGenesisDelay - 1; if (eth1Timestamp < minimumEth1TimestampInclusive) { if (_logger.IsEnabled(LogLevel.Warning)) { Log.QuickStartEth1TimestampTooLow(_logger, eth1Timestamp, quickStartParameters.GenesisTime, minimumEth1TimestampInclusive, null); } eth1Timestamp = minimumEth1TimestampInclusive; } else if (eth1Timestamp > maximumEth1TimestampInclusive) { if (_logger.IsEnabled(LogLevel.Warning)) { Log.QuickStartEth1TimestampTooHigh(_logger, eth1Timestamp, quickStartParameters.GenesisTime, maximumEth1TimestampInclusive, null); } eth1Timestamp = maximumEth1TimestampInclusive; } } var eth1GenesisData = new Eth1GenesisData(quickStartParameters.Eth1BlockHash, eth1Timestamp, deposits); if (_logger.IsEnabled(LogLevel.Debug)) { LogDebug.QuickStartGenesisDataCreated(_logger, eth1GenesisData.BlockHash, eth1GenesisData.Timestamp, eth1GenesisData.Deposits.Count, null); } return(Task.FromResult(eth1GenesisData)); }