diff --git a/core/src/main/java/org/bitcoinj/core/Wallet.java b/core/src/main/java/org/bitcoinj/core/Wallet.java index d066033b..e3e68e30 100644 --- a/core/src/main/java/org/bitcoinj/core/Wallet.java +++ b/core/src/main/java/org/bitcoinj/core/Wallet.java @@ -3708,22 +3708,6 @@ public class Wallet extends BaseTaggableObject */ public Address changeAddress = null; - /** - *

A transaction can have a fee attached, which is defined as the difference between the input values - * and output values. Any value taken in that is not provided to an output can be claimed by a miner. This - * is how mining is incentivized in later years of the Bitcoin system when inflation drops. It also provides - * a way for people to prioritize their transactions over others and is used as a way to make denial of service - * attacks expensive.

- * - *

This is a constant fee (in satoshis) which will be added to the transaction. It is recommended that it be - * at least {@link Transaction#REFERENCE_DEFAULT_MIN_TX_FEE} if it is set, as default Bitcoin Core will - * otherwise simply treat the transaction as if there were no fee at all.

- * - *

You might also consider adding a {@link SendRequest#feePerKb} to set the fee per kb of transaction size - * (rounded down to the nearest kb) as that is how transactions are sorted when added to a block by miners.

- */ - public Coin fee = null; - /** *

A transaction can have a fee attached, which is defined as the difference between the input values * and output values. Any value taken in that is not provided to an output can be claimed by a miner. This @@ -3735,8 +3719,6 @@ public class Wallet extends BaseTaggableObject * including the first. This is useful as as miners usually sort pending transactions by their fee per unit size * when choosing which transactions to add to a block. Note that, to keep this equivalent to Bitcoin Core * definition, a kilobyte is defined as 1000 bytes, not 1024.

- * - *

You might also consider using a {@link SendRequest#fee} to set the fee added for the first kb of size.

*/ public Coin feePerKb = DEFAULT_FEE_PER_KB; @@ -3752,7 +3734,7 @@ public class Wallet extends BaseTaggableObject * only set this to false if you know what you're doing.

* *

Note that this does not enforce certain fee rules that only apply to transactions which are larger than - * 26,000 bytes. If you get a transaction which is that large, you should set a fee and feePerKb of at least + * 26,000 bytes. If you get a transaction which is that large, you should set a feePerKb of at least * {@link Transaction#REFERENCE_DEFAULT_MIN_TX_FEE}.

*/ public boolean ensureMinRequiredFee = true; @@ -3885,7 +3867,6 @@ public class Wallet extends BaseTaggableObject MoreObjects.ToStringHelper helper = MoreObjects.toStringHelper(this).omitNullValues(); helper.add("emptyWallet", emptyWallet); helper.add("changeAddress", changeAddress); - helper.add("fee", fee); helper.add("feePerKb", feePerKb); helper.add("ensureMinRequiredFee", ensureMinRequiredFee); helper.add("signInputs", signInputs); @@ -4184,9 +4165,8 @@ public class Wallet extends BaseTaggableObject req.tx.addInput(output); if (req.emptyWallet) { - final Coin baseFee = req.fee == null ? Coin.ZERO : req.fee; final Coin feePerKb = req.feePerKb == null ? Coin.ZERO : req.feePerKb; - if (!adjustOutputDownwardsForFee(req.tx, bestCoinSelection, baseFee, feePerKb, req.ensureMinRequiredFee)) + if (!adjustOutputDownwardsForFee(req.tx, bestCoinSelection, feePerKb, req.ensureMinRequiredFee)) throw new CouldNotAdjustDownwards(); } @@ -4226,7 +4206,6 @@ public class Wallet extends BaseTaggableObject req.tx.setExchangeRate(req.exchangeRate); req.tx.setMemo(req.memo); req.completed = true; - req.fee = calculatedFee; log.info(" completed: {}", req.tx); } finally { lock.unlock(); @@ -4290,10 +4269,10 @@ public class Wallet extends BaseTaggableObject } /** Reduce the value of the first output of a transaction to pay the given feePerKb as appropriate for its size. */ - private boolean adjustOutputDownwardsForFee(Transaction tx, CoinSelection coinSelection, Coin baseFee, - Coin feePerKb, boolean ensureMinRequiredFee) { + private boolean adjustOutputDownwardsForFee(Transaction tx, CoinSelection coinSelection, Coin feePerKb, + boolean ensureMinRequiredFee) { final int size = tx.unsafeBitcoinSerialize().length + estimateBytesForSigning(coinSelection); - Coin fee = baseFee.add(feePerKb.multiply(size).divide(1000)); + Coin fee = feePerKb.multiply(size).divide(1000); if (ensureMinRequiredFee && fee.compareTo(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE) < 0) fee = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE; TransactionOutput output = tx.getOutput(0); @@ -5045,12 +5024,12 @@ public class Wallet extends BaseTaggableObject while (true) { resetTxInputs(req, originalInputs); - Coin fees = req.fee == null ? Coin.ZERO : req.fee; + Coin fees; if (lastCalculatedSize > 0) { // If the size is exactly 1000 bytes then we'll over-pay, but this should be rare. - fees = fees.add(req.feePerKb.multiply((lastCalculatedSize / 1000) + 1)); + fees = req.feePerKb.multiply((lastCalculatedSize / 1000) + 1); } else { - fees = fees.add(req.feePerKb); // First time around the loop. + fees = req.feePerKb; // First time around the loop. } if (needAtLeastReferenceFee && fees.compareTo(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE) < 0) fees = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE; @@ -5465,7 +5444,7 @@ public class Wallet extends BaseTaggableObject } // When not signing, don't waste addresses. rekeyTx.addOutput(toMove.valueGathered, sign ? freshReceiveAddress() : currentReceiveAddress()); - if (!adjustOutputDownwardsForFee(rekeyTx, toMove, Coin.ZERO, Transaction.REFERENCE_DEFAULT_MIN_TX_FEE, true)) { + if (!adjustOutputDownwardsForFee(rekeyTx, toMove, Transaction.REFERENCE_DEFAULT_MIN_TX_FEE, true)) { log.error("Failed to adjust rekey tx for fees."); return null; } diff --git a/core/src/test/java/org/bitcoinj/core/AbstractFullPrunedBlockChainTest.java b/core/src/test/java/org/bitcoinj/core/AbstractFullPrunedBlockChainTest.java index c3aea9be..c504ee01 100644 --- a/core/src/test/java/org/bitcoinj/core/AbstractFullPrunedBlockChainTest.java +++ b/core/src/test/java/org/bitcoinj/core/AbstractFullPrunedBlockChainTest.java @@ -333,7 +333,7 @@ public abstract class AbstractFullPrunedBlockChainTest { Wallet.SendRequest req = Wallet.SendRequest.to(address2, amount2); wallet.completeTx(req); wallet.commitTx(req.tx); - Coin fee = req.fee; + Coin fee = Coin.ZERO; // There should be one pending tx (our spend). assertEquals("Wrong number of PENDING.4", 1, wallet.getPoolSize(WalletTransaction.Pool.PENDING)); diff --git a/core/src/test/java/org/bitcoinj/core/WalletTest.java b/core/src/test/java/org/bitcoinj/core/WalletTest.java index d78f7b1b..7b80d582 100644 --- a/core/src/test/java/org/bitcoinj/core/WalletTest.java +++ b/core/src/test/java/org/bitcoinj/core/WalletTest.java @@ -214,7 +214,6 @@ public class WalletTest extends TestWithWallet { Coin v2 = valueOf(0, 50); SendRequest req = SendRequest.to(destination, v2); - req.fee = CENT; wallet.completeTx(req); Transaction t2 = req.tx; @@ -231,7 +230,7 @@ public class WalletTest extends TestWithWallet { assertEquals("Wrong number of PENDING", 2, wallet.getPoolSize(Pool.PENDING)); assertEquals("Wrong number of UNSPENT", 0, wallet.getPoolSize(Pool.UNSPENT)); assertEquals("Wrong number of ALL", 3, wallet.getTransactions(true).size()); - assertEquals(valueOf(0, 59), wallet.getBalance(Wallet.BalanceType.ESTIMATED)); + assertEquals(valueOf(0, 60), wallet.getBalance(Wallet.BalanceType.ESTIMATED)); // Now we have another incoming pending return t; @@ -250,7 +249,7 @@ public class WalletTest extends TestWithWallet { assertEquals("Wrong number of PENDING", 1, wallet.getPoolSize(WalletTransaction.Pool.PENDING)); assertEquals("Wrong number of UNSPENT", 0, wallet.getPoolSize(WalletTransaction.Pool.UNSPENT)); assertEquals("Wrong number of ALL", 2, wallet.getTransactions(true).size()); - assertEquals(valueOf(0, 49), wallet.getBalance(Wallet.BalanceType.ESTIMATED)); + assertEquals(valueOf(0, 50), wallet.getBalance(Wallet.BalanceType.ESTIMATED)); } @Test @@ -259,13 +258,12 @@ public class WalletTest extends TestWithWallet { Transaction t = cleanupCommon(destination); // Now we have another incoming pending. Spend everything. - Coin v3 = valueOf(0, 58); + Coin v3 = valueOf(0, 60); SendRequest req = SendRequest.to(destination, v3); // Force selection of the incoming coin so that we can spend it req.coinSelector = new TestCoinSelector(); - req.fee = CENT; wallet.completeTx(req); wallet.commitTx(req.tx); @@ -307,7 +305,6 @@ public class WalletTest extends TestWithWallet { // Prepare to send. Coin v2 = valueOf(0, 50); req = Wallet.SendRequest.to(destination, v2); - req.fee = CENT; if (encryptedWallet != null) { KeyCrypter keyCrypter = encryptedWallet.getKeyCrypter(); @@ -327,7 +324,6 @@ public class WalletTest extends TestWithWallet { // Try to create a send with a fee but the wrong password (this should fail). req = Wallet.SendRequest.to(destination, v2); req.aesKey = wrongAesKey; - req.fee = CENT; req.ensureMinRequiredFee = false; try { @@ -343,7 +339,6 @@ public class WalletTest extends TestWithWallet { // Create a send with a fee with the correct password (this should succeed). req = Wallet.SendRequest.to(destination, v2); req.aesKey = aesKey; - req.fee = CENT; req.ensureMinRequiredFee = false; } @@ -411,7 +406,7 @@ public class WalletTest extends TestWithWallet { assertEquals("Wrong number of tx outputs",2, t.getOutputs().size()); assertEquals(destination, t.getOutput(0).getScriptPubKey().getToAddress(PARAMS)); assertEquals(wallet.currentChangeAddress(), t.getOutputs().get(1).getScriptPubKey().getToAddress(PARAMS)); - assertEquals(valueOf(0, 49), t.getOutputs().get(1).getValue()); + assertEquals(valueOf(0, 50), t.getOutputs().get(1).getValue()); // Check the script runs and signatures verify. t.getInputs().get(0).verify(); } @@ -439,7 +434,7 @@ public class WalletTest extends TestWithWallet { private Wallet spendUnconfirmedChange(Wallet wallet, Transaction t2, KeyParameter aesKey) throws Exception { if (wallet.getTransactionSigners().size() == 1) // don't bother reconfiguring the p2sh wallet wallet = roundTrip(wallet); - Coin v3 = valueOf(0, 49); + Coin v3 = valueOf(0, 50); assertEquals(v3, wallet.getBalance()); Wallet.SendRequest req = Wallet.SendRequest.to(new ECKey().toAddress(PARAMS), valueOf(0, 48)); req.aesKey = aesKey; @@ -2362,7 +2357,7 @@ public class WalletTest extends TestWithWallet { // ...but not more fee than what we request SendRequest request3 = SendRequest.to(notMyAddr, CENT.subtract(SATOSHI)); - request3.fee = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(SATOSHI); + request3.feePerKb = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(SATOSHI); wallet.completeTx(request3); assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(SATOSHI), request3.tx.getFee()); Transaction spend3 = request3.tx; @@ -2373,7 +2368,7 @@ public class WalletTest extends TestWithWallet { // ...unless we need it SendRequest request4 = SendRequest.to(notMyAddr, CENT.subtract(SATOSHI)); - request4.fee = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.subtract(SATOSHI); + request4.feePerKb = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.subtract(SATOSHI); wallet.completeTx(request4); assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE, request4.tx.getFee()); Transaction spend4 = request4.tx; @@ -2445,7 +2440,7 @@ public class WalletTest extends TestWithWallet { SendRequest request11 = SendRequest.to(notMyAddr, COIN.subtract( Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(Transaction.MIN_NONDUST_OUTPUT).add(SATOSHI.multiply(2)))); - request11.fee = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(SATOSHI); + request11.feePerKb = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(SATOSHI); wallet.completeTx(request11); assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.add(SATOSHI), request11.tx.getFee()); Transaction spend11 = request11.tx; @@ -2887,7 +2882,6 @@ public class WalletTest extends TestWithWallet { for (int i = 0; i < 16; i++) request1.tx.addOutput(CENT, notMyAddr); request1.tx.addOutput(new TransactionOutput(PARAMS, request1.tx, CENT, new byte[16])); - request1.fee = SATOSHI; request1.feePerKb = SATOSHI; // We get a category 2 using COIN+CENT // It spends COIN + 1(fee) and because its output is thus < CENT, we have to pay MIN_TX_FEE @@ -3619,7 +3613,6 @@ public class WalletTest extends TestWithWallet { // Send 3 BTC in a single transaction SendRequest req = SendRequest.to(notMyAddr,Coin.COIN.multiply(3)); - req.fee = CENT; wallet.completeTx(req); StoredBlock block2 = createFakeBlock(blockStore, req.tx).storedBlock; wallet.receiveFromBlock(req.tx, block2, AbstractBlockChain.NewBlockType.BEST_CHAIN, 0); diff --git a/tools/src/main/java/org/bitcoinj/tools/WalletTool.java b/tools/src/main/java/org/bitcoinj/tools/WalletTool.java index 34606859..cb6874d6 100644 --- a/tools/src/main/java/org/bitcoinj/tools/WalletTool.java +++ b/tools/src/main/java/org/bitcoinj/tools/WalletTool.java @@ -219,7 +219,7 @@ public class WalletTool { xpubkeysFlag = parser.accepts("xpubkeys").withRequiredArg(); OptionSpec outputFlag = parser.accepts("output").withRequiredArg(); parser.accepts("value").withRequiredArg(); - parser.accepts("fee").withRequiredArg(); + OptionSpec feePerKbOption = parser.accepts("fee-per-kb").withRequiredArg(); unixtimeFlag = parser.accepts("unixtime").withRequiredArg().ofType(Long.class); OptionSpec conditionFlag = parser.accepts("condition").withRequiredArg(); parser.accepts("locktime").withRequiredArg(); @@ -357,16 +357,15 @@ public class WalletTool { System.err.println("--payment-request and --output cannot be used together."); return; } else if (options.has(outputFlag)) { - Coin fee = Coin.ZERO; - if (options.has("fee")) { - fee = parseCoin((String)options.valueOf("fee")); - } + Coin feePerKb = Coin.ZERO; + if (options.has(feePerKbOption)) + feePerKb = parseCoin((String) options.valueOf(feePerKbOption)); String lockTime = null; if (options.has("locktime")) { lockTime = (String) options.valueOf("locktime"); } boolean allowUnconfirmed = options.has("allow-unconfirmed"); - send(outputFlag.values(options), fee, lockTime, allowUnconfirmed); + send(outputFlag.values(options), feePerKb, lockTime, allowUnconfirmed); } else if (options.has(paymentRequestLocation)) { sendPaymentRequest(paymentRequestLocation.value(options), !options.has("no-pki")); } else { @@ -379,10 +378,9 @@ public class WalletTool { System.err.println("You must specify a --output=addr:value"); return; } - Coin fee = Coin.ZERO; - if (options.has("fee")) { - fee = parseCoin((String) options.valueOf("fee")); - } + Coin feePerKb = Coin.ZERO; + if (options.has(feePerKbOption)) + feePerKb = parseCoin((String) options.valueOf(feePerKbOption)); if (!options.has("locktime")) { System.err.println("You must specify a --locktime"); return; @@ -393,39 +391,37 @@ public class WalletTool { System.err.println("You must specify an address to refund money to after expiry: --refund-to=addr"); return; } - sendCLTVPaymentChannel(refundFlag.value(options), outputFlag.value(options), fee, lockTime, allowUnconfirmed); + sendCLTVPaymentChannel(refundFlag.value(options), outputFlag.value(options), feePerKb, lockTime, allowUnconfirmed); } break; case SETTLE_CLTVPAYMENTCHANNEL: { if (!options.has(outputFlag)) { System.err.println("You must specify a --output=addr:value"); return; } - Coin fee = Coin.ZERO; - if (options.has("fee")) { - fee = parseCoin((String) options.valueOf("fee")); - } + Coin feePerKb = Coin.ZERO; + if (options.has(feePerKbOption)) + feePerKb = parseCoin((String) options.valueOf(feePerKbOption)); boolean allowUnconfirmed = options.has("allow-unconfirmed"); if (!options.has(txHashFlag)) { System.err.println("You must specify the transaction to spend: --txhash=tx-hash"); return; } - settleCLTVPaymentChannel(txHashFlag.value(options), outputFlag.value(options), fee, allowUnconfirmed); + settleCLTVPaymentChannel(txHashFlag.value(options), outputFlag.value(options), feePerKb, allowUnconfirmed); } break; case REFUND_CLTVPAYMENTCHANNEL: { if (!options.has(outputFlag)) { System.err.println("You must specify a --output=addr:value"); return; } - Coin fee = Coin.ZERO; - if (options.has("fee")) { - fee = parseCoin((String) options.valueOf("fee")); - } + Coin feePerKb = Coin.ZERO; + if (options.has(feePerKbOption)) + feePerKb = parseCoin((String) options.valueOf(feePerKbOption)); boolean allowUnconfirmed = options.has("allow-unconfirmed"); if (!options.has(txHashFlag)) { System.err.println("You must specify the transaction to spend: --txhash=tx-hash"); return; } - refundCLTVPaymentChannel(txHashFlag.value(options), outputFlag.value(options), fee, allowUnconfirmed); + refundCLTVPaymentChannel(txHashFlag.value(options), outputFlag.value(options), feePerKb, allowUnconfirmed); } break; case ENCRYPT: encrypt(); break; case DECRYPT: decrypt(); break; @@ -569,7 +565,7 @@ public class WalletTool { } } - private static void send(List outputs, Coin fee, String lockTimeStr, boolean allowUnconfirmed) throws VerificationException { + private static void send(List outputs, Coin feePerKb, String lockTimeStr, boolean allowUnconfirmed) throws VerificationException { try { // Convert the input strings to outputs. Transaction t = new Transaction(params); @@ -600,7 +596,7 @@ public class WalletTool { log.info("Emptying out wallet, recipient may get less than what you expect"); req.emptyWallet = true; } - req.fee = fee; + req.feePerKb = feePerKb; if (allowUnconfirmed) { wallet.allowSpendingUnconfirmedTransactions(); } @@ -687,7 +683,7 @@ public class WalletTool { } } - private static void sendCLTVPaymentChannel(String refund, String output, Coin fee, String lockTimeStr, boolean allowUnconfirmed) throws VerificationException { + private static void sendCLTVPaymentChannel(String refund, String output, Coin feePerKb, String lockTimeStr, boolean allowUnconfirmed) throws VerificationException { try { // Convert the input strings to outputs. ECKey outputKey, refundKey; @@ -731,7 +727,7 @@ public class WalletTool { log.info("Emptying out wallet, recipient may get less than what you expect"); req.emptyWallet = true; } - req.fee = fee; + req.feePerKb = feePerKb; if (allowUnconfirmed) { wallet.allowSpendingUnconfirmedTransactions(); } @@ -773,12 +769,8 @@ public class WalletTool { /** * Settles a CLTV payment channel transaction given that we own both private keys (ie. for testing). - * @param txHash - * @param output - * @param fee - * @param allowUnconfirmed */ - private static void settleCLTVPaymentChannel(String txHash, String output, Coin fee, boolean allowUnconfirmed) { + private static void settleCLTVPaymentChannel(String txHash, String output, Coin feePerKb, boolean allowUnconfirmed) { try { OutputSpec outputSpec; Coin value; @@ -802,7 +794,7 @@ public class WalletTool { Wallet.SendRequest req = outputSpec.isAddress() ? Wallet.SendRequest.to(outputSpec.addr, value) : Wallet.SendRequest.to(params, outputSpec.key, value); - req.fee = fee; + req.feePerKb = feePerKb; Transaction lockTimeVerify = wallet.getTransaction(Sha256Hash.wrap(txHash)); if (lockTimeVerify == null) { @@ -820,7 +812,7 @@ public class WalletTool { return; } - if (!req.fee.add(value).equals(lockTimeVerifyOutput.getValue())) { + if (!value.equals(lockTimeVerifyOutput.getValue())) { System.err.println("You must spend all the money in the input transaction"); } @@ -880,12 +872,8 @@ public class WalletTool { /** * Refunds a CLTV payment channel transaction after the lock time has expired. - * @param txHash - * @param output - * @param fee - * @param allowUnconfirmed */ - private static void refundCLTVPaymentChannel(String txHash, String output, Coin fee, boolean allowUnconfirmed) { + private static void refundCLTVPaymentChannel(String txHash, String output, Coin feePerKb, boolean allowUnconfirmed) { try { OutputSpec outputSpec; Coin value; @@ -909,7 +897,7 @@ public class WalletTool { Wallet.SendRequest req = outputSpec.isAddress() ? Wallet.SendRequest.to(outputSpec.addr, value) : Wallet.SendRequest.to(params, outputSpec.key, value); - req.fee = fee; + req.feePerKb = feePerKb; Transaction lockTimeVerify = wallet.getTransaction(Sha256Hash.wrap(txHash)); if (lockTimeVerify == null) { @@ -929,7 +917,7 @@ public class WalletTool { req.tx.setLockTime(lockTimeVerifyOutput.getScriptPubKey().getCLTVPaymentChannelExpiry().longValue()); - if (!req.fee.add(value).equals(lockTimeVerifyOutput.getValue())) { + if (!value.equals(lockTimeVerifyOutput.getValue())) { System.err.println("You must spend all the money in the input transaction"); } diff --git a/tools/src/main/resources/org/bitcoinj/tools/wallet-tool-help.txt b/tools/src/main/resources/org/bitcoinj/tools/wallet-tool-help.txt index 703e3d20..430c1edc 100644 --- a/tools/src/main/resources/org/bitcoinj/tools/wallet-tool-help.txt +++ b/tools/src/main/resources/org/bitcoinj/tools/wallet-tool-help.txt @@ -48,7 +48,7 @@ Usage: wallet-tool --flags action-name --payment-request=http://merchant.com/pay.php?123 Other options include: - --fee=0.01 sets the tx fee + --fee-per-kb=0.0005 sets the tx fee --locktime=1234 sets the lock time to block 1234 --locktime=2013/01/01 sets the lock time to 1st Jan 2013 --allow-unconfirmed will let you create spends of pending non-change outputs. @@ -72,14 +72,14 @@ Usage: wallet-tool --flags action-name Options: --output=pubkey:value sets the amount to lock and the recipient --refund-to=pubkey sets "our" public key - --fee=value sets the mining fee + --fee-per-kb=value sets the network fee --locktime=YYYY/MM/DD sets the expiry time for the channel settle-cltvpaymentchannel Creates and broadcasts a transaction settling a previous micropayment channel. This tool, for testing, requires the presence of both private keys. Options: --output=pubkey:value sets the destination for the money - --fee=value sets the mining fee + --fee-per-kb=value sets the network fee --txhash=hash sets the transaction to spend refund-cltvpaymentchannel Creates and broadcasts a transaction refunding a previous micropayment channel. @@ -87,7 +87,7 @@ Usage: wallet-tool --flags action-name the created transaction won't be accepted into the mempool until that point. Options: --output=pubkey:value sets the destination for the money - --fee=value sets the mining fee + --fee-per-kb=value sets the network fee --txhash=hash sets the transaction to spend >>> GENERAL OPTIONS