public void TestComputeChallengeEmptyMessage() { var signatureService = new MultiSignature(_sepSecp256K1); long bitmap = 0b111; List <byte[]> publicKeys = new List <byte[]>(); byte[] publicKey = new Participant("Alice").PublicKey; var commitments = new List <byte[]> { "02181b4df800671642e3df9a953a29a4f571acc1bf0714ed5ae714a9804d97079f".ToByteArray(), "02e8196913323fbb7a34d9455b778e877e1d1fa0205b5949504e55a2d999931366".ToByteArray(), "02ef67409f09053060e79d8ad5b1fe60690b5eaa35b67f071ca111a0a7edeb6b38".ToByteArray(), new Participant("Commitment 1").PublicKey, new Participant("Commitment 2").PublicKey, publicKey }; byte[] aggregatedCommitment = new byte[0]; var exception = Assert.Throws <ArgumentOutOfRangeException>(() => signatureService.ComputeChallenge(publicKeys, publicKey, aggregatedCommitment, string.Empty.ToHexEncodedByteArray(), bitmap)); Console.WriteLine(exception.Message); Assert.IsTrue(exception.Message.StartsWith("[signers] cannot be less than or equal to 0.")); }
public Transaction CreateMultiSignatureTransaction(out PrivateKeyNotWallet account1, out PrivateKeyNotWallet account2, out PrivateKeyNotWallet account3, out PrivateKeyNotWallet account4) { account1 = CreateAccount(); account2 = CreateAccount(); account3 = CreateAccount(); account4 = CreateAccount(); var multi = new MultiSignature(new List <Address> { account1, account2, account3 }, 2); var declarations = new List <TxDeclaration>() { multi }; var inputs = new List <TxInput>() { new TxInput(multi.Address, Currency.BTC, Amount.FromWholeValue(10)), }; var outputs = new List <TxOutput>() { new TxOutput(account4, Currency.BTC, Amount.FromWholeValue(10)), }; return(new Transaction(declarations, inputs, outputs, TransactionMessage.Empty, DateTime.UtcNow.Ticks)); }
public void TestComputeCommitmentSecretNotZero() { var signatureService = new MultiSignature(_sepSecp256K1); var commitmentSecret = signatureService.ComputeCommitmentSecret(); var secret = new BigInteger(commitmentSecret); Assert.AreNotEqual(BigInteger.Zero, secret); }
public void TestValidateCommitmentValid() { var signatureService = new MultiSignature(_sepSecp256K1); var commitment = signatureService.ComputeCommitment(signatureService.ComputeCommitmentSecret()); var commitmentHash = signatureService.ComputeCommitmentHash(commitment); Assert.IsTrue(signatureService.ValidateCommitment(commitment, commitmentHash)); }
public void TestComputeCommitmentEmptySecret() { var signatureService = new MultiSignature(_sepSecp256K1); var commitmentSecret = new byte[0]; var exception = Assert.Throws <ArgumentOutOfRangeException>(() => signatureService.ComputeCommitment(commitmentSecret)); Assert.IsTrue(exception.Message.StartsWith("[commitmentSecret] cannot be less than or equal to 0.")); }
public void TestComputeCommitmentHash() { var signatureService = new MultiSignature(_sepSecp256K1); var commitment = signatureService.ComputeCommitment(signatureService.ComputeCommitmentSecret()); var commitmentHash = signatureService.ComputeCommitmentHash(commitment); Assert.AreNotEqual(commitment, commitmentHash); }
// bad naming public virtual bool DeclareAccount(MultiSignature account) { if (TrySetDeclaration(account)) { multisigToInclude.Add(account); return(true); } return(false); // Debug.Assert(isNew); // This is false, because account can be added and charged before the declaration sent }
public void TestAggregateCommitmentsEmptyCommitments() { var signatureService = new MultiSignature(_sepSecp256K1); long bitmap = 3; var commitments = new List <byte[]>(); var exception = Assert.Throws <ArgumentOutOfRangeException>(() => signatureService.AggregateCommitments(commitments, bitmap)); Console.WriteLine(exception.Message); Assert.IsTrue(exception.Message.StartsWith("[commitments] cannot be less than or equal to 0.")); }
public void TestComputeCommitmentNullSecret() { var signatureService = new MultiSignature(_sepSecp256K1); byte[] commitmentSecret = null; var exception = // ReSharper disable once ExpressionIsAlwaysNull Assert.Throws <ArgumentNullException>(() => signatureService.ComputeCommitment(commitmentSecret)); Assert.IsTrue(exception.Message.StartsWith("[commitmentSecret] cannot be Null.")); }
public void TestMultiSignature() { using (var context = CreateContext()) { var receiver = CreateAccount(); var signer1 = CreateAccount(); var signer2 = CreateAccount(); var issuer = BTC_ISSUER; var signers = new List <Address>() { signer1.Address, signer2.Address }; var multi = new MultiSignature(signers, 2); var multiAddress = multi.Address; // issuer send to multisignature { var signed = Transfer(issuer, multiAddress, Currency.BTC, 10, null, null, new List <TxDeclaration>() { multi }); context.SendTransaction(signed); Assert.IsTrue(context.TryCreateNextLedger()); Assert.IsTrue(context.TryGetAccount(issuer.Address.Encoded, out var issuerAccount)); Assert.IsTrue(context.TryGetAccount(multiAddress.Encoded, out var multiAccount)); // check that the money has been sent Assert.IsTrue(multiAccount.GetBalance(Currency.BTC) == 10); Assert.IsTrue(issuerAccount.GetBalance(Currency.BTC) == -10); } // multisignature send to receiver { var signed = Transfer(multiAddress, new List <PrivateKeyNotWallet> { signer1, signer2 }, receiver, Currency.BTC, 10); context.SendTransaction(signed); Assert.IsTrue(context.TryCreateNextLedger()); Assert.IsTrue(context.TryGetAccount(receiver.Address.Encoded, out var receiverAccount)); Assert.IsTrue(context.TryGetAccount(issuer.Address.Encoded, out var issuerAccount)); Assert.IsTrue(context.TryGetAccount(multiAddress.Encoded, out var multiAccount)); // check that the money has been received Assert.IsTrue(multiAccount.GetBalance(Currency.BTC) == 0); Assert.IsTrue(issuerAccount.GetBalance(Currency.BTC) == -10); Assert.IsTrue(receiverAccount.GetBalance(Currency.BTC) == 10); } } }
public void TestAggregateCommitmentsNullCommitments() { var signatureService = new MultiSignature(_sepSecp256K1); long bitmap = 3; List <byte[]> commitments = null; var exception = // ReSharper disable once ExpressionIsAlwaysNull Assert.Throws <ArgumentNullException>(() => signatureService.AggregateCommitments(commitments, bitmap)); Console.WriteLine(exception.Message); Assert.IsTrue(exception.Message.StartsWith("[commitments] cannot be Null.")); }
public void TestComputeSignatureShareEmptyCommitmentSecret() { var signatureService = new MultiSignature(_sepSecp256K1); byte[] commitmentSecret = new byte[0]; byte[] challenge = Digests.Sha3("dummy challenge".ToHexEncodedByteArray()); byte[] privateKey = new Participant("Alice").PrivateKey; var exception = Assert.Throws <ArgumentOutOfRangeException>(() => signatureService.ComputeSignatureShare(challenge, privateKey, commitmentSecret)); Console.WriteLine(exception.Message); Assert.IsTrue(exception.Message.StartsWith("[commitmentSecret] cannot be less than or equal to 0.")); }
public void TestComputeSignatureShareNullChallenge() { var signatureService = new MultiSignature(_sepSecp256K1); byte[] challenge = null; byte[] privateKey = new Participant("Alice").PrivateKey; byte[] commitmentSecret = signatureService.ComputeCommitmentSecret(); var exception = Assert.Throws <ArgumentNullException>(() => signatureService.ComputeSignatureShare(challenge, privateKey, commitmentSecret)); Console.WriteLine(exception.Message); Assert.IsTrue(exception.Message.StartsWith("[challenge] cannot be Null.")); }
public void TestComputeSignatureShareNullPrivateKey() { var signatureService = new MultiSignature(_sepSecp256K1); byte[] challenge = Digests.Sha3("dummy challenge".ToHexEncodedByteArray()); byte[] privateKey = null; byte[] commitmentSecret = signatureService.ComputeCommitmentSecret(); var exception = Assert.Throws <ArgumentNullException>(() => signatureService.ComputeSignatureShare(challenge, privateKey, commitmentSecret)); Console.WriteLine(exception.Message); Assert.IsTrue(exception.Message.StartsWith("[privateKey] cannot be Null.")); }
public void Transaction_DuplicateDeclarations() { using (var context = CreateContext()) { var issuer = BTC_ISSUER; var signers = new List <Address>() { CreateAccount().Address, CreateAccount().Address }; var multi = new MultiSignature(signers, 2); // Check multisig { var signed = Transfer(issuer, multi.Address, Currency.BTC, 1, null, null, new List <TxDeclaration> { multi, multi }); context.SendTransaction(signed, ResultCode.TransactionValidationFailed); } // create timelock var timelock = new TimeLock(DateTime.Now.AddDays(-1).ToUnixTimestamp()); // Check timelocks { var signed = Transfer(issuer, timelock.Address, Currency.BTC, 1, null, null, new List <TxDeclaration> { timelock, timelock }); context.SendTransaction(signed, ResultCode.TransactionValidationFailed); } var secret = Secret.GenerateSecret(); var hashlock = new HashLock(secret.ComputeSecretHash(SecretHashType.SHA256)); // Check hashLock { var signed = Transfer(issuer, hashlock.Address, Currency.BTC, 1, null, null, new List <TxDeclaration> { hashlock, hashlock }); context.SendTransaction(signed, ResultCode.TransactionValidationFailed); } var secretRevelation = new SecretRevelation(secret); // Check Secret { var signed = Transfer(issuer, hashlock.Address, Currency.BTC, 1, null, null, new List <TxDeclaration> { secretRevelation, secretRevelation }); context.SendTransaction(signed, ResultCode.TransactionValidationFailed); } } }
public void TestAggregatedCommitment() { var signatureService = new MultiSignature(_sepSecp256K1); long bitmap = 0b111; var commitments = new List <byte[]> { "02181b4df800671642e3df9a953a29a4f571acc1bf0714ed5ae714a9804d97079f".ToByteArray(), "02e8196913323fbb7a34d9455b778e877e1d1fa0205b5949504e55a2d999931366".ToByteArray(), "02ef67409f09053060e79d8ad5b1fe60690b5eaa35b67f071ca111a0a7edeb6b38".ToByteArray() }; Assert.AreEqual("02534d4371d6ea9f8b856a632e4e31d784eec9120b3252080702d872c696012289", signatureService.AggregateCommitments(commitments, bitmap).ToHexString()); }
public void TestVerifySignatureShareOk() { var signatureService = new MultiSignature(_sepSecp256K1); var signers = new List <byte[]>(); var commitmentSecrets = new List <byte[]>(); var commitments = new List <byte[]>(); var alice = new Participant("Alice"); var bob = new Participant("Bob"); var carol = new Participant("Carol"); long bitmap = 0; var message = "The quick brown fox jumps over the lazy dog.".ToHexEncodedByteArray(); signers.Add(alice.PublicKey); signers.Add(bob.PublicKey); signers.Add(carol.PublicKey); for (var i = 0; i < signers.Count; i++) { bitmap = (bitmap << 1) | 1; commitmentSecrets.Add(signatureService.ComputeCommitmentSecret()); commitments.Add(signatureService.ComputeCommitment(commitmentSecrets[i])); } var aggregatedCommitment = signatureService.AggregateCommitments(commitments, bitmap); var challenge = signatureService.ComputeChallenge(signers, alice.PublicKey, aggregatedCommitment, message, bitmap); var signature = signatureService.ComputeSignatureShare(challenge, alice.PrivateKey, commitmentSecrets[0]); Assert.IsTrue(signatureService.VerifySignatureShare( signers, alice.PublicKey, signature, aggregatedCommitment, commitments[0], message, bitmap)); }
public void TestComputeChallengeNullPublicKeys() { var signatureService = new MultiSignature(_sepSecp256K1); long bitmap = 0b111; List <byte[]> publicKeys = null; var keyPair = new Participant("Alice"); var publicKey = keyPair.PublicKey; var commitments = new List <byte[]> { "02181b4df800671642e3df9a953a29a4f571acc1bf0714ed5ae714a9804d97079f".ToByteArray(), "02e8196913323fbb7a34d9455b778e877e1d1fa0205b5949504e55a2d999931366".ToByteArray(), "02ef67409f09053060e79d8ad5b1fe60690b5eaa35b67f071ca111a0a7edeb6b38".ToByteArray() }; var aggregatedCommitment = signatureService.AggregateCommitments(commitments, bitmap); var exception = Assert.Throws <ArgumentNullException>(() => signatureService.ComputeChallenge(publicKeys, publicKey, aggregatedCommitment, "hello".ToHexEncodedByteArray(), bitmap)); Console.WriteLine(exception.Message); Assert.IsTrue(exception.Message.StartsWith("[signers] cannot be Null.")); }
public void TestMultiSignature2() { using (var context = CreateContext()) { var receiver = CreateAccount(); var signer1 = CreateAccount(); var signer2 = CreateAccount(); var issuer = BTC_ISSUER; var signers = new List <Address>() { signer1.Address, signer2.Address }; var multi = new MultiSignature(signers, 2); var multiAddress = multi.Address; // issuer send to multisignature { var signed = Transfer(issuer, multiAddress, Currency.BTC, 3); context.SendTransaction(signed); Assert.IsTrue(context.TryCreateNextLedger()); Assert.IsTrue(context.TryGetAccount(issuer.Address.Encoded, out var issuerAccount)); Assert.IsTrue(context.TryGetAccount(multiAddress.Encoded, out var multiAccount)); // check that the money has been sent Assert.IsTrue(multiAccount.GetBalance(Currency.BTC) == 3); Assert.IsTrue(issuerAccount.GetBalance(Currency.BTC) == -3); } // multisignature send to receiver without the declaration Fail. Because no required declarations (signatures) found for the multisigaddress { var signed = Transfer(multiAddress, new List <PrivateKeyNotWallet> { signer1, signer2 }, receiver, Currency.BTC, 1); context.SendTransaction(signed, ResultCode.TransactionValidationFailed); Assert.IsTrue(context.TryGetAccount(issuer.Address.Encoded, out var issuerAccount)); Assert.IsTrue(context.TryGetAccount(multiAddress.Encoded, out var multiAccount)); // check the money Assert.IsTrue(multiAccount.GetBalance(Currency.BTC) == 3); Assert.IsTrue(issuerAccount.GetBalance(Currency.BTC) == -3); } // multisignature send to receiver with the declaration PASS { var signed = Transfer(multiAddress, new List <PrivateKeyNotWallet> { signer1, signer2 }, receiver, Currency.BTC, 1, new List <TxDeclaration> { multi }); context.SendTransaction(signed); Assert.IsTrue(context.TryCreateNextLedger()); Assert.IsTrue(context.TryGetAccount(issuer.Address.Encoded, out var issuerAccount)); Assert.IsTrue(context.TryGetAccount(multiAddress.Encoded, out var multiAccount)); Assert.IsTrue(context.TryGetAccount(receiver.Address.Encoded, out var receiverAccount)); // check that the money has been received Assert.IsTrue(multiAccount.GetBalance(Currency.BTC) == 2); Assert.IsTrue(issuerAccount.GetBalance(Currency.BTC) == -3); Assert.IsTrue(receiverAccount.GetBalance(Currency.BTC) == 1); } // multisignature send to receiver without the declaration PASS because it has already been declared { var signed = Transfer(multiAddress, new List <PrivateKeyNotWallet> { signer1, signer2 }, receiver, Currency.BTC, 1); context.SendTransaction(signed); Assert.IsTrue(context.TryCreateNextLedger()); Assert.IsTrue(context.TryGetAccount(issuer.Address.Encoded, out var issuerAccount)); Assert.IsTrue(context.TryGetAccount(multiAddress.Encoded, out var multiAccount)); Assert.IsTrue(context.TryGetAccount(receiver.Address.Encoded, out var receiverAccount)); // check that the money has been received Assert.IsTrue(multiAccount.GetBalance(Currency.BTC) == 1); Assert.IsTrue(issuerAccount.GetBalance(Currency.BTC) == -3); Assert.IsTrue(receiverAccount.GetBalance(Currency.BTC) == 2); } } }
private static Internals.MultiSignature CreateMultisignature(MultiSignature declaration) { return(new Internals.MultiSignature(declaration.Signers.Select(_ => _.Encoded).ToList(), declaration.Required, declaration.Address.Encoded)); }
private bool TryGetMultiSigFromDeclarations(List <TxDeclaration> declarations, Address address, out MultiSignature multisig) { foreach (var txDeclaration in declarations) { if (txDeclaration.Type == DeclarationType.MultiSignature) { multisig = (MultiSignature)txDeclaration; if (multisig.Address == address) { return(true); } } } multisig = null; return(false); }
public void LedgerTransformationTestMerkleHash() { using (var context = CreateContext(true)) { var sender = BTC_ISSUER; var signer1 = CreateAccount(); var signer2 = CreateAccount(); var signers = new List <Address>() { signer1, signer2 }; var multi = new MultiSignature(signers, 2); var secret = Secret.GenerateSecret(); var hashlock = new HashLock(secret.ComputeSecretHash(SecretHashType.SHA3)); var timeLock = new TimeLock(DateTime.Now.AddDays(-1).ToUnixTimestamp()); var signed = Transfer(sender, multi.Address, Currency.BTC, 10, null, null, new List <TxDeclaration>() { multi, hashlock, timeLock }); context.SendTransaction(signed); var signed1 = Transfer(sender, hashlock.Address, Currency.BTC, 10, null, null, new List <TxDeclaration>() { multi, hashlock, timeLock }); context.SendTransaction(signed1); var signed2 = Transfer(sender, timeLock.Address, Currency.BTC, 10, null, null, new List <TxDeclaration>() { multi, hashlock, timeLock }); context.SendTransaction(signed2); // Send address declaration but don't use the address var signed3 = Transfer(sender, timeLock.Address, Currency.BTC, 10, null, null, new List <TxDeclaration>() { new MultiSignature(new List <Address>() { CreateAccount(), CreateAccount(), CreateAccount() }, 3) }); context.SendTransaction(signed3); // Send address declaration but don't use the address var signed4 = Transfer(sender, timeLock.Address, Currency.BTC, 10, null, null, new List <TxDeclaration>() { new HashLock(Secret.GenerateSecret().ComputeSecretHash(SecretHashType.SHA256)) }); context.SendTransaction(signed4); // Send address declaration but don't use the address var signed5 = Transfer(sender, timeLock.Address, Currency.BTC, 10, null, null, new List <TxDeclaration>() { new TimeLock(777) }); context.SendTransaction(signed5); Assert.IsTrue(context.TryCreateNextLedger()); context.DataTransformationService.WaitTransformationCompleted(); var last = context.LedgerService.LedgerManager.GetMerkleRootHash(); Assert.Fail(); /* * var fromDb = context.DatabaseService.ReadDatabaseManager.GetLastLedger(); * * if(fromDb.GetHeight() != context.LedgerService.LedgerManager.LastLedger.GetHeight()) * Assert.Inconclusive(); * * Assert.IsTrue(last.Equals(fromDb.Ledger.MerkleHash)); */ } }
public void TestHashTimeLock() { // TODO CANCEL sender + receiver // we can emulate hashtime lock behaviour using (var context = CreateContext()) { var issuer = BTC_ISSUER; var sender = CreateAccount(); var receiver = CreateAccount(); var timeunlocked = new TimeLock(DateTime.Now.AddDays(-1).ToUnixTimestamp()); var timelocked = new TimeLock(DateTime.Now.AddDays(1).ToUnixTimestamp()); // TODO we are missing Hash160 : SHA256 + ripemd160 // create secret hash var type = SecretHashType.SHA3; var secret = Secret.GenerateSecret(); var hash = secret.ComputeSecretHash(type); var hashlock = new HashLock(hash); var revelation = new SecretRevelation(secret); // CLAIM receiver + hashlock var claim = new MultiSignature(new List <Address>() { receiver.Address, hashlock.Address }, 2); // TIMEOUT sender + timelock var timeoutlocked = new MultiSignature(new List <Address>() { sender.Address, timelocked.Address }, 2); var timeoutunlocked = new MultiSignature(new List <Address>() { sender.Address, timeunlocked.Address }, 2); var hashtimelocked = new MultiSignature(new List <Address>() { claim.Address, timeoutlocked.Address }, 1); var hashtimeunlocked = new MultiSignature(new List <Address>() { claim.Address, timeoutunlocked.Address }, 1); // send money to hashtimelocked account { var signed = Transfer(issuer, hashtimelocked.Address, Currency.BTC, 10, null, null, new List <TxDeclaration>() { hashtimelocked }); context.SendTransaction(signed); Assert.IsTrue(context.TryCreateNextLedger()); Assert.IsTrue(context.TryGetAccount(issuer.Address.Encoded, out var issuerAccount)); Assert.IsTrue(context.TryGetAccount(hashtimelocked.Address.Encoded, out var hashtimelockedAccount)); // check that the money has been sent Assert.IsTrue(issuerAccount.GetBalance(Currency.BTC) == -10); Assert.IsTrue(hashtimelockedAccount.GetBalance(Currency.BTC) == 10); } // try timeout from hashtimelocked { var signed = Transfer(hashtimelocked.Address, new List <PrivateKeyNotWallet>() { sender }, sender, Currency.BTC, 10, new List <TxDeclaration>() { timelocked, timeoutlocked }); context.SendTransaction(signed, ResultCode.TransactionValidationFailed); } // claim from hashtimelocked { var signed = Transfer(hashtimelocked.Address, new List <PrivateKeyNotWallet>() { receiver }, issuer.Address, Currency.BTC, 10, new List <TxDeclaration>() { hashlock, claim, revelation }); context.SendTransaction(signed); Assert.IsTrue(context.TryCreateNextLedger()); // update data Assert.IsTrue(context.TryGetAccount(issuer.Address.Encoded, out var issuerAccount)); Assert.IsTrue(context.TryGetAccount(hashtimelocked.Address.Encoded, out var hashtimelockedAccount)); // check that the money has been sent Assert.IsTrue(issuerAccount.GetBalance(Currency.BTC) == 0); Assert.IsTrue(hashtimelockedAccount.GetBalance(Currency.BTC) == 0); } // send money to hashtimeunlocked account { var signed = Transfer(issuer, hashtimeunlocked.Address, Currency.BTC, 10, null, null, new List <TxDeclaration>() { hashtimeunlocked }); context.SendTransaction(signed); Assert.IsTrue(context.TryCreateNextLedger()); Assert.IsTrue(context.TryGetAccount(issuer.Address.Encoded, out var issuerAccount)); Assert.IsTrue(context.TryGetAccount(hashtimeunlocked.Address.Encoded, out var hashtimeunlockedAccount)); // check that the money has been sent Assert.IsTrue(issuerAccount.GetBalance(Currency.BTC) == -10); Assert.IsTrue(hashtimeunlockedAccount.GetBalance(Currency.BTC) == 10); } // timeout from hashtimeunlocked { var signed = Transfer(hashtimeunlocked.Address, new List <PrivateKeyNotWallet>() { sender }, issuer.Address, Currency.BTC, 10, new List <TxDeclaration>() { timeunlocked, timeoutunlocked }); context.SendTransaction(signed); Assert.IsTrue(context.TryCreateNextLedger()); // update data Assert.IsTrue(context.TryGetAccount(issuer.Address.Encoded, out var issuerAccount)); Assert.IsTrue(context.TryGetAccount(hashtimeunlocked.Address.Encoded, out var hashtimeunlockedAccount)); // check that the money has been sent Assert.IsTrue(issuerAccount.GetBalance(Currency.BTC) == 0); Assert.IsTrue(hashtimeunlockedAccount.GetBalance(Currency.BTC) == 0); } } }
protected void Write(MultiSignature multi) { Write(multi.Signers.ToList(), Write); Write(multi.Required); }
public MultiAddressRequiredSignature(MultiSignature multi, List <TransactionRequiredValidation> signers) { this.signers = signers; threshold = multi.Required; }