Beispiel #1
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;
 }
Beispiel #2
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.
     _defaultWallet.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(_defaultWallet));
 }
Beispiel #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);
     _defaultWallet.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, _defaultWallet.GetPoolSize(WalletPool.Unspent));
     Assert.AreEqual(1, _defaultWallet.GetPoolSize(WalletPool.All));
     var someOtherGuy = new EcKey().ToAddress(Params);
     var outbound1 = _defaultWallet.CreateSend(someOtherGuy, coinHalf);
     _defaultWallet.ConfirmSend(outbound1);
     _defaultWallet.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.TransactionOutputs[0]);
     _defaultWallet.Receive(inbound2, null, BlockChain.NewBlockType.BestChain);
     Assert.AreEqual(coin1, _defaultWallet.GetBalance());
 }
 private static Block CreateGenesis(NetworkParameters networkParameters)
 {
     var genesisBlock = new Block(networkParameters);
     var transaction = new Transaction(networkParameters);
     // A script containing the difficulty bits and the following message:
     //   "The Times 03/Jan/2009 Chancellor on brink of second bailout for banks"
     var bytes = Hex.Decode("04ffff001d0104455468652054696d65732030332f4a616e2f32303039204368616e63656c6c6f72206f6e206272696e6b206f66207365636f6e64206261696c6f757420666f722062616e6b73");
     transaction.AddInput(new TransactionInput(networkParameters, transaction, bytes));
     using (var scriptPubKeyBytes = new MemoryStream())
     {
         Script.WriteBytes(scriptPubKeyBytes,Hex.Decode("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f"));
         scriptPubKeyBytes.Write(Script.OpCheckSig);
         transaction.AddOutput(new TransactionOutput(networkParameters, transaction, scriptPubKeyBytes.ToArray()));
     }
     genesisBlock.AddTransaction(transaction);
     return genesisBlock;
 }
Beispiel #5
0
        /// <summary>
        ///     Returns a solved block that builds on top of this one. This exists for unit tests.
        /// </summary>
        internal Block CreateNextBlock(Address toAddress, uint time)
        {
            var block = new Block(NetworkParameters) {TargetDifficulty = _targetDifficulty};
            block.AddCoinbaseTransaction(EmptyBytes);

            // Add a transaction paying 50 coins to the "to" address.
            var transaction = new Transaction(NetworkParameters);
            transaction.AddOutput(new TransactionOutput(NetworkParameters, transaction, Utils.ToNanoCoins(50, 0),
                toAddress));
            // The input does not really need to be a valid signature, as long as it has the right general form.
            var input = new TransactionInput(NetworkParameters, transaction,
                Script.CreateInputScript(EmptyBytes, EmptyBytes));
            // Importantly the outpoint hash cannot be zero as that's how we detect a coinbase transaction in isolation
            // but it must be unique to avoid 'different' transactions looking the same.
            var counter = new byte[32];
            counter[0] = (byte) _transactionCounter++;
            input.Outpoint.Hash = new Sha256Hash(counter);
            transaction.AddInput(input);
            block.AddTransaction(transaction);

            block.PreviousBlockHash = Hash;
            block.TimeSeconds = time;
            block.Solve();
            block.VerifyHeader();
            return block;
        }
Beispiel #6
0
 /// <summary>
 ///     Adds a coinbase transaction to the block. This exists for unit tests.
 /// </summary>
 internal void AddCoinbaseTransaction(byte[] pubKeyTo)
 {
     Transactions = new List<Transaction>();
     var coinbase = new Transaction(NetworkParameters);
     // A real coinbase transaction has some stuff in the scriptSig like the extraNonce and difficulty. The
     // transactions are distinguished by every TX output going to a different key.
     //
     // Here we will do things a bit differently so a new address isn't needed every time. We'll put a simple
     // counter in the scriptSig so every transaction has a different hash.
     coinbase.AddInput(new TransactionInput(NetworkParameters, coinbase, new[] {(byte) _transactionCounter++}));
     coinbase.AddOutput(new TransactionOutput(NetworkParameters, coinbase, Script.CreateOutputScript(pubKeyTo)));
     Transactions.Add(coinbase);
 }
Beispiel #7
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;
            }
        }