Example #1
0
 public void TestScriptPubKey()
 {
     // Check we can extract the to address
     var pubkeyBytes = Hex.Decode(_pubkeyProg);
     var pubkey = new Script(_params, pubkeyBytes, 0, pubkeyBytes.Length);
     var toAddr = new Address(_params, pubkey.PublicKeyHash);
     Assert.AreEqual("mkFQohBpy2HDXrCwyMrYL5RtfrmeiuuPY2", toAddr.ToString());
 }
Example #2
0
        public void TestDecoding()
        {
            var a = new Address(TestParams, "n4eA2nbYqErp7H6jebchxAN59DmNpksexv");
            Assert.AreEqual("fda79a24e50ff70ff42f7d89585da5bd19d9e5cc", Utils.BytesToHexString(a.Hash160));

            var b = new Address(ProdParams, "17kzeh4N8g49GFvdDzSf8PjaPfyoD1MndL");
            Assert.AreEqual("4a22c3c4cbb31e4d03b15550636762bda0baf85a", Utils.BytesToHexString(b.Hash160));
        }
Example #3
0
 public void TestScriptSig()
 {
     var sigProgBytes = Hex.Decode(_sigProg);
     var script = new Script(_params, sigProgBytes, 0, sigProgBytes.Length);
     // Test we can extract the from address.
     var hash160 = Utils.Sha256Hash160(script.PublicKey);
     var a = new Address(_params, hash160);
     Assert.AreEqual("mkFQohBpy2HDXrCwyMrYL5RtfrmeiuuPY2", a.ToString());
 }
Example #4
0
        public void TestStringification()
        {
            // Test a test-net address.
            var a = new Address(TestParams, Hex.Decode("fda79a24e50ff70ff42f7d89585da5bd19d9e5cc"));
            Assert.AreEqual("n4eA2nbYqErp7H6jebchxAN59DmNpksexv", a.ToString());

            var b = new Address(ProdParams, Hex.Decode("4a22c3c4cbb31e4d03b15550636762bda0baf85a"));
            Assert.AreEqual("17kzeh4N8g49GFvdDzSf8PjaPfyoD1MndL", b.ToString());
        }
Example #5
0
 public void SetUp()
 {
     _unitTestParams = NetworkParameters.UnitTests();
     _defaultWallet = new DefaultWallet(_unitTestParams);
     _defaultWallet.AddKey(new EcKey());
     _chainBlockStore = new MemoryBlockStore(_unitTestParams);
     _chain = new BlockChain(_unitTestParams, _defaultWallet, _chainBlockStore);
     _coinbaseTo = _defaultWallet.Keychain[0].ToAddress(_unitTestParams);
     _someOtherGuy = new EcKey().ToAddress(_unitTestParams);
 }
Example #6
0
 public static Transaction CreateFakeTx(NetworkParameters @params, ulong nanocoins, Address to)
 {
     var t = new Transaction(@params);
     var o1 = new TransactionOutput(@params, t, nanocoins, to);
     t.AddOutput(o1);
     // Make a previous tx simply to send us sufficient coins. This prev tx is not really valid but it doesn't
     // matter for our purposes.
     var prevTx = new Transaction(@params);
     var prevOut = new TransactionOutput(@params, prevTx, nanocoins, to);
     prevTx.AddOutput(prevOut);
     // Connect it.
     t.AddInput(prevOut);
     return t;
 }
Example #7
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 DefaultWallet(@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 #8
0
 internal static byte[] CreateOutputScript(Address toAddress)
 {
     using (var bits = new MemoryStream())
     {
         // TODO: Do this by creating a Script *first* then having the script reassemble itself into bytes.
         bits.Write(OpDup);
         bits.Write(OpHash160);
         WriteBytes(bits, toAddress.Hash160);
         bits.Write(OpEqualVerify);
         bits.Write(OpCheckSig);
         return bits.ToArray();
     }
 }
Example #9
0
        public void SetUp()
        {
            _testNetChainBlockStore = new MemoryBlockStore(_testNet);
            _testNetChain = new BlockChain(_testNet, new DefaultWallet(_testNet), _testNetChainBlockStore);
            _unitTestParams = NetworkParameters.UnitTests();
            _defaultWallet = new DefaultWallet(_unitTestParams);
            _defaultWallet.AddKey(new EcKey());

            ResetBlockStore();
            _chain = new BlockChain(_unitTestParams, _defaultWallet, _blockStore);

            _coinbaseTo = _defaultWallet.Keychain[0].ToAddress(_unitTestParams);
        }
Example #10
0
 public void SetUp()
 {
     var myKey = new EcKey();
     _myAddress = myKey.ToAddress(Params);
     _defaultWallet = new DefaultWallet(Params);
     _defaultWallet.AddKey(myKey);
     _blockStore = new MemoryBlockStore(Params);
 }
Example #11
0
 /// <summary>
 /// Sends coins to the given address, via the given <see cref="BitcoinSharp.Core.Network.Peer"/>.
 /// Change is returned to the first key in the wallet.
 /// </summary>
 /// <param name="peer">The peer to send via.</param>
 /// <param name="toAddress">Which address to send coins to.</param>
 /// <param name="nanocoins">How many nanocoins to send. You can use Utils.ToNanoCoins() to calculate this.</param>
 /// <returns>The <see cref="BitcoinSharp.Core.Messages.Transaction"/> that was created or null if there was insufficient balance to send the coins.</returns>
 /// <exception cref="System.IO.IOException">If there was a problem broadcasting the transaction.</exception>
 public Transaction SendCoins(Peer peer, Address toAddress, ulong nanocoins)
 {
     lock (this)
     {
         var transaction = CreateSend(toAddress, nanocoins);
         if (transaction == null) // Not enough money! :-(
             return null;
         peer.BroadcastTransaction(transaction);
         ConfirmSend(transaction);
         return transaction;
     }
 }
Example #12
0
        /// <summary>
        /// Sends coins to the given address, via the given <see cref="BitcoinSharp.Core.Network.PeerGroup"/>.
        /// Change is returned to the first key in the wallet.
        /// </summary>
        /// <param name="peerGroup">The peer group to send via.</param>
        /// <param name="toAddress">Which address to send coins to.</param>
        /// <param name="nanocoins">How many nanocoins to send. You can use Utils.toNanoCoins() to calculate this.</param>
        /// <returns>
        /// The <see cref="BitcoinSharp.Core.Messages.Transaction"/> that was created or null if there was insufficient balance to send the coins.
        /// </returns>
        /// <exception cref="System.IO.IOException">If there was a problem broadcasting the transaction.</exception>
        public Transaction SendCoins(PeerGroup peerGroup, Address toAddress, ulong nanocoins)
        {
            lock (this)
            {
                var transaction = CreateSend(toAddress, nanocoins);
                if (transaction == null) // Not enough money! :-(
                    return null;
                if (!peerGroup.BroadcastTransaction(transaction))
                {
                    throw new IOException("Failed to broadcast tx to all connected peers");
                }

                // TODO - retry logic
                ConfirmSend(transaction);
                return transaction;
            }
        }
Example #13
0
        /// <summary>
        /// Creates a transaction that sends $coins.$cents BTC to the given address.
        /// </summary>
        /// <remarks>
        /// IMPORTANT: This method does NOT update the wallet. If you call createSend again you may get two transactions
        /// that spend the same coins. You have to call confirmSend on the created transaction to prevent this,
        /// but that should only occur once the transaction has been accepted by the network. This implies you cannot have
        /// more than one outstanding sending tx at once.
        /// </remarks>
        /// <param name="address">The BitCoin address to send the money to.</param>
        /// <param name="nanocoins">How much currency to send, in nanocoins.</param>
        /// <param name="changeAddress">
        /// Which address to send the change to, in case we can't make exactly the right value from
        /// our coins. This should be an address we own (is in the keychain).
        /// </param>
        /// <returns>
        /// A new <see cref="BitcoinSharp.Core.Messages.Transaction"/> or null if we cannot afford this send.
        /// </returns>
        public Transaction CreateSend(Address address, ulong nanocoins, Address changeAddress)
        {
            lock (this)
            {
                Log.Info("Creating send tx to " + address + " for " +
                         Utils.BitcoinValueToFriendlyString(nanocoins));
                // To send money to somebody else, we need to do gather up transactions with unspent outputs until we have
                // sufficient value. Many coin selection algorithms are possible, we use a simple but suboptimal one.
                // TODO: Sort coins so we use the smallest first, to combat wallet fragmentation and reduce fees.
                var valueGathered = 0UL;
                var gathered = new LinkedList<TransactionOutput>();
                foreach (var transaction in Unspent.Values)
                {
                    foreach (var transactionOutput in transaction.TransactionOutputs)
                    {
                        if (!transactionOutput.IsAvailableForSpending) continue;
                        if (!transactionOutput.IsMine(this)) continue;
                        gathered.AddLast(transactionOutput);
                        valueGathered += transactionOutput.Value;
                    }
                    if (valueGathered >= nanocoins) break;
                }
                // Can we afford this?
                if (valueGathered < nanocoins)
                {
                    Log.Info("Insufficient value in wallet for send, missing " +
                             Utils.BitcoinValueToFriendlyString(nanocoins - valueGathered));
                    // TODO: Should throw an exception here.
                    return null;
                }
                Debug.Assert(gathered.Count > 0);
                var sendTransaction = new Transaction(_networkParameters);
                sendTransaction.AddOutput(new TransactionOutput(_networkParameters, sendTransaction, nanocoins, address));
                var change = (long) (valueGathered - nanocoins);
                if (change > 0)
                {
                    // The value of the inputs is greater than what we want to send. Just like in real life then,
                    // we need to take back some coins ... this is called "change". Add another output that sends the change
                    // back to us.
                    Log.Info("  with " + Utils.BitcoinValueToFriendlyString((ulong) change) + " coins change");
                    sendTransaction.AddOutput(new TransactionOutput(_networkParameters, sendTransaction, (ulong) change,
                        changeAddress));
                }
                foreach (var output in gathered)
                {
                    sendTransaction.AddInput(output);
                }

                // Now sign the inputs, thus proving that we are entitled to redeem the connected outputs.
                sendTransaction.SignInputs(Transaction.SigHash.All, this);
                Log.InfoFormat("  created {0}", sendTransaction.HashAsString);
                return sendTransaction;
            }
        }
Example #14
0
 /// <summary>
 /// Statelessly creates a transaction that sends the given number of nanocoins to address. The change is sent to
 /// the first address in the wallet, so you must have added at least one key.
 /// </summary>
 /// <remarks>
 /// This method is stateless in the sense that calling it twice with the same inputs will result in two
 /// Transaction objects which are equal. The wallet is not updated to track its pending status or to mark the
 /// coins as spent until confirmSend is called on the result.
 /// </remarks>
 public Transaction CreateSend(Address address, ulong nanocoins)
 {
     lock (this)
     {
         // For now let's just pick the first key in our keychain. In future we might want to do something else to
         // give the user better privacy here, eg in incognito mode.
         Debug.Assert(Keychain.Count > 0, "Can't send value without an address to use for receiving change");
         var first = Keychain[0];
         return CreateSend(address, nanocoins, first.ToAddress(_networkParameters));
     }
 }