[rpc] fundrawtransaction, walletcreatefundedpsbt lock manually selected coins
Previously only automatically selected coins were locked when lockUnspents is set. It now also locks selected coins.
This commit is contained in:
5 files changed
+32
-6
No files matched your search
@@ -0,0 +1,7 @@
|
|||||||
|
Updated RPCs
|
||||||
|
------------
|
||||||
|
|
||||||
|
- `fundrawtransaction` and `walletcreatefundedpsbt` when used with the `lockUnspents`
|
||||||
|
argument now lock manually selected coins, in addition to automatically selected
|
||||||
|
coins. Note that locked coins are never used in automatic coin selection, but
|
||||||
|
can still be manually selected.
|
||||||
@@ -2047,6 +2047,7 @@ static UniValue lockunspent(const JSONRPCRequest& request)
|
|||||||
"Temporarily lock (unlock=false) or unlock (unlock=true) specified transaction outputs.\n"
|
"Temporarily lock (unlock=false) or unlock (unlock=true) specified transaction outputs.\n"
|
||||||
"If no transaction outputs are specified when unlocking then all current locked transaction outputs are unlocked.\n"
|
"If no transaction outputs are specified when unlocking then all current locked transaction outputs are unlocked.\n"
|
||||||
"A locked transaction output will not be chosen by automatic coin selection, when spending bitcoins.\n"
|
"A locked transaction output will not be chosen by automatic coin selection, when spending bitcoins.\n"
|
||||||
|
"Manually selected coins are automatically unlocked.\n"
|
||||||
"Locks are stored in memory only. Nodes start with zero locked outputs, and the locked output list\n"
|
"Locks are stored in memory only. Nodes start with zero locked outputs, and the locked output list\n"
|
||||||
"is always cleared (by virtue of process exit) when a node stops or fails.\n"
|
"is always cleared (by virtue of process exit) when a node stops or fails.\n"
|
||||||
"Also see the listunspent call\n",
|
"Also see the listunspent call\n",
|
||||||
|
|||||||
@@ -2609,10 +2609,11 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nC
|
|||||||
if (!coinControl.IsSelected(txin.prevout)) {
|
if (!coinControl.IsSelected(txin.prevout)) {
|
||||||
tx.vin.push_back(txin);
|
tx.vin.push_back(txin);
|
||||||
|
|
||||||
if (lockUnspents) {
|
|
||||||
LockCoin(txin.prevout);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (lockUnspents) {
|
||||||
|
LockCoin(txin.prevout);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -103,7 +103,16 @@ class PSBTTest(BitcoinTestFramework):
|
|||||||
final_tx = self.nodes[0].finalizepsbt(signed_tx)['hex']
|
final_tx = self.nodes[0].finalizepsbt(signed_tx)['hex']
|
||||||
self.nodes[0].sendrawtransaction(final_tx)
|
self.nodes[0].sendrawtransaction(final_tx)
|
||||||
|
|
||||||
# Get pubkeys
|
# Manually selected inputs can be locked:
|
||||||
|
assert_equal(len(self.nodes[0].listlockunspent()), 0)
|
||||||
|
utxo1 = self.nodes[0].listunspent()[0]
|
||||||
|
psbtx1 = self.nodes[0].walletcreatefundedpsbt([{"txid": utxo1['txid'], "vout": utxo1['vout']}], {self.nodes[2].getnewaddress():1}, 0,{"lockUnspents": True})["psbt"]
|
||||||
|
assert_equal(len(self.nodes[0].listlockunspent()), 1)
|
||||||
|
|
||||||
|
# Locks are ignored for manually selected inputs
|
||||||
|
self.nodes[0].walletcreatefundedpsbt([{"txid": utxo1['txid'], "vout": utxo1['vout']}], {self.nodes[2].getnewaddress():1}, 0)
|
||||||
|
|
||||||
|
# Create p2sh, p2wpkh, and p2wsh addresses
|
||||||
pubkey0 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress())['pubkey']
|
pubkey0 = self.nodes[0].getaddressinfo(self.nodes[0].getnewaddress())['pubkey']
|
||||||
pubkey1 = self.nodes[1].getaddressinfo(self.nodes[1].getnewaddress())['pubkey']
|
pubkey1 = self.nodes[1].getaddressinfo(self.nodes[1].getnewaddress())['pubkey']
|
||||||
pubkey2 = self.nodes[2].getaddressinfo(self.nodes[2].getnewaddress())['pubkey']
|
pubkey2 = self.nodes[2].getaddressinfo(self.nodes[2].getnewaddress())['pubkey']
|
||||||
|
|||||||
@@ -136,11 +136,19 @@ class WalletTest(BitcoinTestFramework):
|
|||||||
self.nodes[2].lockunspent, False,
|
self.nodes[2].lockunspent, False,
|
||||||
[{"txid": unspent_0["txid"], "vout": 999}])
|
[{"txid": unspent_0["txid"], "vout": 999}])
|
||||||
|
|
||||||
# An output should be unlocked when spent
|
# The lock on a manually selected output is ignored
|
||||||
unspent_0 = self.nodes[1].listunspent()[0]
|
unspent_0 = self.nodes[1].listunspent()[0]
|
||||||
self.nodes[1].lockunspent(False, [unspent_0])
|
self.nodes[1].lockunspent(False, [unspent_0])
|
||||||
tx = self.nodes[1].createrawtransaction([unspent_0], { self.nodes[1].getnewaddress() : 1 })
|
tx = self.nodes[1].createrawtransaction([unspent_0], { self.nodes[1].getnewaddress() : 1 })
|
||||||
tx = self.nodes[1].fundrawtransaction(tx)['hex']
|
self.nodes[1].fundrawtransaction(tx,{"lockUnspents": True})
|
||||||
|
|
||||||
|
# fundrawtransaction can lock an input
|
||||||
|
self.nodes[1].lockunspent(True, [unspent_0])
|
||||||
|
assert_equal(len(self.nodes[1].listlockunspent()), 0)
|
||||||
|
tx = self.nodes[1].fundrawtransaction(tx,{"lockUnspents": True})['hex']
|
||||||
|
assert_equal(len(self.nodes[1].listlockunspent()), 1)
|
||||||
|
|
||||||
|
# Send transaction
|
||||||
tx = self.nodes[1].signrawtransactionwithwallet(tx)["hex"]
|
tx = self.nodes[1].signrawtransactionwithwallet(tx)["hex"]
|
||||||
self.nodes[1].sendrawtransaction(tx)
|
self.nodes[1].sendrawtransaction(tx)
|
||||||
assert_equal(len(self.nodes[1].listlockunspent()), 0)
|
assert_equal(len(self.nodes[1].listlockunspent()), 0)
|
||||||
|
|||||||
Reference in new issue
Block a user