public BlsSignature SignHashWithDomain(BlsPublicKey blsPublicKey, Hash32 hash, Domain domain) { if (_publicKeyToBls.Count == 0) { var keyCount = GetPublicKeys().Count(); } BLS bls = _publicKeyToBls[blsPublicKey]; Span <byte> destination = stackalloc byte[BlsSignature.Length]; bool success = bls.TrySignHash(hash.AsSpan(), destination, out int bytesWritten, domain.AsSpan()); if (!success || bytesWritten != BlsSignature.Length) { throw new Exception($"Failure signing hash {hash}, domain {domain} for public key {blsPublicKey}."); } BlsSignature blsSignature = new BlsSignature(destination.ToArray()); return(blsSignature); }
private BlsSignature GetEpochSignature(IServiceProvider testServiceProvider, byte[] privateKey, ForkVersion forkVersion, Slot slot) { SignatureDomains signatureDomains = testServiceProvider.GetService <IOptions <SignatureDomains> >().Value; BeaconChainUtility beaconChainUtility = testServiceProvider.GetService <BeaconChainUtility>(); var domain = beaconChainUtility.ComputeDomain(signatureDomains.Randao, forkVersion); var epoch = beaconChainUtility.ComputeEpochAtSlot(slot); var epochRoot = epoch.HashTreeRoot(); BLSParameters parameters = new BLSParameters() { PrivateKey = privateKey }; BLS bls = BLS.Create(parameters); var destination = new Span <byte>(new byte[96]); bls.TrySignHash(epochRoot.AsSpan(), destination, out var bytesWritten, domain.AsSpan()); var signature = new BlsSignature(destination.ToArray()); return(signature); }
public void QuickStartGenesis() { QuickStartParameters quickStartParameters = _quickStartParameterOptions.CurrentValue; _logger.LogWarning(0, "Mocked quick start with genesis time {GenesisTime:n0} and {ValidatorCount} validators.", quickStartParameters.GenesisTime, quickStartParameters.ValidatorCount); GweiValues gweiValues = _gweiValueOptions.CurrentValue; InitialValues initialValues = _initialValueOptions.CurrentValue; SignatureDomains signatureDomains = _signatureDomainOptions.CurrentValue; // Fixed amount Gwei amount = gweiValues.MaximumEffectiveBalance; // Build deposits var depositDataList = new List <DepositData>(); var deposits = new List <Deposit>(); for (ulong validatorIndex = 0uL; validatorIndex < quickStartParameters.ValidatorCount; validatorIndex++) { var privateKey = GeneratePrivateKey(validatorIndex); // Public Key BLSParameters blsParameters = new BLSParameters() { PrivateKey = privateKey }; using BLS bls = BLS.Create(blsParameters); var publicKeyBytes = new byte[BlsPublicKey.Length]; bls.TryExportBLSPublicKey(publicKeyBytes, out int publicKeyBytesWritten); BlsPublicKey publicKey = new BlsPublicKey(publicKeyBytes); // Withdrawal Credentials var 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 = depositData.SigningRoot(); Domain domain = _beaconChainUtility.ComputeDomain(signatureDomains.Deposit); var 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); Hash32 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(); } Hash32 indexHash = new Hash32(indexBytes); proof.Add(indexHash); Hash32 leaf = depositData.HashTreeRoot(); _beaconChainUtility.IsValidMerkleBranch(leaf, proof, _chainConstants.DepositContractTreeDepth + 1, (ulong)index, root); Deposit deposit = new Deposit(proof, depositData); if (_logger.IsEnabled(LogLevel.Debug)) { _logger.LogDebug("Quick start adding deposit for mocked validator {ValidatorIndex} with public key {PublicKey}.", validatorIndex, publicKey.ToString().Substring(0, 12)); } 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); _logger.LogDebug("Quick start genesis store created with genesis time {GenesisTime:n0}.", store.GenesisTime); }