示例#1
0
        public void CanCompressScript()
        {
            var key = new Key(true);

            //Pay to pubkey hash (encoded as 21 bytes)
            var script = PayToPubkeyHashTemplate.Instance.GenerateScriptPubKey(key.PubKey.Hash);

            AssertCompressed(script, 21);
            script = PayToPubkeyHashTemplate.Instance.GenerateScriptPubKey(key.PubKey.Decompress().Hash);
            AssertCompressed(script, 21);

            //Pay to script hash (encoded as 21 bytes)
            script = PayToScriptHashTemplate.Instance.GenerateScriptPubKey(script);
            AssertCompressed(script, 21);

            //Pay to pubkey starting with 0x02, 0x03 or 0x04 (encoded as 33 bytes)
            script = PayToPubkeyTemplate.Instance.GenerateScriptPubKey(key.PubKey);
            script = AssertCompressed(script, 33);
            var readenKey = PayToPubkeyTemplate.Instance.ExtractScriptPubKeyParameters(script);

            AssertEx.CollectionEquals(readenKey.ToBytes(), key.PubKey.ToBytes());

            script    = PayToPubkeyTemplate.Instance.GenerateScriptPubKey(key.PubKey.Decompress());
            script    = AssertCompressed(script, 33);
            readenKey = PayToPubkeyTemplate.Instance.ExtractScriptPubKeyParameters(script);
            AssertEx.CollectionEquals(readenKey.ToBytes(), key.PubKey.Decompress().ToBytes());


            //Other scripts up to 121 bytes require 1 byte + script length.
            script = new Script(Enumerable.Range(0, 60).Select(_ => (Op)OpcodeType.OP_RETURN).ToArray());
            AssertCompressed(script, 61);
            script = new Script(Enumerable.Range(0, 120).Select(_ => (Op)OpcodeType.OP_RETURN).ToArray());
            AssertCompressed(script, 121);

            //Above that, scripts up to 16505 bytes require 2 bytes + script length.
            script = new Script(Enumerable.Range(0, 122).Select(_ => (Op)OpcodeType.OP_RETURN).ToArray());
            AssertCompressed(script, 124);
        }
示例#2
0
        public void CanCacheNoSqlRepository()
        {
            var cached = new CachedNoSqlRepository(new InMemoryNoSqlRepository());

            byte[] data1 = new byte[] { 1, 2, 3, 4, 5, 6 };
            byte[] data2 = new byte[] { 11, 22, 33, 4, 5, 66 };
            cached.InnerRepository.Put("data1", new RawData(data1));
            Assert.NotNull(cached.Get <RawData>("data1"));
            cached.InnerRepository.Put("data1", new RawData(data2));
            cached.Flush();
            var data1Actual = cached.InnerRepository.Get <RawData>("data1");

            AssertEx.CollectionEquals(data1Actual.Data, data2);
            cached.Put("data1", new RawData(data1));

            data1Actual = cached.InnerRepository.Get <RawData>("data1");
            AssertEx.CollectionEquals(data1Actual.Data, data2);

            cached.Flush();

            data1Actual = cached.InnerRepository.Get <RawData>("data1");
            AssertEx.CollectionEquals(data1Actual.Data, data1);

            cached.Put("data1", null);
            cached.Flush();
            Assert.Null(cached.InnerRepository.Get <RawData>("data1"));

            cached.Put("data1", new RawData(data1));
            cached.Put("data1", null);
            cached.Flush();
            Assert.Null(cached.InnerRepository.Get <RawData>("data1"));

            cached.Put("data1", null);
            cached.Put("data1", new RawData(data1));
            cached.Flush();
            Assert.NotNull(cached.InnerRepository.Get <RawData>("data1"));
        }
示例#3
0
        public void EncryptedSecretECmultiplyNoLotSimple()
        {
            var compressedValues = new[] { false, true };

            foreach (bool compressed in compressedValues)
            {
                var code = new BitcoinPassphraseCode("test", Network.Main, null);
                Assert.Null(code.LotSequence);
                EncryptedKeyResult result = code.GenerateEncryptedSecret(compressed);
                Assert.True(result.ConfirmationCode.Check("test", result.GeneratedAddress));
                Assert.False(result.ConfirmationCode.Check("toto", result.GeneratedAddress));
                Assert.False(result.ConfirmationCode.Check("test", new Key().PubKey.GetAddress(Network.Main)));

                Key decryptedKey = result.EncryptedKey.GetKey("test");
                Assert.Equal(result.GeneratedAddress.ToString(), decryptedKey.PubKey.GetAddress(Network.Main).ToString());

                Assert.Throws <SecurityException>(() => result.EncryptedKey.GetKey("wrong"));

                //Can regenerate same result with same seed
                EncryptedKeyResult result2 = code.GenerateEncryptedSecret(compressed, seedb: result.Seed);
                Key decryptedKey2          = result.EncryptedKey.GetKey("test");
                AssertEx.CollectionEquals(decryptedKey2.ToBytes(), decryptedKey.ToBytes());
            }
        }
示例#4
0
        public void bloom_create_insert_serialize()
        {
            BloomFilter filter = new BloomFilter(3, 0.01, 0, BloomFlags.UPDATE_ALL);

            filter.Insert(ParseHex("99108ad8ed9bb6274d3980bab5a85c048f0950c8"));
            Assert.True(filter.Contains(ParseHex("99108ad8ed9bb6274d3980bab5a85c048f0950c8")), "BloomFilter doesn't contain just-inserted object!");
            // One bit different in first byte
            Assert.True(!filter.Contains(ParseHex("19108ad8ed9bb6274d3980bab5a85c048f0950c8")), "BloomFilter contains something it shouldn't!");

            filter.Insert(ParseHex("b5a2c786d9ef4658287ced5914b37a1b4aa32eee"));
            Assert.True(filter.Contains(ParseHex("b5a2c786d9ef4658287ced5914b37a1b4aa32eee")), "BloomFilter doesn't contain just-inserted object (2)!");

            filter.Insert(ParseHex("b9300670b4c5366e95b2699e8b18bc75e5f729c5"));
            Assert.True(filter.Contains(ParseHex("b9300670b4c5366e95b2699e8b18bc75e5f729c5")), "BloomFilter doesn't contain just-inserted object (3)!");

            var           ms            = new MemoryStream();
            BitcoinStream bitcoinStream = new BitcoinStream(ms, true);

            bitcoinStream.ReadWrite(filter);

            var expected = ParseHex("03614e9b050000000000000001");

            AssertEx.CollectionEquals(expected, ms.ToArray());
        }
示例#5
0
        public void methods()
        {
            Assert.True(R1L.GetHex() == R1L.ToString());
            Assert.True(R2L.GetHex() == R2L.ToString());
            Assert.True(OneL.GetHex() == OneL.ToString());
            Assert.True(MaxL.GetHex() == MaxL.ToString());
            uint256 TmpL = new uint256(R1L);

            Assert.True(TmpL == R1L);
            TmpL.SetHex(R2L.ToString());
            Assert.True(TmpL == R2L);
            TmpL.SetHex(ZeroL.ToString());
            Assert.True(TmpL == 0);
            TmpL.SetHex(HalfL.ToString());
            Assert.True(TmpL == HalfL);

            TmpL.SetHex(R1L.ToString());
            AssertEx.CollectionEquals(R1L.ToBytes(), R1Array);
            AssertEx.CollectionEquals(TmpL.ToBytes(), R1Array);
            AssertEx.CollectionEquals(R2L.ToBytes(), R2Array);
            AssertEx.CollectionEquals(ZeroL.ToBytes(), ZeroArray);
            AssertEx.CollectionEquals(OneL.ToBytes(), OneArray);
            Assert.True(R1L.Size == 32);
            Assert.True(R2L.Size == 32);
            Assert.True(ZeroL.Size == 32);
            Assert.True(MaxL.Size == 32);

            //No sense in .NET
            //Assert.True(R1L.begin() + 32 == R1L.end());
            //Assert.True(R2L.begin() + 32 == R2L.end());
            //Assert.True(OneL.begin() + 32 == OneL.end());
            //Assert.True(MaxL.begin() + 32 == MaxL.end());
            //Assert.True(TmpL.begin() + 32 == TmpL.end());
            Assert.True(R1L.GetLow64() == R1LLow64);
            Assert.True(HalfL.GetLow64() == 0x0000000000000000UL);
            Assert.True(OneL.GetLow64() == 0x0000000000000001UL);
            Assert.True(R1L.GetSerializeSize(0, ProtocolVersion.PROTOCOL_VERSION) == 32);
            Assert.True(ZeroL.GetSerializeSize(0, ProtocolVersion.PROTOCOL_VERSION) == 32);

            MemoryStream ss = new MemoryStream();

            R1L.Serialize(ss, 0, ProtocolVersion.PROTOCOL_VERSION);
            Assert.True(ArrayToString(ss.ToArray()) == ArrayToString(R1Array));
            TmpL.Unserialize(ss, 0, ProtocolVersion.PROTOCOL_VERSION);
            Assert.True(R1L == TmpL);
            ss = new MemoryStream();
            ZeroL.Serialize(ss, 0, ProtocolVersion.PROTOCOL_VERSION);
            Assert.True(ArrayToString(ss.ToArray()) == ArrayToString(ZeroArray));
            ss.Position = 0;
            TmpL.Unserialize(ss, 0, ProtocolVersion.PROTOCOL_VERSION);
            Assert.True(ZeroL == TmpL);
            ss = new MemoryStream();
            MaxL.Serialize(ss, 0, ProtocolVersion.PROTOCOL_VERSION);
            Assert.True(ArrayToString(ss.ToArray()) == ArrayToString(MaxArray));
            ss.Position = 0;
            TmpL.Unserialize(ss, 0, ProtocolVersion.PROTOCOL_VERSION);
            Assert.True(MaxL == TmpL);
            ss = new MemoryStream();

            Assert.True(R1S.GetHex() == R1S.ToString());
            Assert.True(R2S.GetHex() == R2S.ToString());
            Assert.True(OneS.GetHex() == OneS.ToString());
            Assert.True(MaxS.GetHex() == MaxS.ToString());
            uint160 TmpS = new uint160(R1S);

            Assert.True(TmpS == R1S);
            TmpS.SetHex(R2S.ToString());
            Assert.True(TmpS == R2S);
            TmpS.SetHex(ZeroS.ToString());
            Assert.True(TmpS == 0);
            TmpS.SetHex(HalfS.ToString());
            Assert.True(TmpS == HalfS);

            TmpS.SetHex(R1S.ToString());

            Assert.True(ArrayToString(R1S.ToBytes()) == ArrayToString(R1Array.Take(20).ToArray()));
            Assert.True(ArrayToString(TmpS.ToBytes()) == ArrayToString(R1Array.Take(20).ToArray()));
            Assert.True(ArrayToString(R2S.ToBytes()) == ArrayToString(R2Array.Take(20).ToArray()));
            Assert.True(ArrayToString(ZeroS.ToBytes()) == ArrayToString(ZeroArray.Take(20).ToArray()));
            Assert.True(ArrayToString(OneS.ToBytes()) == ArrayToString(OneArray.Take(20).ToArray()));
            Assert.True(R1S.Size == 20);
            Assert.True(R2S.Size == 20);
            Assert.True(ZeroS.Size == 20);
            Assert.True(MaxS.Size == 20);
            //No sense in .NET
            //Assert.True(R1S.begin() + 20 == R1S.end());
            //Assert.True(R2S.begin() + 20 == R2S.end());
            //Assert.True(OneS.begin() + 20 == OneS.end());
            //Assert.True(MaxS.begin() + 20 == MaxS.end());
            //Assert.True(TmpS.begin() + 20 == TmpS.end());
            Assert.True(R1S.GetLow64() == R1LLow64);
            Assert.True(HalfS.GetLow64() == 0x0000000000000000UL);
            Assert.True(OneS.GetLow64() == 0x0000000000000001UL);
            Assert.True(R1S.GetSerializeSize(0, ProtocolVersion.PROTOCOL_VERSION) == 20);
            Assert.True(ZeroS.GetSerializeSize(0, ProtocolVersion.PROTOCOL_VERSION) == 20);

            R1S.Serialize(ss, 0, ProtocolVersion.PROTOCOL_VERSION);
            Assert.True(ArrayToString(ss.ToArray()) == ArrayToString(R1Array.Take(20).ToArray()));
            ss.Position = 0;
            TmpS.Unserialize(ss, 0, ProtocolVersion.PROTOCOL_VERSION);
            Assert.True(R1S == TmpS);
            ss = new MemoryStream();
            ZeroS.Serialize(ss, 0, ProtocolVersion.PROTOCOL_VERSION);
            Assert.True(ArrayToString(ss.ToArray()) == ArrayToString(ZeroArray.Take(20).ToArray()));
            ss.Position = 0;
            TmpS.Unserialize(ss, 0, ProtocolVersion.PROTOCOL_VERSION);
            Assert.True(ZeroS == TmpS);
            ss = new MemoryStream();
            MaxS.Serialize(ss, 0, ProtocolVersion.PROTOCOL_VERSION);
            Assert.True(ArrayToString(ss.ToArray()) == ArrayToString(MaxArray.Take(20).ToArray()));
            ss.Position = 0;
            TmpS.Unserialize(ss, 0, ProtocolVersion.PROTOCOL_VERSION);
            Assert.True(MaxS == TmpS);
            ss = new MemoryStream();

            //for(int i = 0 ; i < 255 ; ++i)
            //{
            //	Assert.True((OneL << i).GetDouble() == Math.Pow(1.0, i));
            //	if(i < 160)
            //		Assert.True((OneS << i).GetDouble() == Math.Pow(1.0, i));
            //}
            //Assert.True(ZeroL.GetDouble() == 0.0);
            //Assert.True(ZeroS.GetDouble() == 0.0);
            //for(int i = 256 ; i > 53 ; --i)
            //	Assert.True(almostEqual((R1L >> (256 - i)).GetDouble(), Math.Pow(R1Ldouble, i)));
            //for(int i = 160 ; i > 53 ; --i)
            //	Assert.True(almostEqual((R1S >> (160 - i)).GetDouble(), Math.Pow(R1Sdouble, i)));
            //ulong R1L64part = (R1L >> 192).GetLow64();
            //ulong R1S64part = (R1S >> 96).GetLow64();
            //for(int i = 53 ; i > 0 ; --i) // doubles can store all integers in {0,...,2^54-1} exactly
            //{
            //	Assert.True((R1L >> (256 - i)).GetDouble() == (double)(R1L64part >> (64 - i)));
            //	Assert.True((R1S >> (160 - i)).GetDouble() == (double)(R1S64part >> (64 - i)));
            //}
        }
        public void CanCreatePayment()
        {
            var tests = new[]
            {
                new CanCreatePaymentData
                {
                    //sx stealth-newkey
                    StealthAddress = "vJmtjxSDxNPXL4RNapp9ARdqKz3uJyf1EDGjr1Fgqs9c8mYsVH82h8wvnA4i5rtJ57mr3kor1EVJrd4e5upACJd588xe52yXtzumxj",

                    ScanSecret = "3e49e7257cb31db997edb1cf8299af0f37e2663e2260e4b8033e49d39a6d02f2",
                    ScanPubKey = "025e58a31122b38c86abc119b9379fe247410aee87a533f9c07b189aef6c3c1f52",

                    SpendSecret = "aa3db0cfb3edc94de4d10f873f8190843f2a17484f6021a95a7742302c744748",
                    SpendPubKey = "03616562c98e7d7b74be409a787cec3a912122f3fb331a9bee9b0b73ce7b9f50af",

                    //sx newkey | sx wif-to-secret
                    EphemSecret = "9e63abaf8dcd5ea3919e6de0b6c544e00bf51bf92496113a01d6e369944dc091",
                    EphemPubKey = "03403d306ec35238384c7e340393335f9bc9bb4a2e574eb4e419452c4ea19f14b0",

                    //sx steatlh-uncover-secret [EphemPubKey] [ScanSecret] [SpendSecret]
                    StealthSecret = "4e422fb1e5e1db6c1f6ab32a7706d368ceb385e7fab098e633c5c5949c3b97cd",
                    //sx stealth-initiate [EphemSecret] [ScanPubKey] [SpendPubKey] (for sender)
                    //or
                    //sx stealth-uncover [EphemPubKey] [ScanSecret] [SpendPubKey]  (for receiver)
                    StealthPubKey = "02726112ad39cb6bf848b1b1ef30b88e35286bf99f746c2be575f96c0e02a9357c",
                },

                //Need padding for to find the stealth secret
                new CanCreatePaymentData {
                    StealthAddress = "vJmyTEybwCKz7W8y6vP62jo7RoyfLneiANcPLBBNYwn98EXzQRStMKqKGRiZhqscuQ6WKy2J3U3zfx72V3b2J6YvxxBcxUj4XMDsw7",
                    ScanSecret     = "2f517d81cf30e47dbf4809321275bbfd92192af81a6141a17aa53e40bd28fe36",
                    ScanPubKey     = "039d91ae0eebea6dc500fb57b704abce3d3fa700cc762a52bc5dcaee27770a8402",
                    SpendSecret    = "71e33219884fc27011f8da9adcc730f0c2e940759bdb1b615764492bce04fcea",
                    SpendPubKey    = "021a3d5b40ec83fc58b5a23207eb9c99b741d8f0e9f8b80f04f49cec915b540c40",
                    EphemSecret    = "578ffe42c0fbfb324a31f41dbbcd8b1f910ce2f4d803444a83b18ae9f8ccd97e",
                    EphemPubKey    = "03c190be0a1c6e50577b3dd637b1fff9344de31c2544ff3d815535c0515711150f",
                    StealthSecret  = "006d138b4bcef0f09c8784c0cc68f2be4497a1a822d8d7b0519c5c0378b5cb45",
                    StealthPubKey  = "0223a99278a5279ea93718503a42377067e72960eb808d8bff6defdd95d4feff76"
                }
            };

            foreach (var test in tests)
            {
                var scan    = AssertKeys(test.ScanSecret, test.ScanPubKey);
                var spend   = AssertKeys(test.SpendSecret, test.SpendPubKey);
                var ephem   = AssertKeys(test.EphemSecret, test.EphemPubKey);
                var stealth = AssertKeys(test.StealthSecret, test.StealthPubKey);

                var address = spend.PubKey.CreateStealthAddress(scan.PubKey, Network.Main);
                Assert.Equal(test.StealthAddress, address.ToString());
                //Try roundtrip
                address = new BitcoinStealthAddress(address.ToBytes(), Network.Main);
                Assert.Equal(test.StealthAddress, address.ToString());

                var payment      = address.CreatePayment(ephem);
                var generatedKey = spend.Uncover(scan, payment.Metadata.EphemKey);
                if (stealth != null)
                {
                    Assert.Equal(stealth.PubKey.Hash, payment.StealthKeys[0].ID);
                    Assert.Equal(stealth.ToBytes(), generatedKey.ToBytes());
                }
                var uncoveredSender    = spend.PubKey.UncoverSender(ephem, scan.PubKey);
                var uncovertedReceiver = spend.PubKey.UncoverReceiver(scan, ephem.PubKey);

                AssertEx.CollectionEquals(uncoveredSender.ToBytes(), uncovertedReceiver.ToBytes());
                AssertEx.CollectionEquals(generatedKey.PubKey.ToBytes(), uncovertedReceiver.ToBytes());

                var transaction = new Transaction();
                payment.AddToTransaction(transaction, 100);
            }
        }
示例#7
0
        public void CanConvertText()
        {
            string testPhrase = "é ^ç hello \"12345\"  wooorld";
            var    tests      = new[]
            {
                new
                {
                    Encoder  = Encoders.Hex,
                    Input    = testPhrase,
                    Expected = "c3a9205ec3a72068656c6c6f20223132333435222020776f6f6f726c64",
                },
                new
                {
                    Encoder  = Encoders.Base58,
                    Input    = testPhrase,
                    Expected = "9tBRc991GhmZNsV5qSyynUsnRCNvxdvvWDmj3nAP"
                },
                new
                {
                    Encoder = Encoders.Base58Check,
                    Input   = testPhrase,
                    //Different from brainwallet, because brainwallet code convert the data to bitcoin address instead of directely formating in base58check (ie : the data followed be the 4 hash bytes)
                    Expected = "2189xoVGsHC6VbVPUrKeH3fhT429VDruzdgUJFk37PNskG"
                },
                new
                {
                    Encoder  = Encoders.Base64,
                    Input    = testPhrase,
                    Expected = "w6kgXsOnIGhlbGxvICIxMjM0NSIgIHdvb29ybGQ="
                },
                //Not yet implemented
                //new
                //{
                //    Encoder = Encoders.Bin,
                //    Input = testPhrase,
                //    Expected = "11000011 10101001 00100000 01011110 11000011 10100111 00100000 01101000 01100101 01101100 01101100 01101111 00100000 00100010 00110001 00110010 00110011 00110100 00110101 00100010 00100000 00100000 01110111 01101111 01101111 01101111 01110010 01101100 01100100"
                //},
                //Not yet implemented
                //new
                //{
                //    Encoder = Encoders.Dec,
                //    Input = testPhrase,
                //    Expected = "5275000693703128425041367611933003709099386868005962673424426230508644"
                //},
                //Useless for bitcoin
                //new
                //{
                //    Encoder = Encoders.RFC1751,
                //    Input = testPhrase,
                //    Expected = "A A OWE BANG BAN BUST KITE ARK HAT SEEN OBOE GRIM KIN GASH GLOB COAT BANE DUN JO MILL SIGH SLID MAD PAR"
                //},
                //Useless for bitcoin
                //new
                //{
                //    Encoder = Encoders.Poetry,
                //    Input = testPhrase,
                //    Expected = "perfect perfect perfect soul stone royal fault companion sharp cross build leap possess possibly yet bone magic beam illuminate moonlight foul juice darkness universe"
                //},
                //Useless for bitcoin
                //new
                //{
                //    Encoder = Encoders.Rot13,
                //    Input = testPhrase,
                //    Expected = "é ^ç uryyb \"12345\"  jbbbeyq"
                //},
                //Useless for bitcoin
                //new
                //{
                //    Encoder = Encoders.Easy16,
                //    Input = testPhrase,
                //    Expected = "aaaa aauf reda houf rkda jwjh juju jnda eriu\r\nddfs fdff fgfh ddda dakk jnjn jnkd jujg euhs"
                //},
            };

            foreach (var test in tests)
            {
                byte[] input   = Encoding.UTF8.GetBytes(test.Input);
                string encoded = test.Encoder.EncodeData(input);
                Assert.Equal(test.Expected, encoded);

                try
                {
                    byte[] decoded = test.Encoder.DecodeData(encoded);
                    AssertEx.CollectionEquals(input, decoded);
                }
                catch (NotSupportedException)
                {
                }
            }

            string expectedText = "2189xoVGsHC6VbVPUrKeH3fhT429VDruzdgUJFk37PNskG";

            byte[] input1   = Encoding.UTF8.GetBytes("---é ^ç hello \"12345\"  wooorld---");
            string encoded1 = Encoders.Base58Check.EncodeData(input1, 3, input1.Length - 6);

            Assert.Equal(expectedText, encoded1);

            byte[] decoded1 = Encoders.Base58Check.DecodeData(encoded1);
            var    arr      = new byte[input1.Length - 6];

            Array.Copy(input1, 3, arr, 0, arr.Length);
            AssertEx.CollectionEquals(input1.SafeSubarray(3, input1.Length - 6), decoded1);
        }
示例#8
0
        public void ShouldPassTheLongestTestInBIP174()
        {
            JObject testcase = (JObject)testdata["final"];
            var     network  = Network.TestNet;
            var     master   = ExtKey.Parse((string)testcase["master"], network);
            var     masterFP = BitConverter.ToUInt32(master.PrivateKey.PubKey.Hash.ToBytes().SafeSubarray(0, 4), 0);
            var     tx       = network.CreateTransaction();

            tx.Version = 2;

            var scriptPubKey1 = Script.FromBytesUnsafe(Encoders.Hex.DecodeData((string)testcase["out1"]["script"]));
            var money1        = Money.Coins((decimal)testcase["out1"]["value"]);
            var scriptPubKey2 = Script.FromBytesUnsafe(Encoders.Hex.DecodeData((string)testcase["out2"]["script"]));
            var money2        = Money.Coins((decimal)testcase["out2"]["value"]);

            tx.Outputs.Add(new TxOut(value: money1, scriptPubKey: scriptPubKey1));
            tx.Outputs.Add(new TxOut(value: money2, scriptPubKey: scriptPubKey2));
            tx.Inputs.Add(new OutPoint(uint256.Parse((string)testcase["in1"]["txid"]), (uint)testcase["in1"]["index"]));
            tx.Inputs.Add(new OutPoint(uint256.Parse((string)testcase["in2"]["txid"]), (uint)testcase["in2"]["index"]));

            var expected = PSBT.Parse((string)testcase["psbt1"], Network.Main);

            var psbt = PSBT.FromTransaction(tx);

            Assert.Equal(expected, psbt, ComparerInstance);

            var prevtx1 = Transaction.Parse((string)testcase["prevtx1"], network);
            var prevtx2 = Transaction.Parse((string)testcase["prevtx2"], network);

            psbt.AddTransactions(prevtx1, prevtx2);
            var redeem1         = Script.FromBytesUnsafe(Encoders.Hex.DecodeData((string)testcase["redeem1"]));
            var redeem2         = Script.FromBytesUnsafe(Encoders.Hex.DecodeData((string)testcase["redeem2"]));
            var witness_script1 = Script.FromBytesUnsafe(Encoders.Hex.DecodeData((string)testcase["witness1"]));

            foreach (var sc in new Script[] { redeem1, redeem2, witness_script1 })
            {
                psbt.AddScript(sc);
            }

            for (int i = 0; i < 6; i++)
            {
                var pk     = testcase[$"pubkey{i}"];
                var pubkey = new PubKey((string)pk["hex"]);
                var path   = KeyPath.Parse((string)pk["path"]);
                psbt.AddKeyPath(pubkey, Tuple.Create(masterFP, path));
            }

            expected = PSBT.Parse((string)testcase["psbt2"], Network.Main);
            Assert.Equal(expected, psbt, ComparerInstance);

            foreach (var psbtin in psbt.Inputs)
            {
                psbtin.SighashType = SigHash.All;
            }
            expected = PSBT.Parse((string)testcase["psbt3"], Network.Main);
            Assert.Equal(expected, psbt, ComparerInstance);

            psbt.CheckSanity();
            var psbtForBob = psbt.Clone();

            // path 1 ... alice
            Assert.Equal(psbt, psbtForBob, ComparerInstance);
            var aliceKey1 = master.Derive(new KeyPath((string)testcase["key7"]["path"])).PrivateKey;
            var aliceKey2 = master.Derive(new KeyPath((string)testcase["key8"]["path"])).PrivateKey;

            psbt.SignAll(aliceKey1, aliceKey2);
            expected = PSBT.Parse((string)testcase["psbt4"], Network.Main);
            Assert.Equal(expected, psbt);

            // path 2 ... bob.
            var bobKey1    = master.Derive(new KeyPath((string)testcase["key9"]["path"])).PrivateKey;
            var bobKey2    = master.Derive(new KeyPath((string)testcase["key10"]["path"])).PrivateKey;
            var bobKeyhex1 = (string)testcase["key9"]["wif"];
            var bobKeyhex2 = (string)testcase["key10"]["wif"];

            Assert.Equal(bobKey1, new BitcoinSecret(bobKeyhex1, network).PrivateKey);
            Assert.Equal(bobKey2, new BitcoinSecret(bobKeyhex2, network).PrivateKey);
            psbtForBob.UseLowR = false;
            psbtForBob.SignAll(bobKey1, bobKey2);
            expected = PSBT.Parse((string)testcase["psbt5"], Network.Main);
            Assert.Equal(expected, psbtForBob);

            // merge above 2
            var combined = psbt.Combine(psbtForBob);

            expected = PSBT.Parse((string)testcase["psbtcombined"], Network.Main);
            Assert.Equal(expected, combined);

            var finalized = psbt.Finalize();

            expected = PSBT.Parse((string)testcase["psbtfinalized"], Network.Main);
            Assert.Equal(expected, finalized);

            var finalTX    = psbt.ExtractTX();
            var expectedTX = Transaction.Parse((string)testcase["txextracted"], network);

            AssertEx.CollectionEquals(expectedTX.ToBytes(), finalTX.ToBytes());
        }
示例#9
0
        public void AddingScriptCoinShouldResultMoreInfoThanAddingSeparatelyInCaseOfP2SH()
        {
            var keys    = new Key[] { new Key(), new Key(), new Key() };
            var redeem  = PayToMultiSigTemplate.Instance.GenerateScriptPubKey(3, keys.Select(k => k.PubKey).ToArray());
            var network = Network.Main;
            var funds   = CreateDummyFunds(network, keys, redeem);

            var tx   = CreateTxToSpendFunds(funds, keys, redeem, false, false);
            var psbt = PSBT.FromTransaction(tx);

            // case 1: Check that it will result to more info by adding ScriptCoin in case of p2sh-p2wpkh
            var coins1       = DummyFundsToCoins(funds, null, null);       // without script
            var scriptCoins2 = DummyFundsToCoins(funds, null, keys[0]);    // only with p2sh-p2wpkh redeem.
            var psbt1        = psbt.Clone().AddCoins(coins1).AddScript(redeem);
            var psbt2        = psbt.Clone().AddCoins(scriptCoins2).AddScript(redeem);

            for (int i = 0; i < 6; i++)
            {
                Output.WriteLine($"Testing {i}");
                var a = psbt1.Inputs[i];
                var e = psbt2.Inputs[i];
                // Since there are no way psbt can know p2sh-p2wpkh is actually a witness input in case we add coins and scripts separately,
                // coin will not be added to the inputs[4].
                if (i == 4)                 // p2sh-p2wpkh
                {
                    Assert.NotEqual(a.ToBytes(), e.ToBytes());
                    Assert.Null(a.RedeemScript);
                    Assert.Null(a.WitnessUtxo);
                    Assert.NotNull(e.RedeemScript);
                    Assert.NotNull(e.WitnessUtxo);
                }
                // but otherwise, it will be the same.
                else
                {
                    AssertEx.CollectionEquals(a.ToBytes(), e.ToBytes());
                }
            }

            // case 2: bare p2sh and p2sh-pw2sh
            var scriptCoins3 = DummyFundsToCoins(funds, redeem, keys[0]);             // with full scripts.
            var psbt3        = psbt.Clone().AddCoins(scriptCoins3);

            for (int i = 0; i < 6; i++)
            {
                Output.WriteLine($"Testing {i}");
                var a = psbt2.Inputs[i];
                var e = psbt3.Inputs[i];
                if (i == 2 || i == 5)                 // p2sh or p2sh-p2wsh
                {
                    Assert.NotEqual <byte[]>(a.ToBytes(), e.ToBytes());
                    Assert.Null(a.WitnessUtxo);
                    Assert.Null(a.RedeemScript);
                    Assert.NotNull(e.RedeemScript);
                    if (i == 5)                     // p2sh-p2wsh
                    {
                        Assert.NotNull(e.WitnessUtxo);
                        Assert.NotNull(e.WitnessScript);
                    }
                }
                else
                {
                    AssertEx.CollectionEquals(a.ToBytes(), e.ToBytes());
                }
            }
        }
示例#10
0
        public void ShouldDecodeProperly(string data, string encoded)
        {
            var testBytes = Encoders.Base58.DecodeData(encoded);

            AssertEx.CollectionEquals(Encoders.Hex.DecodeData(data), testBytes);
        }
示例#11
0
 internal static void StackEquals(ContextStack <byte[]> stack1, ContextStack <byte[]> stack2)
 {
     uint256[] hash1 = stack1.Select(o => Hashes.Hash256(o)).ToArray();
     uint256[] hash2 = stack2.Select(o => Hashes.Hash256(o)).ToArray();
     AssertEx.CollectionEquals(hash1, hash2);
 }