public IList <BlsPublicKey> GetPublicKeys() { if (_publicKeyToBls.Count == 0) { QuickStartParameters _quickStartParameters = _quickStartParameterOptions.CurrentValue; ulong endIndex = _quickStartParameters.ValidatorStartIndex + _quickStartParameters.NumberOfValidators; for (ulong validatorIndex = _quickStartParameters.ValidatorStartIndex; validatorIndex < endIndex; validatorIndex++) { byte[] privateKey = GeneratePrivateKey(validatorIndex); BLSParameters blsParameters = new BLSParameters() { PrivateKey = privateKey }; BLS bls = BLS.Create(blsParameters); byte[] publicKeyBytes = new byte[BlsPublicKey.Length]; bls.TryExportBlsPublicKey(publicKeyBytes, out int publicKeyBytesWritten); BlsPublicKey publicKey = new BlsPublicKey(publicKeyBytes); // Cache the BLS class, for easy signing _publicKeyToBls[publicKey] = bls; } } return(_publicKeyToBls.Keys.ToList()); }
public void BlsRoundtripSignAndVerify() { // Arrange var privateKey = HexMate.Convert.FromHexString(PrivateKeys[1]); var messageHash = MessageHashes[0]; var domain = Domains[0]; Console.WriteLine("Input:"); Console.WriteLine("Private Key: [{0}] {1}", privateKey.Length, HexMate.Convert.ToHexString(privateKey)); Console.WriteLine("Domain: [{0}] {1}", domain.Length, HexMate.Convert.ToHexString(domain)); Console.WriteLine("MessageHash: [{0}] {1}", messageHash.Length, HexMate.Convert.ToHexString(messageHash)); // Act var parameters = new BLSParameters() { PrivateKey = privateKey }; using var bls = new BLSHerumi(parameters); var publicKey = new byte[48]; _ = bls.TryExportBLSPublicKey(publicKey, out var _); Console.WriteLine("Public Key: [{0}] {1}", publicKey.Length, HexMate.Convert.ToHexString(publicKey)); var initialX = new byte[96]; _ = bls.TryCombineHashAndDomain(messageHash, domain, initialX, out var _); Console.WriteLine("InitialX: [{0}] {1}", initialX.Length, HexMate.Convert.ToHexString(initialX)); var signature = new byte[96]; var signatureSuccess = bls.TrySignHash(initialX, signature.AsSpan(), out var bytesWritten); Console.WriteLine("Signature: {0} [{1}] {2}", signatureSuccess, bytesWritten, HexMate.Convert.ToHexString(signature)); //var expectedSignature = HexMate.Convert.FromHexString("b9d1bf921b3dd048bdce38c2ceac2a2a8093c864881f2415f22b198de935ffa791707855c1656dc21a7af2d502bb46590151d645f062634c3b2cb79c4ed1c4a4b8b3f19f0f5c76965c651553e83d153ff95353735156eff77692f7a62ae653fb"); //signature.ShouldBe(expectedSignature); var verifySuccess = bls.VerifyHash(initialX, signature); Console.WriteLine("Verify1: {0}", verifySuccess); var parameters2 = new BLSParameters() { PublicKey = publicKey }; using var bls2 = new BLSHerumi(parameters); var verifySuccess2 = bls2.VerifyHash(initialX, signature); Console.WriteLine("Verify2: {0}", verifySuccess2); verifySuccess2.ShouldBeTrue(); }
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())); }
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 CryptographyService(ChainConstants chainConstants, IOptionsMonitor <MiscellaneousParameters> miscellaneousParameterOptions, IOptionsMonitor <TimeParameters> timeParameterOptions, IOptionsMonitor <StateListLengths> stateListLengthOptions, IOptionsMonitor <MaxOperationsPerBlock> maxOperationsPerBlockOptions) { _chainConstants = chainConstants; _miscellaneousParameterOptions = miscellaneousParameterOptions; _timeParameterOptions = timeParameterOptions; _stateListLengthOptions = stateListLengthOptions; _maxOperationsPerBlockOptions = maxOperationsPerBlockOptions; MiscellaneousParameters miscellaneousParameters = miscellaneousParameterOptions.CurrentValue; TimeParameters timeParameters = timeParameterOptions.CurrentValue; StateListLengths stateListLengths = stateListLengthOptions.CurrentValue; MaxOperationsPerBlock maxOperationsPerBlock = maxOperationsPerBlockOptions.CurrentValue; BLSParameters blsParameters = new BLSParameters(); _bls = BLS.Create(blsParameters); Nethermind.Ssz.Ssz.Init( chainConstants.DepositContractTreeDepth, chainConstants.JustificationBitsLength, miscellaneousParameters.MaximumValidatorsPerCommittee, timeParameters.SlotsPerEpoch, timeParameters.SlotsPerEth1VotingPeriod, timeParameters.SlotsPerHistoricalRoot, stateListLengths.EpochsPerHistoricalVector, stateListLengths.EpochsPerSlashingsVector, stateListLengths.HistoricalRootsLimit, stateListLengths.ValidatorRegistryLimit, maxOperationsPerBlock.MaximumProposerSlashings, maxOperationsPerBlock.MaximumAttesterSlashings, maxOperationsPerBlock.MaximumAttestations, maxOperationsPerBlock.MaximumDeposits, maxOperationsPerBlock.MaximumVoluntaryExits); Nethermind.Ssz.Ssz.Init( chainConstants.DepositContractTreeDepth, chainConstants.JustificationBitsLength, miscellaneousParameters.MaximumValidatorsPerCommittee, timeParameters.SlotsPerEpoch, timeParameters.SlotsPerEth1VotingPeriod, timeParameters.SlotsPerHistoricalRoot, stateListLengths.EpochsPerHistoricalVector, stateListLengths.EpochsPerSlashingsVector, stateListLengths.HistoricalRootsLimit, stateListLengths.ValidatorRegistryLimit, maxOperationsPerBlock.MaximumProposerSlashings, maxOperationsPerBlock.MaximumAttesterSlashings, maxOperationsPerBlock.MaximumAttestations, maxOperationsPerBlock.MaximumDeposits, maxOperationsPerBlock.MaximumVoluntaryExits); }
public static BlsSignature BlsSign(Root messageHash, byte[] privateKey) { var parameters = new BLSParameters() { PrivateKey = privateKey }; using var signingAlgorithm = SignatureAlgorithmFactory(parameters); var destination = new byte[96]; var success = signingAlgorithm.TrySignData(messageHash.AsSpan(), destination, out var bytesWritten); return(new BlsSignature(destination)); }
public static BlsSignature BlsSign(Hash32 messageHash, byte[] privateKey, Domain domain) { var parameters = new BLSParameters() { PrivateKey = privateKey }; using var signingAlgorithm = SignatureAlgorithmFactory(parameters); var destination = new byte[96]; var success = signingAlgorithm.TrySignHash(messageHash.AsSpan(), destination, out var bytesWritten, domain.AsSpan().ToArray()); return(new BlsSignature(destination)); }
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 void DataSignAndVerify() { // Arrange var privateKey = HexMate.Convert.FromHexString(PrivateKeys[1]); var messageData = MessageData[1]; Console.WriteLine("Input:"); Console.WriteLine("Private Key: [{0}] {1}", privateKey.Length, HexMate.Convert.ToHexString(privateKey)); Console.WriteLine("MessageData: [{0}] {1}", messageData.Length, HexMate.Convert.ToHexString(messageData)); // Act var parameters = new BLSParameters() { PrivateKey = privateKey }; using var bls = new BLSHerumi(parameters); var publicKey = new byte[48]; _ = bls.TryExportBlsPublicKey(publicKey, out var _); Console.WriteLine("Public Key: [{0}] {1}", publicKey.Length, HexMate.Convert.ToHexString(publicKey)); var signature = new byte[96]; var signatureSuccess = bls.TrySignData(messageData, signature.AsSpan(), out var bytesWritten); Console.WriteLine("Signature: {0} [{1}] {2}", signatureSuccess, bytesWritten, HexMate.Convert.ToHexString(signature)); var verifySuccess = bls.VerifyData(messageData, signature); Console.WriteLine("Verify1: {0}", verifySuccess); var parameters2 = new BLSParameters() { PublicKey = publicKey }; using var bls2 = new BLSHerumi(parameters); var verifySuccess2 = bls2.VerifyData(messageData, signature); Console.WriteLine("Verify2: {0}", verifySuccess2); verifySuccess2.ShouldBeTrue(); }
public void TestPrivateKeyToPublic() { var privateKeyBytes = Bytes.FromHexString("47b8192d77bf871b62e87859d653922725724a5c031afeabc60bcef5ff665138"); Console.WriteLine("Serialized private key: {0}", privateKeyBytes.ToHexString()); //BlsProxy.GetPublicKey(privateKeyBytes, out var publicKeySpan); var parameters = new BLSParameters() { PrivateKey = privateKeyBytes }; using var bls = new BLSHerumi(parameters); var result = new byte[48]; var success = bls.TryExportBlsPublicKey(result.AsSpan(), out var bytesWritten); //var publicKeyBytes = publicKeySpan.ToArray(); var publicKeyBytes = result; Assert.AreEqual("b301803f8b5ac4a1133581fc676dfedc60d891dd5fa99028805e5ea5b08d3491af75d0707adab3b70c6a6a580217bf81", publicKeyBytes.ToHexString()); }
private static void EnsureKeys(TimeParameters timeParameters) { var keysRequired = (int)(ulong)timeParameters.SlotsPerEpoch * 16; if (_testKeys.Count == keysRequired) { return; } _testKeys.Clear(); _privateKeys.Clear(); _publicKeys.Clear(); // Private key is ~255 bits (32 bytes) long for (var keyNumber = 0; keyNumber < keysRequired; keyNumber++) { var privateKeySpan = new Span <byte>(new byte[32]); // Key is big endian number, so write Int32 to last 4 bytes. BitConverter.TryWriteBytes(privateKeySpan.Slice(28), keyNumber + 1); if (BitConverter.IsLittleEndian) { // And reverse if necessary privateKeySpan.Slice(28).Reverse(); } var privateKey = privateKeySpan.ToArray(); var blsParameters = new BLSParameters() { PrivateKey = privateKey }; using var bls = BLS.Create(blsParameters); var publicKeyBytes = new byte[BlsPublicKey.Length]; bls.TryExportBLSPublicKey(publicKeyBytes, out var bytesWritten); var publicKey = new BlsPublicKey(publicKeyBytes); _privateKeys.Add(privateKey); _publicKeys.Add(publicKey); _testKeys[publicKey] = privateKey; } }
public void Verify(string testName, byte[] publicKey, byte[] messageData, byte[] signature, bool expected) { // Arrange var parameters = new BLSParameters() { PublicKey = publicKey }; Console.WriteLine("Input:"); Console.WriteLine("Public Key: [{0}] {1}", publicKey.Length, HexMate.Convert.ToHexString(publicKey)); Console.WriteLine("MessageHash: [{0}] {1}", messageData.Length, HexMate.Convert.ToHexString(messageData)); Console.WriteLine("Signature: [{0}] {1}", signature.Length, HexMate.Convert.ToHexString(signature)); // Act using var bls = new BLSHerumi(parameters); var success = bls.VerifyData(messageData, signature); Console.WriteLine("Output: Success {0}", success); // Assert success.ShouldBe(expected); }
public void Case03PrivateToPublicKey(byte[] privateKey, byte[] expected) { // Arrange var parameters = new BLSParameters() { PrivateKey = privateKey }; Console.WriteLine("Input:"); Console.WriteLine("Private Key: [{0}] {1}", privateKey.Length, HexMate.Convert.ToHexString(privateKey)); // Act using var bls = new BLSHerumi(parameters); var result = new byte[48]; var success = bls.TryExportBlsPublicKey(result.AsSpan(), out var bytesWritten); Console.WriteLine("Output:"); Console.WriteLine("Public Key: [{0}] {1}", result.Length, HexMate.Convert.ToHexString(result)); // Assert result.ShouldBe(expected); }
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 Case05VerifyMessages(byte[] publicKey, byte[] messageHash, byte[] domain, byte[] signature, bool expected) { // Arrange var parameters = new BLSParameters() { PublicKey = publicKey }; Console.WriteLine("Input:"); Console.WriteLine("Public Key: [{0}] {1}", publicKey.Length, HexMate.Convert.ToHexString(publicKey)); Console.WriteLine("MessageHash: [{0}] {1}", messageHash.Length, HexMate.Convert.ToHexString(messageHash)); Console.WriteLine("Domain: [{0}] {1}", domain.Length, HexMate.Convert.ToHexString(domain)); Console.WriteLine("Signature: [{0}] {1}", signature.Length, HexMate.Convert.ToHexString(signature)); // Act using var bls = new BLSHerumi(parameters); var success = bls.VerifyHash(messageHash, signature, domain); Console.WriteLine("Output: Success {0}", success); // Assert success.ShouldBe(expected); }
public void Sign(string testName, byte[] privateKey, byte[] messageData, byte[] expected) { // Arrange var parameters = new BLSParameters() { PrivateKey = privateKey }; Console.WriteLine("Input:"); Console.WriteLine("MessageData: [{0}] {1}", messageData.Length, HexMate.Convert.ToHexString(messageData)); Console.WriteLine("Private Key: [{0}] {1}", privateKey.Length, HexMate.Convert.ToHexString(privateKey)); // Act using var bls = new BLSHerumi(parameters); var result = new byte[96]; //var success = bls.TrySignData(privateKey, messageData, result.AsSpan(), out var bytesWritten); var success = bls.TrySignData(messageData, result.AsSpan(), out var bytesWritten); Console.WriteLine("Output:"); Console.WriteLine("Signature: {0} [{1}] {2}", success, bytesWritten, HexMate.Convert.ToHexString(result)); // Assert result.ShouldBe(expected); }
public void Case04SignMessages(byte[] privateKey, byte[] messageHash, byte[] domain, byte[] expected) { // Arrange var parameters = new BLSParameters() { PrivateKey = privateKey }; Console.WriteLine("Input:"); Console.WriteLine("Domain: [{0}] {1}", domain.Length, HexMate.Convert.ToHexString(domain)); Console.WriteLine("MessageHash: [{0}] {1}", messageHash.Length, HexMate.Convert.ToHexString(messageHash)); Console.WriteLine("Private Key: [{0}] {1}", privateKey.Length, HexMate.Convert.ToHexString(privateKey)); // Act using var bls = new BLSHerumi(parameters); var result = new byte[96]; var success = bls.TrySignHash(messageHash, result.AsSpan(), out var bytesWritten, domain); Console.WriteLine("Output:"); Console.WriteLine("Signature: {0} [{1}] {2}", success, bytesWritten, HexMate.Convert.ToHexString(result)); // Assert result.ShouldBe(expected); }
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)); }
public void BlsRoundtripAggregatePublicKeyVerifySharedHash() { // Arrange var privateKey1 = HexMate.Convert.FromHexString(PrivateKeys[1]); var privateKey2 = HexMate.Convert.FromHexString(PrivateKeys[2]); var sharedMessageHash = MessageHashes[1]; var domain1 = Domains[1]; Console.WriteLine("Input:"); Console.WriteLine("Private Key 1: [{0}] {1}", privateKey1.Length, HexMate.Convert.ToHexString(privateKey1)); Console.WriteLine("Private Key 2: [{0}] {1}", privateKey2.Length, HexMate.Convert.ToHexString(privateKey2)); Console.WriteLine("MessageHash 1: [{0}] {1}", sharedMessageHash.Length, HexMate.Convert.ToHexString(sharedMessageHash)); Console.WriteLine("Domain: [{0}] {1}", domain1.Length, HexMate.Convert.ToHexString(domain1)); // Sign 1 using var bls1 = new BLSHerumi(new BLSParameters() { PrivateKey = privateKey1 }); var signature1 = new byte[96]; _ = bls1.TrySignHash(sharedMessageHash, signature1.AsSpan(), out var _, domain1); Console.WriteLine("Signature 1: [{0}] {1}", signature1.Length, HexMate.Convert.ToHexString(signature1)); var publicKey1 = new byte[48]; _ = bls1.TryExportBlsPublicKey(publicKey1, out var _); Console.WriteLine("Public Key 1: [{0}] {1}", publicKey1.Length, HexMate.Convert.ToHexString(publicKey1)); // Sign 2 using var bls2 = new BLSHerumi(new BLSParameters() { PrivateKey = privateKey2 }); var signature2 = new byte[96]; _ = bls2.TrySignHash(sharedMessageHash, signature2.AsSpan(), out var _, domain1); Console.WriteLine("Signature 2: [{0}] {1}", signature2.Length, HexMate.Convert.ToHexString(signature2)); var publicKey2 = new byte[48]; _ = bls2.TryExportBlsPublicKey(publicKey2, out var _); Console.WriteLine("Public Key 2: [{0}] {1}", publicKey2.Length, HexMate.Convert.ToHexString(publicKey2)); // Aggregate public keys var publicKeys = new Span <byte>(new byte[48 * 2]); publicKey1.CopyTo(publicKeys); publicKey2.CopyTo(publicKeys.Slice(48)); using var blsAggregateKeys = new BLSHerumi(new BLSParameters()); var aggregatePublicKey = new byte[48]; blsAggregateKeys.TryAggregatePublicKeys(publicKeys, aggregatePublicKey, out var _); Console.WriteLine("Aggregate Public Key: [{0}] {1}", aggregatePublicKey.Length, HexMate.Convert.ToHexString(aggregatePublicKey)); // Aggregate signatures var signatures = new Span <byte>(new byte[96 * 2]); signature1.CopyTo(signatures); signature2.CopyTo(signatures.Slice(96)); using var blsAggregate = new BLSHerumi(new BLSParameters()); var aggregateSignature = new byte[96]; blsAggregate.TryAggregateSignatures(signatures, aggregateSignature, out var _); Console.WriteLine("Aggregate Signature: [{0}] {1}", aggregateSignature.Length, HexMate.Convert.ToHexString(aggregateSignature)); // Verify aggregates // i.e. the combined aggregatePublicKey / aggregateSignature are a valid pair var aggregatePublicKeyParameters = new BLSParameters() { PublicKey = aggregatePublicKey }; using var blsVerify = new BLSHerumi(aggregatePublicKeyParameters); var verifySuccess = blsVerify.VerifyHash(sharedMessageHash, aggregateSignature, domain1); Console.WriteLine("Verify: {0}", verifySuccess); verifySuccess.ShouldBeTrue(); }
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 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); }