public void TestStorage()
        {
            var temp = new FileInfo(Path.GetTempFileName());

            try
            {
                Console.WriteLine(temp.FullName);
                var         networkParams = NetworkParameters.UnitTests();
                var         to            = new EcKey().ToAddress(networkParams);
                StoredBlock b1;
                using (var store = new BoundedOverheadBlockStore(networkParams, temp))
                {
                    // Check the first block in a new store is the genesis block.
                    var genesis = store.GetChainHead();
                    Assert.AreEqual(networkParams.GenesisBlock, genesis.Header);

                    // Build a new block.
                    b1 = genesis.Build(genesis.Header.CreateNextBlock(to).CloneAsHeader());
                    store.Put(b1);
                    store.SetChainHead(b1);
                }
                // Check we can get it back out again if we rebuild the store object.
                using (var store = new BoundedOverheadBlockStore(networkParams, temp))
                {
                    var b2 = store.Get(b1.Header.Hash);
                    Assert.AreEqual(b1, b2);
                    // Check the chain head was stored correctly also.
                    Assert.AreEqual(b1, store.GetChainHead());
                }
            }
            finally
            {
                temp.Delete();
            }
        }
Example #2
0
        public static EcKey CreateEcKeyFromHexString(String privateKey)
        {
            BigInteger pkey = new BigInteger(privateKey, 16);
            EcKey      key  = new EcKey(pkey);

            return(key);
        }
Example #3
0
        public void Bounce()
        {
            // This test covers bug 64 (False double spends). Check that if we create a spend and it's immediately sent
            // back to us, this isn't considered as a double spend.
            var coin1    = Utils.ToNanoCoins(1, 0);
            var coinHalf = Utils.ToNanoCoins(0, 50);
            // Start by giving us 1 coin.
            var inbound1 = TestUtils.CreateFakeTx(_params, coin1, _myAddress);

            _wallet.Receive(inbound1, null, BlockChain.NewBlockType.BestChain);
            // Send half to some other guy. Sending only half then waiting for a confirm is important to ensure the tx is
            // in the unspent pool, not pending or spent.
            Assert.AreEqual(1, _wallet.GetPoolSize(Wallet.Pool.Unspent));
            Assert.AreEqual(1, _wallet.GetPoolSize(Wallet.Pool.All));
            var someOtherGuy = new EcKey().ToAddress(_params);
            var outbound1    = _wallet.CreateSend(someOtherGuy, coinHalf);

            _wallet.ConfirmSend(outbound1);
            _wallet.Receive(outbound1, null, BlockChain.NewBlockType.BestChain);
            // That other guy gives us the coins right back.
            var inbound2 = new Transaction(_params);

            inbound2.AddOutput(new TransactionOutput(_params, inbound2, coinHalf, _myAddress));
            inbound2.AddInput(outbound1.Outputs[0]);
            _wallet.Receive(inbound2, null, BlockChain.NewBlockType.BestChain);
            Assert.AreEqual(coin1, _wallet.GetBalance());
        }
        public void TestDoubleSpendOnFork()
        {
            // Check what happens when a re-org happens and one of our confirmed transactions becomes invalidated by a
            // double spend on the new best chain.

            var eventCalled = false;
            _wallet.DeadTransaction += (sender, e) => eventCalled = true;

            var b1 = _unitTestParams.GenesisBlock.CreateNextBlock(_coinbaseTo);
            _chain.Add(b1);

            var t1 = _wallet.CreateSend(_someOtherGuy, Utils.ToNanoCoins(10, 0));
            var yetAnotherGuy = new EcKey().ToAddress(_unitTestParams);
            var t2 = _wallet.CreateSend(yetAnotherGuy, Utils.ToNanoCoins(20, 0));
            _wallet.ConfirmSend(t1);
            // Receive t1 as confirmed by the network.
            var b2 = b1.CreateNextBlock(new EcKey().ToAddress(_unitTestParams));
            b2.AddTransaction(t1);
            b2.Solve();
            _chain.Add(b2);

            // Now we make a double spend become active after a re-org.
            var b3 = b1.CreateNextBlock(new EcKey().ToAddress(_unitTestParams));
            b3.AddTransaction(t2);
            b3.Solve();
            _chain.Add(b3); // Side chain.
            var b4 = b3.CreateNextBlock(new EcKey().ToAddress(_unitTestParams));
            _chain.Add(b4); // New best chain.

            // Should have seen a double spend.
            Assert.IsTrue(eventCalled);
            Assert.AreEqual(Utils.ToNanoCoins(30, 0), _wallet.GetBalance());
        }
Example #5
0
        public void BasicSpending()
        {
            // We'll set up a wallet that receives a coin, then sends a coin of lesser value and keeps the change.
            var v1 = Utils.ToNanoCoins(1, 0);
            var t1 = TestUtils.CreateFakeTx(_params, v1, _myAddress);

            _wallet.Receive(t1, null, BlockChain.NewBlockType.BestChain);
            Assert.AreEqual(v1, _wallet.GetBalance());
            Assert.AreEqual(1, _wallet.GetPoolSize(Wallet.Pool.Unspent));
            Assert.AreEqual(1, _wallet.GetPoolSize(Wallet.Pool.All));

            var k2 = new EcKey();
            var v2 = Utils.ToNanoCoins(0, 50);
            var t2 = _wallet.CreateSend(k2.ToAddress(_params), v2);

            Assert.AreEqual(1, _wallet.GetPoolSize(Wallet.Pool.Unspent));
            Assert.AreEqual(1, _wallet.GetPoolSize(Wallet.Pool.All));

            // Do some basic sanity checks.
            Assert.AreEqual(1, t2.Inputs.Count);
            Assert.AreEqual(_myAddress, t2.Inputs[0].ScriptSig.FromAddress);

            // We have NOT proven that the signature is correct!

            _wallet.ConfirmSend(t2);
            Assert.AreEqual(1, _wallet.GetPoolSize(Wallet.Pool.Pending));
            Assert.AreEqual(1, _wallet.GetPoolSize(Wallet.Pool.Spent));
            Assert.AreEqual(2, _wallet.GetPoolSize(Wallet.Pool.All));
        }
        public void TestForking3()
        {
            // Check that we can handle our own spends being rolled back by a fork.
            var b1 = _unitTestParams.GenesisBlock.CreateNextBlock(_coinbaseTo);

            _chain.Add(b1);
            Assert.AreEqual("50.00", Utils.BitcoinValueToFriendlyString(_wallet.GetBalance()));
            var dest  = new EcKey().ToAddress(_unitTestParams);
            var spend = _wallet.CreateSend(dest, Utils.ToNanoCoins(10, 0));

            _wallet.ConfirmSend(spend);
            // Waiting for confirmation ...
            Assert.AreEqual(0UL, _wallet.GetBalance());
            var b2 = b1.CreateNextBlock(_someOtherGuy);

            b2.AddTransaction(spend);
            b2.Solve();
            _chain.Add(b2);
            Assert.AreEqual(Utils.ToNanoCoins(40, 0), _wallet.GetBalance());
            // genesis -> b1 (receive coins) -> b2 (spend coins)
            //                               \-> b3 -> b4
            var b3 = b1.CreateNextBlock(_someOtherGuy);
            var b4 = b3.CreateNextBlock(_someOtherGuy);

            _chain.Add(b3);
            _chain.Add(b4);
            // b4 causes a re-org that should make our spend go inactive. Because the inputs are already spent our
            // available balance drops to zero again.
            Assert.AreEqual(0UL, _wallet.GetBalance(Wallet.BalanceType.Available));
            // We estimate that it'll make it back into the block chain (we know we won't double spend).
            // assertEquals(Utils.toNanoCoins(40, 0), wallet.getBalance(Wallet.BalanceType.ESTIMATED));
        }
Example #7
0
        public void TestAsn1Roundtrip()
        {
            var privKeyAsn1 = Hex.Decode("3082011302010104205c0b98e524ad188ddef35dc6abba13c34a351a05409e5d285403718b93336a4aa081a53081a2020101302c06072a8648ce3d0101022100fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f300604010004010704410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8022100fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141020101a144034200042af7a2aafe8dafd7dc7f9cfb58ce09bda7dce28653ab229b98d1d3d759660c672dd0db18c8c2d76aa470448e876fc2089ab1354c01a6e72cefc50915f4a963ee");
            var decodedKey  = EcKey.FromAsn1(privKeyAsn1);

            // Now re-encode and decode the ASN.1 to see if it is equivalent (it does not produce the exact same byte
            // sequence, some integers are padded now).
            var roundtripKey = EcKey.FromAsn1(decodedKey.ToAsn1());

            byte[] message;
            foreach (var key in new[] { decodedKey, roundtripKey })
            {
                message = Utils.ReverseBytes(Hex.Decode("11da3761e86431e4a54c176789e41f1651b324d240d599a7067bee23d328ec2a"));
                var output = key.Sign(message);
                Assert.IsTrue(key.Verify(message, output));

                output = Hex.Decode("304502206faa2ebc614bf4a0b31f0ce4ed9012eb193302ec2bcaccc7ae8bb40577f47549022100c73a1a1acc209f3f860bf9b9f5e13e9433db6f8b7bd527a088a0e0cd0a4c83e9");
                Assert.IsTrue(key.Verify(message, output));
            }

            // Try to sign with one key and verify with the other.
            message = Utils.ReverseBytes(Hex.Decode("11da3761e86431e4a54c176789e41f1651b324d240d599a7067bee23d328ec2a"));
            Assert.IsTrue(roundtripKey.Verify(message, decodedKey.Sign(message)));
            Assert.IsTrue(decodedKey.Verify(message, roundtripKey.Sign(message)));
        }
        public void TestStorage()
        {
            var temp = new FileInfo(Path.GetTempFileName());
            try
            {
                Console.WriteLine(temp.FullName);
                var @params = NetworkParameters.UnitTests();
                var to = new EcKey().ToAddress(@params);
                StoredBlock b1;
                using (var store = new BoundedOverheadBlockStore(@params, temp))
                {
                    // Check the first block in a new store is the genesis block.
                    var genesis = store.GetChainHead();
                    Assert.AreEqual(@params.GenesisBlock, genesis.Header);

                    // Build a new block.
                    b1 = genesis.Build(genesis.Header.CreateNextBlock(to).CloneAsHeader());
                    store.Put(b1);
                    store.SetChainHead(b1);
                }
                // Check we can get it back out again if we rebuild the store object.
                using (var store = new BoundedOverheadBlockStore(@params, temp))
                {
                    var b2 = store.Get(b1.Header.Hash);
                    Assert.AreEqual(b1, b2);
                    // Check the chain head was stored correctly also.
                    Assert.AreEqual(b1, store.GetChainHead());
                }
            }
            finally
            {
                temp.Delete();
            }
        }
        public void TestForking4()
        {
            // Check that we can handle external spends on an inactive chain becoming active. An external spend is where
            // we see a transaction that spends our own coins but we did not broadcast it ourselves. This happens when
            // keys are being shared between wallets.
            var b1 = _unitTestParams.GenesisBlock.CreateNextBlock(_coinbaseTo);

            _chain.Add(b1);
            Assert.AreEqual("50.00", Utils.BitcoinValueToFriendlyString(_wallet.GetBalance()));
            var dest  = new EcKey().ToAddress(_unitTestParams);
            var spend = _wallet.CreateSend(dest, Utils.ToNanoCoins(50, 0));
            // We do NOT confirm the spend here. That means it's not considered to be pending because createSend is
            // stateless. For our purposes it is as if some other program with our keys created the tx.
            //
            // genesis -> b1 (receive 50) --> b2
            //                            \-> b3 (external spend) -> b4
            var b2 = b1.CreateNextBlock(_someOtherGuy);

            _chain.Add(b2);
            var b3 = b1.CreateNextBlock(_someOtherGuy);

            b3.AddTransaction(spend);
            b3.Solve();
            _chain.Add(b3);
            // The external spend is not active yet.
            Assert.AreEqual(Utils.ToNanoCoins(50, 0), _wallet.GetBalance());
            var b4 = b3.CreateNextBlock(_someOtherGuy);

            _chain.Add(b4);
            // The external spend is now active.
            Assert.AreEqual(Utils.ToNanoCoins(0, 0), _wallet.GetBalance());
        }
Example #10
0
 public void SetUp()
 {
     var myKey = new EcKey();
     _myAddress = myKey.ToAddress(_params);
     _wallet = new Wallet(_params);
     _wallet.AddKey(myKey);
     _blockStore = new MemoryBlockStore(_params);
 }
Example #11
0
 /// <summary>
 /// Creates a scriptSig that can redeem a pay-to-address output.
 /// If given signature is null, incomplete scriptSig will be created with ScriptOpCodes.OP_0 instead of signature
 /// </summary>
 public static Script CreateInputScript(TransactionSignature signature, EcKey pubKey)
 {
     byte[] pubkeyBytes = pubKey.PublicKeyBytes;
     byte[] sigBytes    = signature != null?signature.EncodeToBitcoin() : new byte[]
     {
     };
     return(new ScriptBuilder().Data(sigBytes).Data(pubkeyBytes).Build());
 }
Example #12
0
        public static void SaveEcKey(EcKey ecKey)
        {
            byte[]     bytes = ecKey.ToAsn1();
            FileStream fs    = new FileStream(PRIV_KEY_FILENAME, FileMode.Create, FileAccess.Write);

            fs.Write(bytes, 0, bytes.Length);
            fs.Close();
        }
Example #13
0
        private static EcKey CreateRandomKey(string curve, string defaultAlgo)
        {
            var kid = new Guid().ToString("N");
            var key = new EcKey(kid, curve);

            Assert.Equal(kid, key.Kid);
            Assert.Equal(defaultAlgo, key.DefaultSignatureAlgorithm);
            return(key);
        }
Example #14
0
        public void SetUp()
        {
            var myKey = new EcKey();

            _myAddress = myKey.ToAddress(_params);
            _wallet    = new Wallet(_params);
            _wallet.AddKey(myKey);
            _blockStore = new MemoryBlockStore(_params);
        }
Example #15
0
        private static EcKey CreateKeyFromJwk(string json, string curve, string defaultAlgo, bool isPrivateKey = false)
        {
            var jwk = JsonConvert.DeserializeObject <JsonWebKey>(json);
            var kid = new Guid().ToString("N");
            var key = new EcKey(kid, curve, jwk.X, jwk.Y, isPrivateKey ? jwk.D : null);

            Assert.Equal(kid, key.Kid);
            Assert.Equal(defaultAlgo, key.DefaultSignatureAlgorithm);
            return(key);
        }
Example #16
0
 public static EcKey LoadEcKey()
 {
     using (FileStream fs = File.OpenRead(PRIV_KEY_FILENAME))
     {
         byte[] b = new byte[1024];
         fs.Read(b, 0, b.Length);
         EcKey key = EcKey.FromAsn1(b);
         return(key);
     }
 }
Example #17
0
 public void Base58EncodingStress()
 {
     // Replace the loop bound with 1000 to get some keys with leading zero byte
     for (var i = 0; i < 20; i++)
     {
         var key  = new EcKey();
         var key1 = new DumpedPrivateKey(NetworkParameters.TestNet(),
                                         key.GetPrivateKeyEncoded(NetworkParameters.TestNet()).ToString()).Key;
         Assert.AreEqual(Utils.BytesToHexString(key.GetPrivKeyBytes()),
                         Utils.BytesToHexString(key1.GetPrivKeyBytes()));
     }
 }
Example #18
0
        public IAsymmetricKeyPair CreateKeyPair(string curve)
        {
            AsymmetricCipherKeyPair keyPair = keyPairGenerator.GenerateEcKeyPair(curve);

            byte[] publicKeyContent  = GetPublicKey(keyPair.Public);
            byte[] privateKeyContent = GetPrivateKey(keyPair.Private);

            var publicKey  = new EcKey(publicKeyContent, AsymmetricKeyType.Public, GetKeyLength(keyPair.Public), curve);
            var privateKey = new EcKey(privateKeyContent, AsymmetricKeyType.Private, GetKeyLength(keyPair.Private), curve);

            return(new AsymmetricKeyPair(privateKey, publicKey));
        }
Example #19
0
 public void Base58EncodingStress()
 {
     // Replace the loop bound with 1000 to get some keys with leading zero byte
     for (var i = 0; i < 20; i++)
     {
         var key = new EcKey();
         var key1 = new DumpedPrivateKey(NetworkParameters.TestNet(),
                                         key.GetPrivateKeyEncoded(NetworkParameters.TestNet()).ToString()).Key;
         Assert.AreEqual(Utils.BytesToHexString(key.GetPrivKeyBytes()),
                         Utils.BytesToHexString(key1.GetPrivKeyBytes()));
     }
 }
Example #20
0
        public static void Run(string[] args)
        {
            // TODO: Assumes production network not testnet. Make it selectable.
            var @params = NetworkParameters.ProdNet();

            try
            {
                // Decode the private key from Satoshi's Base58 variant. If 51 characters long then it's from BitCoins
                // "dumpprivkey" command and includes a version byte and checksum. Otherwise assume it's a raw key.
                EcKey key;
                if (args[0].Length == 51)
                {
                    var dumpedPrivateKey = new DumpedPrivateKey(@params, args[0]);
                    key = dumpedPrivateKey.Key;
                }
                else
                {
                    var privKey = Base58.DecodeToBigInteger(args[0]);
                    key = new EcKey(privKey);
                }
                Console.WriteLine("Address from private key is: " + key.ToAddress(@params));
                // And the address ...
                var destination = new Address(@params, args[1]);

                // Import the private key to a fresh wallet.
                var wallet = new Wallet(@params);
                wallet.AddKey(key);

                // Find the transactions that involve those coins.
                using (var blockStore = new MemoryBlockStore(@params))
                {
                    var chain = new BlockChain(@params, wallet, blockStore);

                    var peerGroup = new PeerGroup(blockStore, @params, chain);
                    peerGroup.AddAddress(new PeerAddress(IPAddress.Loopback));
                    peerGroup.Start();
                    peerGroup.DownloadBlockChain();
                    peerGroup.Stop();

                    // And take them!
                    Console.WriteLine("Claiming " + Utils.BitcoinValueToFriendlyString(wallet.GetBalance()) + " coins");
                    wallet.SendCoins(peerGroup, destination, wallet.GetBalance());
                    // Wait a few seconds to let the packets flush out to the network (ugly).
                    Thread.Sleep(5000);
                }
            }
            catch (IndexOutOfRangeException)
            {
                Console.WriteLine("First arg should be private key in Base58 format. Second argument should be address to send to.");
            }
        }
Example #21
0
        public static void Run(string[] args)
        {
            // TODO: Assumes production network not testnet. Make it selectable.
            var networkParams = NetworkParameters.ProdNet();
            try
            {
                // Decode the private key from Satoshi's Base58 variant. If 51 characters long then it's from BitCoins
                // "dumpprivkey" command and includes a version byte and checksum. Otherwise assume it's a raw key.
                EcKey key;
                if (args[0].Length == 51)
                {
                    var dumpedPrivateKey = new DumpedPrivateKey(networkParams, args[0]);
                    key = dumpedPrivateKey.Key;
                }
                else
                {
                    var privKey = Base58.DecodeToBigInteger(args[0]);
                    key = new EcKey(privKey);
                }
                Console.WriteLine("Address from private key is: " + key.ToAddress(networkParams));
                // And the address ...
                var destination = new Address(networkParams, args[1]);

                // Import the private key to a fresh wallet.
                var wallet = new Wallet(networkParams);
                wallet.AddKey(key);

                // Find the transactions that involve those coins.
                using (var blockStore = new MemoryBlockStore(networkParams))
                {
                    var chain = new BlockChain(networkParams, wallet, blockStore);

                    var peerGroup = new PeerGroup(blockStore, networkParams, chain);
                    peerGroup.AddAddress(new PeerAddress(IPAddress.Loopback));
                    peerGroup.Start();
                    peerGroup.DownloadBlockChain();
                    peerGroup.Stop();

                    // And take them!
                    Console.WriteLine("Claiming " + Utils.BitcoinValueToFriendlystring(wallet.GetBalance()) + " coins");
                    wallet.SendCoins(peerGroup, destination, wallet.GetBalance());
                    // Wait a few seconds to let the packets flush out to the network (ugly).
                    Thread.Sleep(5000);
                }
            }
            catch (IndexOutOfRangeException)
            {
                Console.WriteLine("First arg should be private key in Base58 format. Second argument should be address to send to.");
            }
        }
Example #22
0
        public void TestSignatures()
        {
            // Test that we can construct an ECKey from a private key (deriving the public from the private), then signing
            // a message with it.
            var privkey = new BigInteger(1, Hex.Decode("180cb41c7c600be951b5d3d0a7334acc7506173875834f7a6c4c786a28fcbb19"));
            var key = new EcKey(privkey);
            var message = new byte[32]; // All zeroes.
            var output = key.Sign(message);
            Assert.True(key.Verify(message, output));

            // Test interop with a signature from elsewhere.
            var sig = Hex.Decode("3046022100dffbc26774fc841bbe1c1362fd643609c6e42dcb274763476d87af2c0597e89e022100c59e3c13b96b316cae9fa0ab0260612c7a133a6fe2b3445b6bf80b3123bf274d");
            Assert.True(key.Verify(message, sig));
        }
Example #23
0
        /// <summary>
        /// Constructor for use if the keys and SIN were derived external to this library.
        /// </summary>
        /// <param name="ecKey">An elliptical curve key.</param>
        /// <param name="clientName">The label for this client.</param>
        /// <param name="envUrl">The target server URL.</param>
        public BitPayService(EcKey ecKey, string clientName = BITPAY_PLUGIN_INFO, string envUrl = BITPAY_URL)
        {
            _ecKey      = ecKey;
            _identity   = KeyUtils.DeriveSIN(_ecKey);
            _baseUrl    = envUrl;
            _httpClient = new HttpClient
            {
                BaseAddress = new Uri(_baseUrl)
            };

            _tokenCache = new Dictionary <string, string>();
            var response = Get <List <Dictionary <string, string> > >("tokens", new Dictionary <string, string>());

            _tokenCache = response.SelectMany(t => t).ToDictionary(r => r.Key, r => r.Value);
        }
        public BitPayTest()
        {
            //            string privHexStr = "00c7a830ce41ea2f0955016b74e213da3b4ecb1fe3aaf3ea51191925f337d7f8cb";
            string privHexStr = "c7a830ce41ea2f0955016b74e213da3b4ecb1fe3aaf3ea51191925f337d7f8cb";

            byte[]     bytes = KeyUtils.hexToBytes(privHexStr);
            BigInteger pkey  = new BigInteger(privHexStr, 16);

            _ecKey = KeyUtils.createEcKeyFromHexString(privHexStr);


            string privHexStr2 = "c7a830ce41ea2f0955016b74e213da3b4ecb1fe3aaf3ea51191925f337d7f8cb";

            byte[] bytes2 = KeyUtils.hexToBytes(privHexStr2);
            _nbKey = new Key(bytes2, -1, false);
        }
Example #25
0
        public void TestSignatures()
        {
            // Test that we can construct an ECKey from a private key (deriving the public from the private), then signing
            // a message with it.
            var privkey = new BigInteger(1, Hex.Decode("180cb41c7c600be951b5d3d0a7334acc7506173875834f7a6c4c786a28fcbb19"));
            var key     = new EcKey(privkey);
            var message = new byte[32]; // All zeroes.
            var output  = key.Sign(message);

            Assert.IsTrue(key.Verify(message, output));

            // Test interop with a signature from elsewhere.
            var sig = Hex.Decode("3046022100dffbc26774fc841bbe1c1362fd643609c6e42dcb274763476d87af2c0597e89e022100c59e3c13b96b316cae9fa0ab0260612c7a133a6fe2b3445b6bf80b3123bf274d");

            Assert.IsTrue(key.Verify(message, sig));
        }
Example #26
0
        private Dictionary <string, string> _tokenCache; // {facade, token}

        /// <summary>
        /// Constructor for use if the keys and SIN are managed by this library.
        /// </summary>
        /// <param name="keyString">Private key string.</param>
        /// <param name="clientName">The label for this client.</param>
        /// <param name="envUrl">The target server URL.</param>
        public BitPayService(string keyString = "", string clientName = BITPAY_PLUGIN_INFO, string envUrl = BITPAY_URL)
        {
            if (clientName.Equals(BITPAY_PLUGIN_INFO))
            {
                clientName += " on " + Environment.MachineName;
            }
            // Eliminate special characters from the client name (used as a token label).  Trim to 60 chars.
            string _clientName = new Regex("[^a-zA-Z0-9_ ]").Replace(clientName, "_");

            if (_clientName.Length > 60)
            {
                _clientName = _clientName.Substring(0, 60);
            }

            _baseUrl    = envUrl;
            _httpClient = new HttpClient()
            {
                BaseAddress = new Uri(_baseUrl)
            };

            if (!String.IsNullOrWhiteSpace(keyString))
            {
                _ecKey = KeyUtils.CreateEcKeyFromHexString(keyString);
            }
            else
            {
                if (KeyUtils.PrivateKeyExists())
                {
                    _ecKey = KeyUtils.LoadEcKey();
                }
                else
                {
                    _ecKey = KeyUtils.CreateEcKey();
                    KeyUtils.SaveEcKey(_ecKey);
                }
            }
            _identity = KeyUtils.DeriveSIN(_ecKey);

            _tokenCache = new Dictionary <string, string>();
            var response = Get <List <Dictionary <string, string> > >("tokens", new Dictionary <string, string>());

            _tokenCache = response.SelectMany(t => t).ToDictionary(r => r.Key, r => r.Value);
        }
Example #27
0
        public static String DeriveSIN(EcKey ecKey)
        {
            String preSIN = "0F02" + BytesToHex(ecKey.PubKeyHash);

            // Convert the hex string back to binary and double sha256 hash it leaving in binary both times
            byte[] preSINbyte = HexToBytes(preSIN);
            byte[] hash2Bytes = Utils.DoubleDigest(preSINbyte);

            // Convert back to hex and take first four bytes
            String hashString  = BytesToHex(hash2Bytes);
            String first4Bytes = hashString.Substring(0, 8);

            // Append first four bytes to fully appended SIN string
            String unencoded = preSIN + first4Bytes;

            byte[] unencodedBytes = new BigInteger(unencoded, 16).ToByteArray();
            String encoded        = Base58.Encode(unencodedBytes);

            return(encoded);
        }
Example #28
0
        private static void DoSignVerifyTests(int digestSize, EcKey privateKey, EcKey publicKey)
        {
            // Create pseudo-random hash.
            var rnd    = new Random(0);
            var digest = new byte[digestSize];

            rnd.NextBytes(digest);

            bool verified;

            // Check if private key can sign digest.
            var signatureResult = privateKey.SignAsync(digest, null).Result;
            var signature       = signatureResult.Item1;
            var algorithm       = signatureResult.Item2;

            Assert.Equal(algorithm, privateKey.DefaultSignatureAlgorithm);

            // Check if private key can verify digest.
            verified = privateKey.VerifyAsync(digest, signature, algorithm).Result;
            Assert.True(verified);

            if (publicKey != null)
            {
                // Check if public key can verify digest.
                verified = publicKey.VerifyAsync(digest, signature, algorithm).Result;
                Assert.True(verified);
            }

            signature[signature.Length - 1] ^= 1;

            // Check if private key can deny invalid digest.
            verified = privateKey.VerifyAsync(digest, signature, algorithm).Result;
            Assert.False(verified);

            if (publicKey != null)
            {
                // Check if public key can deny invalid digest.
                verified = publicKey.VerifyAsync(digest, signature, algorithm).Result;
                Assert.False(verified);
            }
        }
Example #29
0
        public void Transactions()
        {
            // This test covers a bug in which Transaction.getValueSentFromMe was calculating incorrectly.
            var tx = TestUtils.CreateFakeTx(_params, Utils.ToNanoCoins(1, 0), _myAddress);
            // Now add another output (ie, change) that goes to some other address.
            var someOtherGuy = new EcKey().ToAddress(_params);
            var output       = new TransactionOutput(_params, tx, Utils.ToNanoCoins(0, 5), someOtherGuy);

            tx.AddOutput(output);
            // Note that tx is no longer valid: it spends more than it imports. However checking transactions balance
            // correctly isn't possible in SPV mode because value is a property of outputs not inputs. Without all
            // transactions you can't check they add up.
            _wallet.Receive(tx, null, BlockChain.NewBlockType.BestChain);
            // Now the other guy creates a transaction which spends that change.
            var tx2 = new Transaction(_params);

            tx2.AddInput(output);
            tx2.AddOutput(new TransactionOutput(_params, tx2, Utils.ToNanoCoins(0, 5), _myAddress));
            // tx2 doesn't send any coins from us, even though the output is in the wallet.
            Assert.AreEqual(Utils.ToNanoCoins(0, 0), tx2.GetValueSentFromMe(_wallet));
        }
Example #30
0
        public void TestDoubleSpendOnFork()
        {
            // Check what happens when a re-org happens and one of our confirmed transactions becomes invalidated by a
            // double spend on the new best chain.

            var eventCalled = false;

            _wallet.DeadTransaction += (sender, e) => eventCalled = true;

            var b1 = _unitTestParams.GenesisBlock.CreateNextBlock(_coinbaseTo);

            _chain.Add(b1);

            var t1            = _wallet.CreateSend(_someOtherGuy, Utils.ToNanoCoins(10, 0));
            var yetAnotherGuy = new EcKey().ToAddress(_unitTestParams);
            var t2            = _wallet.CreateSend(yetAnotherGuy, Utils.ToNanoCoins(20, 0));

            _wallet.ConfirmSend(t1);
            // Receive t1 as confirmed by the network.
            var b2 = b1.CreateNextBlock(new EcKey().ToAddress(_unitTestParams));

            b2.AddTransaction(t1);
            b2.Solve();
            _chain.Add(b2);

            // Now we make a double spend become active after a re-org.
            var b3 = b1.CreateNextBlock(new EcKey().ToAddress(_unitTestParams));

            b3.AddTransaction(t2);
            b3.Solve();
            _chain.Add(b3); // Side chain.
            var b4 = b3.CreateNextBlock(new EcKey().ToAddress(_unitTestParams));

            _chain.Add(b4); // New best chain.

            // Should have seen a double spend.
            Assert.IsTrue(eventCalled);
            Assert.AreEqual(Utils.ToNanoCoins(30, 0), _wallet.GetBalance());
        }
Example #31
0
        /// <summary>
        /// Creates an incomplete scriptSig that, once filled with signatures, can redeem output containing this scriptPubKey.
        /// Instead of the signatures resulting script has ScriptOpCodes.OP_0.
        /// Having incomplete input script allows to pass around partially signed tx.
        /// It is expected that this program later on will be updated with proper signatures.
        /// </summary>
        public Script CreateEmptyInputScript(EcKey key, Script redeemScript)
        {
            if (this.IsSentToAddress())
            {
                Guard.Require(key != null, "Key required to create pay-to-address input script");
                return(ScriptBuilder.CreateInputScript(null, key));
            }

            if (this.IsSentToRawPubKey())
            {
                return(ScriptBuilder.CreateInputScript(null));
            }

            if (this.IsPayToScriptHash())
            {
                throw new NotImplementedException();

                ////Guard.Require(redeemScript != null, "Redeem script required to create P2SH input script");
                ////return ScriptBuilder.CreateP2SHMultiSigInputScript(null, redeemScript);
            }

            throw new ScriptException("Do not understand script type: " + this);
        }
Example #32
0
        public static String Sign(EcKey ecKey, String input)
        {
            String hash = Sha256Hash(input);

            return(BytesToHex(ecKey.Sign(HexToBytes(hash))));
        }
Example #33
0
        public void TestBasicSpending()
        {
            // We'll set up a wallet that receives a coin, then sends a coin of lesser value and keeps the change.
            var v1 = Utils.ToNanoCoins(1, 0);
            var t1 = CreateFakeTx(v1, _myAddress);

            _wallet.Receive(t1, null, BlockChain.NewBlockType.BestChain);
            Assert.AreEqual(v1, _wallet.GetBalance());

            var k2 = new EcKey();
            var v2 = Utils.ToNanoCoins(0, 50);
            var t2 = _wallet.CreateSend(k2.ToAddress(_params), v2);

            // Do some basic sanity checks.
            Assert.AreEqual(1, t2.Inputs.Count);
            Assert.AreEqual(_myAddress, t2.Inputs[0].ScriptSig.FromAddress);

            // We have NOT proven that the signature is correct!
        }
Example #34
0
        public void TestDoubleSpendOnForkPending()
        {
            // Check what happens when a re-org happens and one of our UNconfirmed transactions becomes invalidated by a
            // double spend on the new best chain.

            Transaction eventDead        = null;
            Transaction eventReplacement = null;

            _wallet.DeadTransaction +=
                (sender, e) =>
            {
                eventDead        = e.DeadTx;
                eventReplacement = e.ReplacementTx;
            };

            // Start with 50 coins.
            var b1 = _unitTestParams.GenesisBlock.CreateNextBlock(_coinbaseTo);

            _chain.Add(b1);

            var t1            = _wallet.CreateSend(_someOtherGuy, Utils.ToNanoCoins(10, 0));
            var yetAnotherGuy = new EcKey().ToAddress(_unitTestParams);
            var t2            = _wallet.CreateSend(yetAnotherGuy, Utils.ToNanoCoins(20, 0));

            _wallet.ConfirmSend(t1);
            // t1 is still pending ...
            var b2 = b1.CreateNextBlock(new EcKey().ToAddress(_unitTestParams));

            _chain.Add(b2);
            Assert.AreEqual(Utils.ToNanoCoins(0, 0), _wallet.GetBalance());
            Assert.AreEqual(Utils.ToNanoCoins(40, 0), _wallet.GetBalance(Wallet.BalanceType.Estimated));

            // Now we make a double spend become active after a re-org.
            // genesis -> b1 -> b2 [t1 pending]
            //              \-> b3 (t2) -> b4
            var b3 = b1.CreateNextBlock(new EcKey().ToAddress(_unitTestParams));

            b3.AddTransaction(t2);
            b3.Solve();
            _chain.Add(b3); // Side chain.
            var b4 = b3.CreateNextBlock(new EcKey().ToAddress(_unitTestParams));

            _chain.Add(b4); // New best chain.

            // Should have seen a double spend against the pending pool.
            Assert.AreEqual(t1, eventDead);
            Assert.AreEqual(t2, eventReplacement);
            Assert.AreEqual(Utils.ToNanoCoins(30, 0), _wallet.GetBalance());

            // ... and back to our own parallel universe.
            var b5 = b2.CreateNextBlock(new EcKey().ToAddress(_unitTestParams));

            _chain.Add(b5);
            var b6 = b5.CreateNextBlock(new EcKey().ToAddress(_unitTestParams));

            _chain.Add(b6);
            // genesis -> b1 -> b2 -> b5 -> b6 [t1 pending]
            //              \-> b3 [t2 inactive] -> b4
            Assert.AreEqual(Utils.ToNanoCoins(0, 0), _wallet.GetBalance());
            Assert.AreEqual(Utils.ToNanoCoins(40, 0), _wallet.GetBalance(Wallet.BalanceType.Estimated));
        }
Example #35
0
 /// <summary>
 /// Creates a script that sends coins directly to the given public key. Same as
 /// <seealso cref="Script#CreateOutputScript(byte[])"/> but more type safe.
 /// </summary>
 public static byte[] CreateOutputScript(EcKey pubkey)
 {
     return(CreateOutputScript(pubkey.PubKey));
 }
        public void TestDoubleSpendOnForkPending()
        {
            // Check what happens when a re-org happens and one of our UNconfirmed transactions becomes invalidated by a
            // double spend on the new best chain.

            Transaction eventDead = null;
            Transaction eventReplacement = null;
            _wallet.DeadTransaction +=
                (sender, e) =>
                {
                    eventDead = e.DeadTx;
                    eventReplacement = e.ReplacementTx;
                };

            // Start with 50 coins.
            var b1 = _unitTestParams.GenesisBlock.CreateNextBlock(_coinbaseTo);
            _chain.Add(b1);

            var t1 = _wallet.CreateSend(_someOtherGuy, Utils.ToNanoCoins(10, 0));
            var yetAnotherGuy = new EcKey().ToAddress(_unitTestParams);
            var t2 = _wallet.CreateSend(yetAnotherGuy, Utils.ToNanoCoins(20, 0));
            _wallet.ConfirmSend(t1);
            // t1 is still pending ...
            var b2 = b1.CreateNextBlock(new EcKey().ToAddress(_unitTestParams));
            _chain.Add(b2);
            Assert.AreEqual(Utils.ToNanoCoins(0, 0), _wallet.GetBalance());
            Assert.AreEqual(Utils.ToNanoCoins(40, 0), _wallet.GetBalance(Wallet.BalanceType.Estimated));

            // Now we make a double spend become active after a re-org.
            // genesis -> b1 -> b2 [t1 pending]
            //              \-> b3 (t2) -> b4
            var b3 = b1.CreateNextBlock(new EcKey().ToAddress(_unitTestParams));
            b3.AddTransaction(t2);
            b3.Solve();
            _chain.Add(b3); // Side chain.
            var b4 = b3.CreateNextBlock(new EcKey().ToAddress(_unitTestParams));
            _chain.Add(b4); // New best chain.

            // Should have seen a double spend against the pending pool.
            Assert.AreEqual(t1, eventDead);
            Assert.AreEqual(t2, eventReplacement);
            Assert.AreEqual(Utils.ToNanoCoins(30, 0), _wallet.GetBalance());

            // ... and back to our own parallel universe.
            var b5 = b2.CreateNextBlock(new EcKey().ToAddress(_unitTestParams));
            _chain.Add(b5);
            var b6 = b5.CreateNextBlock(new EcKey().ToAddress(_unitTestParams));
            _chain.Add(b6);
            // genesis -> b1 -> b2 -> b5 -> b6 [t1 pending]
            //              \-> b3 [t2 inactive] -> b4
            Assert.AreEqual(Utils.ToNanoCoins(0, 0), _wallet.GetBalance());
            Assert.AreEqual(Utils.ToNanoCoins(40, 0), _wallet.GetBalance(Wallet.BalanceType.Estimated));
        }
Example #37
0
 /// <summary>
 /// Creates a script that sends coins directly to the given public key. Same as
 /// <seealso cref="Script#CreateOutputScript(byte[])"/> but more type safe.
 /// </summary>
 public static byte[] CreateOutputScript(EcKey pubkey)
 {
     return CreateOutputScript(pubkey.PubKey);
 }
Example #38
0
 public void Transactions()
 {
     // This test covers a bug in which Transaction.getValueSentFromMe was calculating incorrectly.
     var tx = TestUtils.CreateFakeTx(_params, Utils.ToNanoCoins(1, 0), _myAddress);
     // Now add another output (ie, change) that goes to some other address.
     var someOtherGuy = new EcKey().ToAddress(_params);
     var output = new TransactionOutput(_params, tx, Utils.ToNanoCoins(0, 5), someOtherGuy);
     tx.AddOutput(output);
     // Note that tx is no longer valid: it spends more than it imports. However checking transactions balance
     // correctly isn't possible in SPV mode because value is a property of outputs not inputs. Without all
     // transactions you can't check they add up.
     _wallet.Receive(tx, null, BlockChain.NewBlockType.BestChain);
     // Now the other guy creates a transaction which spends that change.
     var tx2 = new Transaction(_params);
     tx2.AddInput(output);
     tx2.AddOutput(new TransactionOutput(_params, tx2, Utils.ToNanoCoins(0, 5), _myAddress));
     // tx2 doesn't send any coins from us, even though the output is in the wallet.
     Assert.AreEqual(Utils.ToNanoCoins(0, 0), tx2.GetValueSentFromMe(_wallet));
 }
Example #39
0
        public TransactionSignature CalculateSignature(Transaction transaction, TransactionOutPoint outPoint, EcKey key, Script.Script redeemScript, Transaction.SigHash hashType)
        {
            // at the moment only signing all the outputs is supported
            Thrower.If(hashType != Transaction.SigHash.All).Throw <TransactionException>("Only SigHash type 'All' supported");

            //// clone the transaction and clear all the inputs
            //// only the inputs for the equivalent output needs to be present for signing
            var signTx = transaction.Clone();

            signTx.Inputs.ForEach(input => input.ScriptBytes = Enumerable.Empty <byte>().ToArray());

            // set the redeem script and clear it of 'OP_CODESEPARATOR'
            var connectedScript       = redeemScript.GetProgram();
            var redeemConnectedScript = Script.Script.RemoveAllInstancesOfOp(connectedScript, ScriptOpCodes.OP_CODESEPARATOR);

            signTx.FindInput(outPoint).ScriptBytes = redeemConnectedScript;

            // serialize then hash the transaction to HEX and sign it.
            var trxHex = this.Serializer.ToHex(signTx, hashType);
            var hash   = CryptoUtil.Sha256HashTwice(CryptoUtil.ConvertHex(trxHex));

            return(new TransactionSignature(key.Sign(hash), hashType));
        }
Example #40
0
        private static void GenerateKeyPair(EcKey ecKey)
        {
            Console.Clear();
            DrawTitle();

            if (env == Env.Test)
            {
                ecKeyFilePath = appConfig.BitPayConfiguration.EnvConfig.Test.PrivateKeyPath;
            }
            if (env == Env.Prod)
            {
                ecKeyFilePath = appConfig.BitPayConfiguration.EnvConfig.Prod.PrivateKeyPath;
            }

            if (!string.IsNullOrEmpty(ecKeyFilePath))
            {
                Console.WriteLine(" The current private key file defined is: " + ecKeyFilePath);
                Console.WriteLine(" Would you like to change it? [yes|no] (default: no)");
                Console.WriteLine();
                Console.Write(" > ");
                var answer = Console.ReadLine();
                while (answer.ToLower() != "yes" && answer.ToLower() != "no" && answer.ToLower() != "")
                {
                    answer = Console.ReadLine();
                }

                if (answer.ToLower() == "no" || answer.ToLower() == "")
                {
                    if (File.Exists(ecKeyFilePath))
                    {
                        SetNotification(" Selected private key file: " + ecKeyFilePath);

                        return;
                    }

                    SetNotification(" The private key file does not longer exists in: \n \"" + ecKeyFilePath +
                                    "\"\n Please, proceed with the following instructions.");
                    Console.Clear();
                    DrawTitle();
                }
            }

            Console.WriteLine(" Enter the full path for the private key files where this will loaded from or generated:");
            Console.WriteLine(" If click Enter, a file named \"bitpay_private_" + env.ToLower() +
                              " will be generated in the root of this application and");
            Console.WriteLine(" any file with the same name in this directory will be overwritten.");
            Console.WriteLine();
            Console.Write(" > ");
            var newEcKeyPath = Console.ReadLine().Trim();

            if (string.IsNullOrEmpty(newEcKeyPath))
            {
                ecKeyFilePath = @"bitpay_private_" + env.ToLower() + ".key";
                if (KeyUtils.PrivateKeyExists(ecKeyFilePath))
                {
                    SetNotification(" The file name entered already exists: \n \"" + ecKeyFilePath +
                                    "\"\n Make sure you want to modify it and then delete it before trying again");

                    return;
                }

                ecKey = KeyUtils.CreateEcKey();
                KeyUtils.SaveEcKey(ecKey);
                SetNotification(" New private key generated successfully with public key:\n " + ecKey.PublicKeyHexBytes +
                                "\n in: \"" + ecKeyFilePath + "\"");
            }
            else
            {
                if (!File.Exists(newEcKeyPath))
                {
                    SetNotification(" The file entered not found in: \n \"" + newEcKeyPath + "\"");
                    Console.Clear();
                    DrawTitle();
                    Console.WriteLine(" Would you like to provide a different file path? [yes|no] (default: no)");
                    Console.WriteLine(
                        " If 'no', a new file will be generated in the entered location with the given name.");
                    Console.WriteLine();
                    Console.Write(" > ");
                    var answer = Console.ReadLine();
                    while (answer.ToLower() != "yes" && answer.ToLower() != "no" && answer.ToLower() != "")
                    {
                        answer = Console.ReadLine();
                    }

                    if (answer.ToLower() == "yes")
                    {
                        GenerateKeyPair(ecKey);
                    }

                    if (KeyUtils.PrivateKeyExists(newEcKeyPath))
                    {
                        SetNotification(" The file name entered already exists: \n \"" + newEcKeyPath +
                                        "\"\n Be sure you want to modify it and then delete it manually before trying again");

                        return;
                    }
                    ecKeyFilePath = newEcKeyPath;
                }

                try
                {
                    ecKey = KeyUtils.CreateEcKey();
                    KeyUtils.SaveEcKey(ecKey);
                }
                catch (Exception e)
                {
                    SetNotification(
                        " An error occurred, please, check if the you have the right\n permissions to write in the specified directory.\n Error Details: " +
                        e.Message);

                    return;
                }

                SetNotification(" New key pair generated successfully with public key: " + ecKey.PublicKeyHexBytes +
                                " in: \n \"" + newEcKeyPath + "\"");
            }

            if (env == Env.Test)
            {
                appConfig.BitPayConfiguration.EnvConfig.Test.PrivateKeyPath = ecKeyFilePath;
            }
            if (env == Env.Prod)
            {
                appConfig.BitPayConfiguration.EnvConfig.Prod.PrivateKeyPath = ecKeyFilePath;
            }

            GenerateConfFile(confFilePath);
        }
 public void TestForking3()
 {
     // Check that we can handle our own spends being rolled back by a fork.
     var b1 = _unitTestParams.GenesisBlock.CreateNextBlock(_coinbaseTo);
     _chain.Add(b1);
     Assert.AreEqual("50.00", Utils.BitcoinValueToFriendlyString(_wallet.GetBalance()));
     var dest = new EcKey().ToAddress(_unitTestParams);
     var spend = _wallet.CreateSend(dest, Utils.ToNanoCoins(10, 0));
     _wallet.ConfirmSend(spend);
     // Waiting for confirmation ...
     Assert.AreEqual(0UL, _wallet.GetBalance());
     var b2 = b1.CreateNextBlock(_someOtherGuy);
     b2.AddTransaction(spend);
     b2.Solve();
     _chain.Add(b2);
     Assert.AreEqual(Utils.ToNanoCoins(40, 0), _wallet.GetBalance());
     // genesis -> b1 (receive coins) -> b2 (spend coins)
     //                               \-> b3 -> b4
     var b3 = b1.CreateNextBlock(_someOtherGuy);
     var b4 = b3.CreateNextBlock(_someOtherGuy);
     _chain.Add(b3);
     _chain.Add(b4);
     // b4 causes a re-org that should make our spend go inactive. Because the inputs are already spent our
     // available balance drops to zero again.
     Assert.AreEqual(0UL, _wallet.GetBalance(Wallet.BalanceType.Available));
     // We estimate that it'll make it back into the block chain (we know we won't double spend).
     // assertEquals(Utils.toNanoCoins(40, 0), wallet.getBalance(Wallet.BalanceType.ESTIMATED));
 }
 public void TestForking4()
 {
     // Check that we can handle external spends on an inactive chain becoming active. An external spend is where
     // we see a transaction that spends our own coins but we did not broadcast it ourselves. This happens when
     // keys are being shared between wallets.
     var b1 = _unitTestParams.GenesisBlock.CreateNextBlock(_coinbaseTo);
     _chain.Add(b1);
     Assert.AreEqual("50.00", Utils.BitcoinValueToFriendlyString(_wallet.GetBalance()));
     var dest = new EcKey().ToAddress(_unitTestParams);
     var spend = _wallet.CreateSend(dest, Utils.ToNanoCoins(50, 0));
     // We do NOT confirm the spend here. That means it's not considered to be pending because createSend is
     // stateless. For our purposes it is as if some other program with our keys created the tx.
     //
     // genesis -> b1 (receive 50) --> b2
     //                            \-> b3 (external spend) -> b4
     var b2 = b1.CreateNextBlock(_someOtherGuy);
     _chain.Add(b2);
     var b3 = b1.CreateNextBlock(_someOtherGuy);
     b3.AddTransaction(spend);
     b3.Solve();
     _chain.Add(b3);
     // The external spend is not active yet.
     Assert.AreEqual(Utils.ToNanoCoins(50, 0), _wallet.GetBalance());
     var b4 = b3.CreateNextBlock(_someOtherGuy);
     _chain.Add(b4);
     // The external spend is now active.
     Assert.AreEqual(Utils.ToNanoCoins(0, 0), _wallet.GetBalance());
 }
Example #43
0
 public void Bounce()
 {
     // This test covers bug 64 (False double spends). Check that if we create a spend and it's immediately sent
     // back to us, this isn't considered as a double spend.
     var coin1 = Utils.ToNanoCoins(1, 0);
     var coinHalf = Utils.ToNanoCoins(0, 50);
     // Start by giving us 1 coin.
     var inbound1 = TestUtils.CreateFakeTx(_params, coin1, _myAddress);
     _wallet.Receive(inbound1, null, BlockChain.NewBlockType.BestChain);
     // Send half to some other guy. Sending only half then waiting for a confirm is important to ensure the tx is
     // in the unspent pool, not pending or spent.
     Assert.AreEqual(1, _wallet.GetPoolSize(Wallet.Pool.Unspent));
     Assert.AreEqual(1, _wallet.GetPoolSize(Wallet.Pool.All));
     var someOtherGuy = new EcKey().ToAddress(_params);
     var outbound1 = _wallet.CreateSend(someOtherGuy, coinHalf);
     _wallet.ConfirmSend(outbound1);
     _wallet.Receive(outbound1, null, BlockChain.NewBlockType.BestChain);
     // That other guy gives us the coins right back.
     var inbound2 = new Transaction(_params);
     inbound2.AddOutput(new TransactionOutput(_params, inbound2, coinHalf, _myAddress));
     inbound2.AddInput(outbound1.Outputs[0]);
     _wallet.Receive(inbound2, null, BlockChain.NewBlockType.BestChain);
     Assert.AreEqual(coin1, _wallet.GetBalance());
 }
Example #44
0
        /// <summary>
        /// Once a transaction has some inputs and outputs added, the signatures in the inputs can be calculated. The
        /// signature is over the transaction itself, to prove the redeemer actually created that transaction,
        /// so we have to do this step last.
        /// </summary>
        /// <remarks>
        /// This method is similar to SignatureHash in script.cpp
        /// </remarks>
        /// <param name="hashType">This should always be set to SigHash.ALL currently. Other types are unused. </param>
        /// <param name="defaultWallet">A wallet is required to fetch the keys needed for signing.</param>
        /// <exception cref="ScriptException"/>
        public void SignInputs(SigHash hashType, IDefaultWallet defaultWallet)
        {
            Debug.Assert(_transactionInputs.Count > 0);
            Debug.Assert(_transactionOutputs.Count > 0);

            // I don't currently have an easy way to test other modes work, as the official client does not use them.
            Debug.Assert(hashType == SigHash.All);

            // The transaction is signed with the input scripts empty except for the input we are signing. In the case
            // where addInput has been used to set up a new transaction, they are already all empty. The input being signed
            // has to have the connected OUTPUT program in it when the hash is calculated!
            //
            // Note that each input may be claiming an output sent to a different key. So we have to look at the outputs
            // to figure out which key to sign with.

            var signatures = new byte[_transactionInputs.Count][];
            var signingKeys = new EcKey[_transactionInputs.Count];
            for (var i = 0; i < _transactionInputs.Count; i++)
            {
                var transactionInput = _transactionInputs[i];
                Debug.Assert(transactionInput.ScriptBytes.Length == 0, "Attempting to sign a non-fresh transaction");
                // Set the input to the script of its output.
                transactionInput.ScriptBytes = transactionInput.Outpoint.ConnectedPubKeyScript;
                // Find the signing key we'll need to use.
                var connectedPublicKeyHash = transactionInput.Outpoint.ConnectedPubKeyHash;
                var key = defaultWallet.FindKeyFromPublicHash(connectedPublicKeyHash);
                // This assert should never fire. If it does, it means the wallet is inconsistent.
                Debug.Assert(key != null,
                    "Transaction exists in wallet that we cannot redeem: " +
                    Utils.BytesToHexString(connectedPublicKeyHash));
                // Keep the key around for the script creation step below.
                signingKeys[i] = key;
                // The anyoneCanPay feature isn't used at the moment.
                const bool anyoneCanPay = false;
                var hash = HashTransactionForSignature(hashType, anyoneCanPay);
                // Set the script to empty again for the next input.
                transactionInput.ScriptBytes = TransactionInput.EmptyArray;

                // Now sign for the output so we can redeem it. We use the keypair to sign the hash,
                // and then put the resulting signature in the script along with the public key (below).
                using (var byteOutputStream = new MemoryStream())
                {
                    byteOutputStream.Write(key.Sign(hash));
                    byteOutputStream.Write((byte) (((int) hashType + 1) | (0)));
                    signatures[i] = byteOutputStream.ToArray();
                }
            }

            // Now we have calculated each signature, go through and create the scripts. Reminder: the script consists of
            // a signature (over a hash of the transaction) and the complete public key needed to sign for the connected
            // output.
            for (var i = 0; i < _transactionInputs.Count; i++)
            {
                var transactionInput = _transactionInputs[i];
                Debug.Assert(transactionInput.ScriptBytes.Length == 0);
                var signingKey = signingKeys[i];
                transactionInput.ScriptBytes = Script.CreateInputScript(signatures[i], signingKey.PublicKey);
            }

            // Every input is now complete.
        }