public SignInputs ( SigHash hashType, |
||
hashType | SigHash | This should always be set to SigHash.ALL currently. Other types are unused. |
wallet | A wallet is required to fetch the keys needed for signing. | |
return | void |
/// <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="Transaction"/> or null if we cannot afford this send. /// </returns> internal 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 tx in Unspent.Values) { foreach (var output in tx.Outputs) { if (!output.IsAvailableForSpending) continue; if (!output.IsMine(this)) continue; gathered.AddLast(output); valueGathered += output.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 sendTx = new Transaction(_params); sendTx.AddOutput(new TransactionOutput(_params, sendTx, 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"); sendTx.AddOutput(new TransactionOutput(_params, sendTx, (ulong) change, changeAddress)); } foreach (var output in gathered) { sendTx.AddInput(output); } // Now sign the inputs, thus proving that we are entitled to redeem the connected outputs. sendTx.SignInputs(Transaction.SigHash.All, this); _log.InfoFormat(" created {0}", sendTx.HashAsString); return sendTx; } }