Exemplo n.º 1
0
        public void CreateRawTransactionTest()
        {
            ExtPrivkey privkey = new ExtPrivkey("xprv9zt1onyw8BdEf7SQ6wUVH3bQQdGD9iy9QzXveQQRhX7i5iUN7jZgLbqFEe491LfjozztYa6bJAGZ65GmDCNcbjMdjZcgmdisPJwVjcfcDhV");
            Address    addr1   = new Address(privkey.DerivePubkey(1).GetPubkey(), CfdAddressType.P2wpkh, CfdNetworkType.Regtest);
            Address    addr2   = new Address(privkey.DerivePubkey(2).GetPubkey(), CfdAddressType.P2wpkh, CfdNetworkType.Regtest);
            Address    addr3   = new Address(privkey.DerivePubkey(3).GetPubkey(), CfdAddressType.P2wpkh, CfdNetworkType.Regtest);

            OutPoint    outpoint1 = new OutPoint("0000000000000000000000000000000000000000000000000000000000000001", 2);
            OutPoint    outpoint2 = new OutPoint("0000000000000000000000000000000000000000000000000000000000000001", 3);
            Transaction tx        = new Transaction("02000000000000000000", new[] {
                new TxIn(outpoint1),
                new TxIn(outpoint2),
            }, new[] {
                new TxOut(10000, addr1.GetLockingScript()),
                new TxOut(10000, addr2.GetLockingScript()),
            });

            tx.AddTxOut(50000, addr3);
            output.WriteLine("tx:\n" + tx.ToHexString());
            Assert.Equal("020000000201000000000000000000000000000000000000000000000000000000000000000200000000ffffffff01000000000000000000000000000000000000000000000000000000000000000300000000ffffffff0310270000000000001600148b756cbd98f4f55e985f80437a619d47f0732a941027000000000000160014c0a3dd0b7c1b3281be91112e16ce931dbac2a97950c3000000000000160014ad3abd3c325e40e20d89aa054dd980b97494f16c00000000",
                         tx.ToHexString());

            Privkey           privkey1    = privkey.DerivePrivkey(11).GetPrivkey();
            Pubkey            pubkey1     = privkey1.GetPubkey();
            SignatureHashType sighashType = new SignatureHashType(CfdSighashType.All, false);
            ByteData          sighash     = tx.GetSignatureHash(outpoint1, CfdHashType.P2wpkh, pubkey1, 50000, sighashType);
            SignParameter     signature   = privkey1.CalculateEcSignature(sighash);

            signature.SetDerEncode(sighashType);
            tx.AddSign(outpoint1, CfdHashType.P2wpkh, signature, true);
            tx.AddSign(outpoint1, CfdHashType.P2wpkh, new SignParameter(pubkey1.ToHexString()), false);
            output.WriteLine("tx:\n" + tx.ToHexString());
            Assert.Equal("0200000000010201000000000000000000000000000000000000000000000000000000000000000200000000ffffffff01000000000000000000000000000000000000000000000000000000000000000300000000ffffffff0310270000000000001600148b756cbd98f4f55e985f80437a619d47f0732a941027000000000000160014c0a3dd0b7c1b3281be91112e16ce931dbac2a97950c3000000000000160014ad3abd3c325e40e20d89aa054dd980b97494f16c02473044022034db802aad655cd9be589075fc8ef325b6ffb8c24e5b27eb87bde8ad38f5fd7a0220364c916c8e8fc0adf714d7148cd1c6dc6f3e67d55471e57233b1870c65ec2727012103782f0ea892d7000e5f0f82b6ff283382a76500137a542bb0a616530094a8f54c0000000000",
                         tx.ToHexString());

            Address addr11 = new Address(pubkey1, CfdAddressType.P2wpkh, CfdNetworkType.Regtest);

            try
            {
                tx.VerifySign(outpoint1, addr11, addr11.GetAddressType(), 50000);
            }
            catch (Exception e)
            {
                Assert.Null(e);
            }

            string json = Transaction.DecodeRawTransaction(tx);

            output.WriteLine(json);
        }
Exemplo n.º 2
0
        public void PrivkeySignTest()
        {
            ExtPrivkey  privkey   = new ExtPrivkey("xprv9zt1onyw8BdEf7SQ6wUVH3bQQdGD9iy9QzXveQQRhX7i5iUN7jZgLbqFEe491LfjozztYa6bJAGZ65GmDCNcbjMdjZcgmdisPJwVjcfcDhV");
            Transaction tx        = new Transaction("020000000201000000000000000000000000000000000000000000000000000000000000000200000000ffffffff01000000000000000000000000000000000000000000000000000000000000000300000000ffffffff0310270000000000001600148b756cbd98f4f55e985f80437a619d47f0732a941027000000000000160014c0a3dd0b7c1b3281be91112e16ce931dbac2a97950c3000000000000160014ad3abd3c325e40e20d89aa054dd980b97494f16c00000000");
            OutPoint    outpoint1 = new OutPoint("0000000000000000000000000000000000000000000000000000000000000001", 2);

            Privkey           privkey1    = privkey.DerivePrivkey(11).GetPrivkey();
            SignatureHashType sighashType = new SignatureHashType(CfdSighashType.All, false);

            tx.AddSignWithPrivkeySimple(outpoint1, CfdHashType.P2wpkh, privkey1, 50000, sighashType);
            // output.WriteLine("tx:\n" + tx.ToHexString());
            Assert.Equal("0200000000010201000000000000000000000000000000000000000000000000000000000000000200000000ffffffff01000000000000000000000000000000000000000000000000000000000000000300000000ffffffff0310270000000000001600148b756cbd98f4f55e985f80437a619d47f0732a941027000000000000160014c0a3dd0b7c1b3281be91112e16ce931dbac2a97950c3000000000000160014ad3abd3c325e40e20d89aa054dd980b97494f16c02473044022034db802aad655cd9be589075fc8ef325b6ffb8c24e5b27eb87bde8ad38f5fd7a0220364c916c8e8fc0adf714d7148cd1c6dc6f3e67d55471e57233b1870c65ec2727012103782f0ea892d7000e5f0f82b6ff283382a76500137a542bb0a616530094a8f54c0000000000",
                         tx.ToHexString());
        }
        public static byte[] SignTransaction(byte[] privateKey,
            Script script, Transaction transaction, int transactionInputIndex, SignatureHashType signatureType)
        {
            ContractsCommon.NotNull(privateKey, "privateKey");
            ContractsCommon.NotNull(script, "script");
            ContractsCommon.NotNull(transaction, "transaction");
            ContractsCommon.ValidIndex(0, transaction.TransactionInputs.Count, transactionInputIndex, "transactionInputIndex");
            ContractsCommon.ResultIsNonNull<byte[]>();

            var hash = HashTransactionForSigning(script, transaction, transactionInputIndex, signatureType);

            var ecdsa = new ECDsaBouncyCastle(privateKey, true);

            return ecdsa.SignHash(hash.Bytes);
        }
        public static Hash256 HashTransactionForSigning(Script script, Transaction transaction, int transactionInputIndex, SignatureHashType signatureType)
        {
            ContractsCommon.NotNull(script, "script");
            ContractsCommon.NotNull(transaction, "transaction");
            ContractsCommon.ValidIndex(0, transaction.TransactionInputs.Count, transactionInputIndex, "transactionInputIndex");
            ContractsCommon.ResultIsNonNull<Hash256>();

            var t = TransformTransactionForSigning(script, transaction, transactionInputIndex, signatureType);
            using (var ms = new MemoryStream(t.SerializedByteSize + BufferOperations.UINT32_SIZE))
            {
                t.Serialize(ms);
                var sigType = (int)signatureType;
                ms.WriteByte((byte)sigType);
                ms.WriteByte((byte)(sigType >> 8));
                ms.WriteByte((byte)(sigType >> 16));
                ms.WriteByte((byte)(sigType >> 24));
                return CryptoFunctionProviderFactory.Default.Hash256(ms.ToArray());
            }
        }
Exemplo n.º 5
0
 /// <summary>
 /// encode by DER.
 /// </summary>
 /// <param name="signature">signature</param>
 /// <param name="sighashType">sighash type</param>
 /// <returns>DER encoded data</returns>
 public static ByteData EncodeToDer(ByteData signature, SignatureHashType sighashType)
 {
     if (signature is null)
     {
         throw new ArgumentNullException(nameof(signature));
     }
     using (var handle = new ErrorHandle())
     {
         var ret = NativeMethods.CfdEncodeSignatureByDer(
             handle.GetHandle(), signature.ToHexString(),
             sighashType.GetValue(),
             sighashType.IsSighashAnyoneCanPay,
             out IntPtr derSignature);
         if (ret != CfdErrorCode.Success)
         {
             handle.ThrowError(ret);
         }
         return(new ByteData(CCommon.ConvertToString(derSignature)));
     }
 }
Exemplo n.º 6
0
        public void TaprootSchnorrSignTest1()
        {
            var sk  = new Privkey("305e293b010d29bf3c888b617763a438fee9054c8cab66eb12ad078f819d9f27");
            var spk = SchnorrPubkey.GetPubkeyFromPrivkey(sk, out bool _);

            Assert.Equal("1777701648fa4dd93c74edd9d58cfcc7bdc2fa30a2f6fa908b6fd70c92833cfb", spk.ToHexString());

            var addr = new Address(spk, CfdAddressType.Taproot, CfdNetworkType.Testnet);

            var txHex    = "020000000116d975e4c2cea30f72f4f5fe528f5a0727d9ea149892a50c030d44423088ea2f0000000000ffffffff0130f1029500000000160014164e985d0fc92c927a66c0cbaf78e6ea389629d500000000";
            var outpoint = new OutPoint("2fea883042440d030ca5929814ead927075a8f52fef5f4720fa3cec2e475d916", 0);
            var utxos    = new UtxoData[] {
                new UtxoData(outpoint, 2499999000, new Descriptor(addr)),
            };
            var tx      = new Transaction(txHex);
            var feeData = tx.EstimateFee(utxos, 2.0);

            Assert.Equal(202, feeData.GetTotalFee());

            tx.SetTxInUtxoData(utxos);
            var sighashType = new SignatureHashType(CfdSighashType.All);
            var sighash     = tx.GetSigHashByUtxoData(outpoint, sighashType, spk);

            Assert.Equal("e5b11ddceab1e4fc49a8132ae589a39b07acf49cabb2b0fbf6104bc31da12c02", sighash.ToHexString());

            var signature = SchnorrUtil.Sign(sighash, sk);
            var sig       = signature.GetSignData(sighashType);

            Assert.Equal("61f75636003a870b7a1685abae84eedf8c9527227ac70183c376f7b3a35b07ebcbea14749e58ce1a87565b035b2f3963baa5ae3ede95e89fd607ab7849f2087201", sig.ToHexString());

            tx.AddTaprootSchnorrSign(outpoint, sig);
            Assert.Equal("0200000000010116d975e4c2cea30f72f4f5fe528f5a0727d9ea149892a50c030d44423088ea2f0000000000ffffffff0130f1029500000000160014164e985d0fc92c927a66c0cbaf78e6ea389629d5014161f75636003a870b7a1685abae84eedf8c9527227ac70183c376f7b3a35b07ebcbea14749e58ce1a87565b035b2f3963baa5ae3ede95e89fd607ab7849f208720100000000", tx.ToHexString());

            tx.VerifySignByUtxoList(outpoint);

            var isVerify = spk.Verify(signature, sighash);

            Assert.True(isVerify);
        }
        public static bool VerifySignature(byte[] publicKey, byte[] sigHash,
            Script script, Transaction transaction, int transactionInputIndex, SignatureHashType signatureType)
        {
            ContractsCommon.NotNull(publicKey, "publicKey");
            ContractsCommon.NotNull(sigHash, "sigHash");
            ContractsCommon.NotNull(script, "script");
            ContractsCommon.NotNull(transaction, "transaction");
            ContractsCommon.ValidIndex(0, transaction.TransactionInputs.Count, transactionInputIndex, "transactionInputIndex");

            // Cng ECC Public Key Blob format [72 bytes]:
            //6fbfcf5da60c7e59dfe724f4fb1b4e73f12bc48f17fb90f1e74f0d058c65e77c76aa75787f18ddd8be32b08014046ff62fef598011583e6f2d77e2b2ab850e5f0000002031534345
            //coordY[cBytes]BIG-ENDIAN coordX[cBytes]BIG-ENDIAN cBytes[4]LITTLE-ENDIAN magic[4]LITTLE-ENDIAN
            // For ECDsaP256, that magic number is: 0x31534345U, and cBytes will be 0x00000020

            // Bitcoin ECC Public Key Blob format [65 bytes]:
            //04e77ae594d5932f11547eea049b526044cbf8ac938fabfa97d3ab37732822572bd7d71c77a8ac1f5ca46fd73260f5aecc7270efbbf283bacd64ef0a9bb41e3ab9
            //type[1] coordX[cBytes] coordY[cBytes] (all LITTLE-ENDIAN)
            // type = 04 means curve points are uncompressed. No other value is expected.
            // For secp256k1, cBytes = 0x00000020

            // Probable issue here: Cng supports the NIST P-256 curve (alias of secp256r1), but Bitcoin uses the secp256k1 curve.

            if (signatureType == 0)
            {
                signatureType = (SignatureHashType)sigHash[sigHash.Length - 1];
            }
            else if (signatureType != (SignatureHashType)sigHash[sigHash.Length - 1])
            {
                return false;
            }
            var signature = new byte[72];
            Array.Copy(sigHash, signature, signature.Length);

            var hash = HashTransactionForSigning(script, transaction, transactionInputIndex, signatureType);

            var ecdsa = new ECDsaBouncyCastle(publicKey, false);

            return ecdsa.VerifyHash(hash.Bytes, signature);
        }
Exemplo n.º 8
0
 /// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="hex">hex string</param>
 public SchnorrSignature(string hex)
 {
     if (hex is null)
     {
         throw new ArgumentNullException(nameof(hex));
     }
     if ((hex.Length != Size * 2) && (hex.Length != AddedSigHashTypeSize * 2))
     {
         CfdCommon.ThrowError(CfdErrorCode.IllegalArgumentError, "Failed to signature size.");
     }
     data = hex;
     string[] list = Verify(data);
     nonce = new SchnorrPubkey(list[0]);
     key   = new Privkey(list[1]);
     if (hex.Length == AddedSigHashTypeSize * 2)
     {
         sighashType = CollectSigHashType(data);
     }
     else
     {
         sighashType = new SignatureHashType(CfdSighashType.Default, false);
     }
 }
Exemplo n.º 9
0
 /// <summary>
 /// Calculate ec-signature.
 /// </summary>
 /// <param name="sighash">signature hash.</param>
 /// <param name="hasGrindR">use grind-R.</param>
 /// <returns></returns>
 public SignParameter CalculateEcSignature(ByteData sighash, bool hasGrindR)
 {
     if (sighash is null)
     {
         throw new ArgumentNullException(nameof(sighash));
     }
     using (var handle = new ErrorHandle())
     {
         var ret = NativeMethods.CfdCalculateEcSignature(
             handle.GetHandle(), sighash.ToHexString(),
             privkey, privkeyWif, (int)networkType, hasGrindR,
             out IntPtr signatureHex);
         if (ret != CfdErrorCode.Success)
         {
             handle.ThrowError(ret);
         }
         SignParameter     signature   = new SignParameter(CCommon.ConvertToString(signatureHex));
         SignatureHashType sighashType = new SignatureHashType(CfdSighashType.All, false);
         signature.SetDerEncode(sighashType);
         signature.SetRelatedPubkey(GetPubkey());
         return(signature);
     }
 }
Exemplo n.º 10
0
        public void TaprootSchnorrSignTest2()
        {
            var sk  = new Privkey("305e293b010d29bf3c888b617763a438fee9054c8cab66eb12ad078f819d9f27");
            var spk = SchnorrPubkey.GetPubkeyFromPrivkey(sk, out bool _);

            Assert.Equal("1777701648fa4dd93c74edd9d58cfcc7bdc2fa30a2f6fa908b6fd70c92833cfb", spk.ToHexString());

            var addr = new Address(spk, CfdAddressType.Taproot, CfdNetworkType.Testnet);

            var txHex    = "020000000116d975e4c2cea30f72f4f5fe528f5a0727d9ea149892a50c030d44423088ea2f0000000000ffffffff0130f1029500000000160014164e985d0fc92c927a66c0cbaf78e6ea389629d500000000";
            var outpoint = new OutPoint("2fea883042440d030ca5929814ead927075a8f52fef5f4720fa3cec2e475d916", 0);
            var utxos    = new UtxoData[] {
                new UtxoData(outpoint, 2499999000, new Descriptor(addr.GetLockingScript(), CfdNetworkType.Mainnet)),
            };
            var tx = new Transaction(txHex);

            tx.SetTxInUtxoData(utxos);
            var sighashType = new SignatureHashType(CfdSighashType.All);

            tx.AddSignWithPrivkeyByUtxoList(outpoint, sk, sighashType);
            Assert.Equal("0200000000010116d975e4c2cea30f72f4f5fe528f5a0727d9ea149892a50c030d44423088ea2f0000000000ffffffff0130f1029500000000160014164e985d0fc92c927a66c0cbaf78e6ea389629d5014161f75636003a870b7a1685abae84eedf8c9527227ac70183c376f7b3a35b07ebcbea14749e58ce1a87565b035b2f3963baa5ae3ede95e89fd607ab7849f208720100000000", tx.ToHexString());

            tx.VerifySignByUtxoList(outpoint);
        }
Exemplo n.º 11
0
 /// <summary>
 /// decode from DER.
 /// </summary>
 /// <param name="derSignature">DER encoded data</param>
 /// <returns>signature (SignParameter object)</returns>
 public static SignParameter DecodeFromDer(ByteData derSignature)
 {
     if (derSignature is null)
     {
         throw new ArgumentNullException(nameof(derSignature));
     }
     using (var handle = new ErrorHandle())
     {
         var ret = NativeMethods.CfdDecodeSignatureFromDer(
             handle.GetHandle(), derSignature.ToHexString(),
             out IntPtr signature,
             out int signatureHashType,
             out bool _);
         if (ret != CfdErrorCode.Success)
         {
             handle.ThrowError(ret);
         }
         string            signatureStr = CCommon.ConvertToString(signature);
         SignatureHashType sighashType  = new SignatureHashType(signatureHashType);
         SignParameter     signParam    = new SignParameter(signatureStr);
         signParam.SetDerEncode(sighashType);
         return(signParam);
     }
 }
Exemplo n.º 12
0
        public void GetTxInfoTest()
        {
            ExtPrivkey privkey = new ExtPrivkey("xprv9zt1onyw8BdEf7SQ6wUVH3bQQdGD9iy9QzXveQQRhX7i5iUN7jZgLbqFEe491LfjozztYa6bJAGZ65GmDCNcbjMdjZcgmdisPJwVjcfcDhV");
            Address    addr1   = new Address(privkey.DerivePubkey(1).GetPubkey(), CfdAddressType.P2wpkh, CfdNetworkType.Regtest);
            Address    addr2   = new Address(privkey.DerivePubkey(2).GetPubkey(), CfdAddressType.P2wpkh, CfdNetworkType.Regtest);
            Address    addr3   = new Address(privkey.DerivePubkey(3).GetPubkey(), CfdAddressType.P2wpkh, CfdNetworkType.Regtest);

            OutPoint outpoint1 = new OutPoint("0000000000000000000000000000000000000000000000000000000000000001", 2);
            OutPoint outpoint2 = new OutPoint("0000000000000000000000000000000000000000000000000000000000000001", 3);
            var      txins     = new[] {
                new TxIn(outpoint1),
                new TxIn(outpoint2),
            };
            var txouts = new[] {
                new TxOut(10000, addr1.GetLockingScript()),
                new TxOut(10000, addr2.GetLockingScript()),
            };
            Transaction tx = new Transaction("02000000000000000000", txins, txouts);

            tx.AddTxOut(50000, addr3);
            output.WriteLine("tx:\n" + tx.ToHexString());
            Assert.Equal("020000000201000000000000000000000000000000000000000000000000000000000000000200000000ffffffff01000000000000000000000000000000000000000000000000000000000000000300000000ffffffff0310270000000000001600148b756cbd98f4f55e985f80437a619d47f0732a941027000000000000160014c0a3dd0b7c1b3281be91112e16ce931dbac2a97950c3000000000000160014ad3abd3c325e40e20d89aa054dd980b97494f16c00000000",
                         tx.ToHexString());

            Privkey           privkey1    = privkey.DerivePrivkey(11).GetPrivkey();
            SignatureHashType sighashType = new SignatureHashType(CfdSighashType.All, false);

            tx.AddSignWithPrivkeySimple(outpoint1, CfdHashType.P2wpkh, privkey1, 50000, sighashType);
            // output.WriteLine("tx:\n" + tx.ToHexString());
            Assert.Equal("0200000000010201000000000000000000000000000000000000000000000000000000000000000200000000ffffffff01000000000000000000000000000000000000000000000000000000000000000300000000ffffffff0310270000000000001600148b756cbd98f4f55e985f80437a619d47f0732a941027000000000000160014c0a3dd0b7c1b3281be91112e16ce931dbac2a97950c3000000000000160014ad3abd3c325e40e20d89aa054dd980b97494f16c02473044022034db802aad655cd9be589075fc8ef325b6ffb8c24e5b27eb87bde8ad38f5fd7a0220364c916c8e8fc0adf714d7148cd1c6dc6f3e67d55471e57233b1870c65ec2727012103782f0ea892d7000e5f0f82b6ff283382a76500137a542bb0a616530094a8f54c0000000000",
                         tx.ToHexString());

            Txid txid = tx.GetTxid();

            output.WriteLine("txid: " + txid.ToHexString());
            Assert.Equal("67e1878d1621e77e166bed9d726bff27b2afcde9eb3dbb1ae3088d0387f40be4",
                         txid.ToHexString());
            Txid wtxid = tx.GetWtxid();

            output.WriteLine("wtxid: " + wtxid.ToHexString());
            Assert.Equal("24c66461b4b38c750fa4528d0cf3aea9a13d3156c0a73cfd6fca6958523b97f7",
                         wtxid.ToHexString());
            Assert.Equal((uint)295, tx.GetSize());
            Assert.Equal((uint)213, tx.GetVsize());
            Assert.Equal((uint)850, tx.GetWeight());
            Assert.Equal((uint)2, tx.GetVersion());
            Assert.Equal((uint)0, tx.GetLockTime());

            Assert.Equal((uint)2, tx.GetTxInCount());
            Assert.Equal((uint)3, tx.GetTxOutCount());
            Assert.Equal((uint)1, tx.GetTxInIndex(outpoint2));
            Assert.Equal((uint)2, tx.GetTxOutIndex(addr3));
            Assert.Equal((uint)1, tx.GetTxOutIndex(addr2.GetLockingScript()));

            Assert.True(outpoint2.Equals(tx.GetTxIn(outpoint2).OutPoint));
            Assert.True(outpoint2.Equals(tx.GetTxIn(1).OutPoint));
            Assert.True(outpoint2.Equals(tx.GetTxInList()[1].OutPoint));

            Assert.True(addr2.GetLockingScript().Equals(tx.GetTxOut(addr2).ScriptPubkey));
            Assert.True(addr2.GetLockingScript().Equals(tx.GetTxOut(addr2.GetLockingScript()).ScriptPubkey));
            Assert.True(addr2.GetLockingScript().Equals(tx.GetTxOut(1).ScriptPubkey));
            Assert.True(addr2.GetLockingScript().Equals(tx.GetTxOutList()[1].ScriptPubkey));
        }
Exemplo n.º 13
0
 public ByteData ToDerEncode(SignatureHashType sighashType)
 {
     return(EncodeToDer(new ByteData(data), sighashType));
 }
        public static Transaction TransformTransactionForSigning(Script script, Transaction transaction, int transactionInputIndex, SignatureHashType signatureType)
        {
            ContractsCommon.NotNull(script, "script");
            ContractsCommon.NotNull(transaction, "transaction");
            ContractsCommon.ValidIndex(0, transaction.TransactionInputs.Count, transactionInputIndex, "transactionInputIndex");
            ContractsCommon.ResultIsNonNull <Transaction>();

            var tb = transaction.ThawTree();

            //script.Atoms.RemoveAllCopies(Scripting.Atoms.OpCodeSeparatorAtom.Atom);

            ClearAllScripts(tb.TransactionInputs);

            tb.TransactionInputs[transactionInputIndex].Script.Atoms.AddAll(script.Atoms);

            // By default, signing a transaction with SignatureHashType = 0 means the signer
            // agrees with the transaction only if the inputs and outputs are exactly the same
            // as they were when originally signed, except input scripts, which are cleared and
            // the input script for this index set as passed above.

            switch (signatureType & SignatureHashType.OutputMask)
            {
            // Signer accepts transaction regardless of the outputs specified in the transaction
            // or the sequence numbers of the other inputs.
            case SignatureHashType.None:
                tb.TransactionOutputs.Clear();
                SetSequenceNumbersToZero(tb.TransactionInputs, transactionInputIndex);
                break;

            // Signer accepts transaction if the matching outputs index of this transaction is
            // as originally signed, regarless of the sequence numbers of the other inputs.
            case SignatureHashType.Single:
                OnlyUseSingleOutput(tb.TransactionOutputs, transactionInputIndex);
                SetSequenceNumbersToZero(tb.TransactionInputs, transactionInputIndex);
                break;
            }

            // Signer accepts all other inputs to this transaction, whatever they may be
            if ((signatureType & SignatureHashType.AnyoneCanPay) == SignatureHashType.AnyoneCanPay)
            {
                OnlyUseSingleInput(tb.TransactionInputs, transactionInputIndex);
            }

            tb.Freeze();

            return(tb);
        }
        public static Hash256 HashTransactionForSigning(Script script, Transaction transaction, int transactionInputIndex, SignatureHashType signatureType)
        {
            ContractsCommon.NotNull(script, "script");
            ContractsCommon.NotNull(transaction, "transaction");
            ContractsCommon.ValidIndex(0, transaction.TransactionInputs.Count, transactionInputIndex, "transactionInputIndex");
            ContractsCommon.ResultIsNonNull <Hash256>();

            var t = TransformTransactionForSigning(script, transaction, transactionInputIndex, signatureType);

            using (var ms = new MemoryStream(t.SerializedByteSize + BufferOperations.UINT32_SIZE))
            {
                t.Serialize(ms);
                var sigType = (int)signatureType;
                ms.WriteByte((byte)sigType);
                ms.WriteByte((byte)(sigType >> 8));
                ms.WriteByte((byte)(sigType >> 16));
                ms.WriteByte((byte)(sigType >> 24));
                return(CryptoFunctionProviderFactory.Default.Hash256(ms.ToArray()));
            }
        }
        public static bool VerifySignature(byte[] publicKey, byte[] sigHash,
                                           Script script, Transaction transaction, int transactionInputIndex, SignatureHashType signatureType)
        {
            ContractsCommon.NotNull(publicKey, "publicKey");
            ContractsCommon.NotNull(sigHash, "sigHash");
            ContractsCommon.NotNull(script, "script");
            ContractsCommon.NotNull(transaction, "transaction");
            ContractsCommon.ValidIndex(0, transaction.TransactionInputs.Count, transactionInputIndex, "transactionInputIndex");

            // Cng ECC Public Key Blob format [72 bytes]:
            //6fbfcf5da60c7e59dfe724f4fb1b4e73f12bc48f17fb90f1e74f0d058c65e77c76aa75787f18ddd8be32b08014046ff62fef598011583e6f2d77e2b2ab850e5f0000002031534345
            //coordY[cBytes]BIG-ENDIAN coordX[cBytes]BIG-ENDIAN cBytes[4]LITTLE-ENDIAN magic[4]LITTLE-ENDIAN
            // For ECDsaP256, that magic number is: 0x31534345U, and cBytes will be 0x00000020

            // Bitcoin ECC Public Key Blob format [65 bytes]:
            //04e77ae594d5932f11547eea049b526044cbf8ac938fabfa97d3ab37732822572bd7d71c77a8ac1f5ca46fd73260f5aecc7270efbbf283bacd64ef0a9bb41e3ab9
            //type[1] coordX[cBytes] coordY[cBytes] (all LITTLE-ENDIAN)
            // type = 04 means curve points are uncompressed. No other value is expected.
            // For secp256k1, cBytes = 0x00000020

            // Probable issue here: Cng supports the NIST P-256 curve (alias of secp256r1), but Bitcoin uses the secp256k1 curve.

            if (signatureType == 0)
            {
                signatureType = (SignatureHashType)sigHash[sigHash.Length - 1];
            }
            else if (signatureType != (SignatureHashType)sigHash[sigHash.Length - 1])
            {
                return(false);
            }
            var signature = new byte[72];

            Array.Copy(sigHash, signature, signature.Length);

            var hash = HashTransactionForSigning(script, transaction, transactionInputIndex, signatureType);

            var ecdsa = new ECDsaBouncyCastle(publicKey, false);

            return(ecdsa.VerifyHash(hash.Bytes, signature));
        }
        public static byte[] SignTransaction(byte[] privateKey,
                                             Script script, Transaction transaction, int transactionInputIndex, SignatureHashType signatureType)
        {
            ContractsCommon.NotNull(privateKey, "privateKey");
            ContractsCommon.NotNull(script, "script");
            ContractsCommon.NotNull(transaction, "transaction");
            ContractsCommon.ValidIndex(0, transaction.TransactionInputs.Count, transactionInputIndex, "transactionInputIndex");
            ContractsCommon.ResultIsNonNull <byte[]>();

            var hash = HashTransactionForSigning(script, transaction, transactionInputIndex, signatureType);

            var ecdsa = new ECDsaBouncyCastle(privateKey, true);

            return(ecdsa.SignHash(hash.Bytes));
        }
Exemplo n.º 18
0
        public void TapScriptSignTest1()
        {
            var sk  = new Privkey("305e293b010d29bf3c888b617763a438fee9054c8cab66eb12ad078f819d9f27");
            var spk = SchnorrPubkey.GetPubkeyFromPrivkey(sk, out bool _);

            Assert.Equal("1777701648fa4dd93c74edd9d58cfcc7bdc2fa30a2f6fa908b6fd70c92833cfb", spk.ToHexString());

            var scriptCheckSig = Script.CreateFromAsm(new string[] { spk.ToHexString(), "OP_CHECKSIG" });

            var tree = new TaprootScriptTree(scriptCheckSig);

            tree.AddBranches(new string[] {
                "4d18084bb47027f47d428b2ed67e1ccace5520fdc36f308e272394e288d53b6d",
                "dc82121e4ff8d23745f3859e8939ecb0a38af63e6ddea2fff97a7fd61a1d2d54",
            });
            var taprootData = tree.GetTaprootData(spk);

            Assert.Equal("3dee5a5387a2b57902f3a6e9da077726d19c6cc8c8c7b04bcf5a197b2a9b01d2", taprootData.Pubkey.ToHexString());
            Assert.Equal("dfc43ba9fc5f8a9e1b6d6a50600c704bb9e41b741d9ed6de6559a53d2f38e513", taprootData.TapLeafHash.ToHexString());
            Assert.Equal(
                "c01777701648fa4dd93c74edd9d58cfcc7bdc2fa30a2f6fa908b6fd70c92833cfb4d18084bb47027f47d428b2ed67e1ccace5520fdc36f308e272394e288d53b6ddc82121e4ff8d23745f3859e8939ecb0a38af63e6ddea2fff97a7fd61a1d2d54",
                taprootData.ControlBlock.ToHexString());
            var tweakedPrivkey = tree.GetTweakedPrivkey(sk);

            Assert.Equal("a7d17bee0b6313cf864a1ac6f203aafd74a40703ffc050f66517e4f83ff41a03", tweakedPrivkey.ToHexString());

            var addr = new Address(taprootData.Pubkey, CfdAddressType.Taproot, CfdNetworkType.Mainnet);

            Assert.Equal("bc1p8hh955u8526hjqhn5m5a5pmhymgecmxgerrmqj70tgvhk25mq8fqw77n40", addr.ToAddressString());

            var txHex    = "02000000015b80a1af0e00c700bee9c8e4442bec933fcdc0c686dac2dc336caaaf186c5d190000000000ffffffff0130f1029500000000160014164e985d0fc92c927a66c0cbaf78e6ea389629d500000000";
            var outpoint = new OutPoint("195d6c18afaa6c33dcc2da86c6c0cd3f93ec2b44e4c8e9be00c7000eafa1805b", 0);
            var utxos    = new UtxoData[] {
                new UtxoData(outpoint, 2499999000, new Descriptor(addr.GetLockingScript(), CfdNetworkType.Mainnet)),
            };
            var tx = new Transaction(txHex);

            tx.SetTxInUtxoData(utxos);
            var sighashType = new SignatureHashType(CfdSighashType.All);
            var sighash     = tx.GetSigHashByUtxoData(outpoint, sighashType, taprootData.TapLeafHash, Transaction.codeSeparatorPositionFinal);

            Assert.Equal("80e53eaee13048aee9c6c13fa5a8529aad7fe2c362bfc16f1e2affc71f591d36", sighash.ToHexString());

            var signature = SchnorrUtil.Sign(sighash, sk);
            var sig       = signature.GetSignData(sighashType);

            Assert.Equal(
                "f5aa6b260f9df687786cd3813ba83b476e195041bccea800f2571212f4aae9848a538b6175a4f8ea291d38e351ea7f612a3d700dca63cd3aff05d315c5698ee901",
                sig.ToHexString());

            tx.AddTapScriptSign(outpoint, new SignParameter[] { sig }, taprootData.TapScript, taprootData.ControlBlock);
            Assert.Equal(
                "020000000001015b80a1af0e00c700bee9c8e4442bec933fcdc0c686dac2dc336caaaf186c5d190000000000ffffffff0130f1029500000000160014164e985d0fc92c927a66c0cbaf78e6ea389629d50341f5aa6b260f9df687786cd3813ba83b476e195041bccea800f2571212f4aae9848a538b6175a4f8ea291d38e351ea7f612a3d700dca63cd3aff05d315c5698ee90122201777701648fa4dd93c74edd9d58cfcc7bdc2fa30a2f6fa908b6fd70c92833cfbac61c01777701648fa4dd93c74edd9d58cfcc7bdc2fa30a2f6fa908b6fd70c92833cfb4d18084bb47027f47d428b2ed67e1ccace5520fdc36f308e272394e288d53b6ddc82121e4ff8d23745f3859e8939ecb0a38af63e6ddea2fff97a7fd61a1d2d5400000000",
                tx.ToHexString());

            try
            {
                tx.VerifySignByUtxoList(outpoint);
                Assert.True(false);
            }
            catch (InvalidOperationException ae)
            {
                Assert.Equal("CFD error[IllegalStateError] message:The script analysis of tapscript is not supported.", ae.Message);
            }
            catch (Exception e)
            {
                Assert.Null(e);
            }

            var isVerify = spk.Verify(signature, sighash);

            Assert.True(isVerify);
        }
Exemplo n.º 19
0
 public void SetDerEncode(SignatureHashType signatureHashType)
 {
     SetSignatureHashType(signatureHashType);
     isSetDerEncode = true;
 }
Exemplo n.º 20
0
 public void SetSignatureHashType(SignatureHashType signatureHashType)
 {
     this.signatureHashType = signatureHashType;
 }
Exemplo n.º 21
0
        public static byte[] CalculateSignatureHash(ParsedOpCode[] subScript, SignatureHashType hashType, MsgTx transaction, int index)
        {
            const SignatureHashType mask = (SignatureHashType)0x1f;

            if ((hashType & mask) == SignatureHashType.Single && index >= transaction.TxOut.Length)
            {
                throw new InvalidSignatureException("SignatureHashType.Single index out of range");
            }

            // Clear out signature scripts for input transactions not at index
            // transactionIndex
            for (var i = 0; i < transaction.TxIn.Length; i++)
            {
                transaction.TxIn[i].SignatureScript =
                    i == index?
                    subScript.SelectMany(s => s.Serialize()).ToArray()
                        : new byte[0];
            }

            switch (hashType & mask)
            {
            case SignatureHashType.None:
                transaction.TxOut = new TxOut[0];
                for (var i = 0; i < transaction.TxIn.Length; i++)
                {
                    if (i != index)
                    {
                        transaction.TxIn[i].Sequence = 0;
                    }
                }
                break;

            case SignatureHashType.Single:
                transaction.TxOut = new TxOut[index];

                for (var i = 0; i < index; i++)
                {
                    transaction.TxOut[i].Value    = -1;
                    transaction.TxOut[i].PkScript = null;
                }

                for (var i = 0; i < transaction.TxIn.Length; i++)
                {
                    if (i != index)
                    {
                        transaction.TxIn[i].Sequence = 0;
                    }
                }
                break;

            case SignatureHashType.Old:
                break;

            case SignatureHashType.All:
                break;

            case SignatureHashType.AllValue:
                break;

            case SignatureHashType.AnyOneCanPay:
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }

            if ((hashType & SignatureHashType.AnyOneCanPay) != 0)
            {
                transaction.TxIn = transaction.TxIn
                                   .Skip(index)
                                   .Take(1)
                                   .ToArray();
            }

            var wbuf = new List <byte>(32 * 2 + 4);

            wbuf.AddRange(BitConverter.GetBytes((uint)hashType));

            var prefixHash  = transaction.GetHash(TxSerializeType.NoWitness);
            var witnessHash = transaction.GetHash(
                (hashType & mask) != SignatureHashType.All ?
                TxSerializeType.WitnessSigning :
                TxSerializeType.WitnessValueSigning
                );

            wbuf.AddRange(prefixHash);
            wbuf.AddRange(witnessHash);

            return(HashUtil.Blake256(wbuf.ToArray()));
        }
        public static Transaction TransformTransactionForSigning(Script script, Transaction transaction, int transactionInputIndex, SignatureHashType signatureType)
        {
            ContractsCommon.NotNull(script, "script");
            ContractsCommon.NotNull(transaction, "transaction");
            ContractsCommon.ValidIndex(0, transaction.TransactionInputs.Count, transactionInputIndex, "transactionInputIndex");
            ContractsCommon.ResultIsNonNull<Transaction>();

            var tb = transaction.ThawTree();

            //script.Atoms.RemoveAllCopies(Scripting.Atoms.OpCodeSeparatorAtom.Atom);

            ClearAllScripts(tb.TransactionInputs);

            tb.TransactionInputs[transactionInputIndex].Script.Atoms.AddAll(script.Atoms);

            // By default, signing a transaction with SignatureHashType = 0 means the signer
            // agrees with the transaction only if the inputs and outputs are exactly the same
            // as they were when originally signed, except input scripts, which are cleared and
            // the input script for this index set as passed above.

            switch (signatureType & SignatureHashType.OutputMask)
            {
                // Signer accepts transaction regardless of the outputs specified in the transaction
                // or the sequence numbers of the other inputs.
                case SignatureHashType.None:
                    tb.TransactionOutputs.Clear();
                    SetSequenceNumbersToZero(tb.TransactionInputs, transactionInputIndex);
                    break;
                // Signer accepts transaction if the matching outputs index of this transaction is
                // as originally signed, regarless of the sequence numbers of the other inputs.
                case SignatureHashType.Single:
                    OnlyUseSingleOutput(tb.TransactionOutputs, transactionInputIndex);
                    SetSequenceNumbersToZero(tb.TransactionInputs, transactionInputIndex);
                    break;
            }

            // Signer accepts all other inputs to this transaction, whatever they may be
            if ((signatureType & SignatureHashType.AnyoneCanPay) == SignatureHashType.AnyoneCanPay)
            {
                OnlyUseSingleInput(tb.TransactionInputs, transactionInputIndex);
            }

            tb.Freeze();

            return tb;
        }