Skip to content

Commit 4bc0858

Browse files
committed
rpc: use anti-fee-sniping in sendall
1 parent 642e4b6 commit 4bc0858

File tree

3 files changed

+24
-3
lines changed

3 files changed

+24
-3
lines changed

src/wallet/rpc/spend.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1377,7 +1377,7 @@ RPCHelpMan sendall()
13771377
},
13781378
},
13791379
},
1380-
{"locktime", RPCArg::Type::NUM, RPCArg::Default{0}, "Raw locktime. Non-0 value also locktime-activates inputs"},
1380+
{"locktime", RPCArg::Type::NUM, RPCArg::DefaultHint{"Approximately the current height"}, "Raw locktime. Non-0 value also locktime-activates inputs"},
13811381
{"lock_unspents", RPCArg::Type::BOOL, RPCArg::Default{false}, "Lock selected unspent outputs"},
13821382
{"psbt", RPCArg::Type::BOOL, RPCArg::DefaultHint{"automatic"}, "Always return a PSBT, implies add_to_wallet=false."},
13831383
{"send_max", RPCArg::Type::BOOL, RPCArg::Default{false}, "When true, only use UTXOs that can pay for their own fees to maximize the output amount. When 'false' (default), no UTXO is left behind. send_max is incompatible with providing specific inputs."},
@@ -1508,12 +1508,21 @@ RPCHelpMan sendall()
15081508
if (send_max && fee_rate.GetFee(output.input_bytes) > output.txout.nValue) {
15091509
continue;
15101510
}
1511-
CTxIn input(output.outpoint.hash, output.outpoint.n, CScript(), rbf ? MAX_BIP125_RBF_SEQUENCE : CTxIn::SEQUENCE_FINAL);
1511+
CTxIn input(output.outpoint.hash, output.outpoint.n, CScript(), rbf ? MAX_BIP125_RBF_SEQUENCE : CTxIn::MAX_SEQUENCE_NONFINAL);
15121512
rawTx.vin.push_back(input);
15131513
total_input_value += output.txout.nValue;
15141514
}
15151515
}
15161516

1517+
if (!options["locktime"].isNull()) {
1518+
coin_control.m_locktime = options["locktime"].getInt<int>();
1519+
coin_control.m_use_anti_fee_sniping = false;
1520+
}
1521+
1522+
if (rawTx.vin.size()) {
1523+
MaybeDiscourageFeeSniping(*pwallet, rawTx, coin_control);
1524+
}
1525+
15171526
std::vector<COutPoint> outpoints_spent;
15181527
outpoints_spent.reserve(rawTx.vin.size());
15191528

test/functional/wallet_create_tx.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,12 @@ def test_anti_fee_sniping(self):
5252
tx = self.nodes[0].gettransaction(txid=res['txid'], verbose=True)['decoded']
5353
assert_equal(tx['locktime'], 0)
5454

55+
# sendall RPC (don't actually empty the wallet)
56+
res = self.nodes[0].sendall(recipients=[self.nodes[0].getnewaddress()], add_to_wallet=False)
57+
assert(res["complete"])
58+
tx = self.nodes[0].decoderawtransaction(res['hex'])
59+
assert_equal(tx['locktime'], 0)
60+
5561
self.log.info('Check that anti-fee-sniping is enabled when we mine a recent block')
5662
self.generate(self.nodes[0], 1)
5763
txid = self.nodes[0].sendtoaddress(self.nodes[0].getnewaddress(), 1)
@@ -65,6 +71,12 @@ def test_anti_fee_sniping(self):
6571
tx = self.nodes[0].gettransaction(txid=res['txid'], verbose=True)['decoded']
6672
assert 0 < tx['locktime'] <= 201
6773

74+
# sendall RPC
75+
res = self.nodes[0].sendall(recipients=[self.nodes[0].getnewaddress()], add_to_wallet=False)
76+
assert(res["complete"])
77+
tx = self.nodes[0].decoderawtransaction(res['hex'])
78+
assert 0 < tx['locktime'] <= 201
79+
6880
def test_tx_size_too_large(self):
6981
# More than 10kB of outputs, so that we hit -maxtxfee with a high feerate
7082
outputs = {self.nodes[0].getnewaddress(address_type='bech32'): 0.000025 for _ in range(400)}

test/functional/wallet_rescan_unconfirmed.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ def run_test(self):
5353
# The only UTXO available to spend is tx_parent_to_reorg.
5454
assert_equal(len(w0_utxos), 1)
5555
assert_equal(w0_utxos[0]["txid"], tx_parent_to_reorg["txid"])
56-
tx_child_unconfirmed_sweep = w0.sendall([ADDRESS_BCRT1_UNSPENDABLE])
56+
tx_child_unconfirmed_sweep = w0.sendall([ADDRESS_BCRT1_UNSPENDABLE], locktime=0)
5757
assert tx_child_unconfirmed_sweep["txid"] in node.getrawmempool()
5858
node.syncwithvalidationinterfacequeue()
5959

0 commit comments

Comments
 (0)