@@ -2137,8 +2137,9 @@ static RPCHelpMan lockunspent()
21372137 " If no transaction outputs are specified when unlocking then all current locked transaction outputs are unlocked.\n "
21382138 " A locked transaction output will not be chosen by automatic coin selection, when spending bitcoins.\n "
21392139 " Manually selected coins are automatically unlocked.\n "
2140- " Locks are stored in memory only. Nodes start with zero locked outputs, and the locked output list\n "
2141- " is always cleared (by virtue of process exit) when a node stops or fails.\n "
2140+ " Locks are stored in memory only, unless persistent=true, in which case they will be written to the\n "
2141+ " wallet database and loaded on node start. Unwritten (persistent=false) locks are always cleared\n "
2142+ " (by virtue of process exit) when a node stops or fails. Unlocking will clear both persistent and not.\n "
21422143 " Also see the listunspent call\n " ,
21432144 {
21442145 {" unlock" , RPCArg::Type::BOOL, RPCArg::Optional::NO, " Whether to unlock (true) or lock (false) the specified transactions" },
@@ -2152,6 +2153,7 @@ static RPCHelpMan lockunspent()
21522153 },
21532154 },
21542155 },
2156+ {" persistent" , RPCArg::Type::BOOL, RPCArg::Default{false }, " Whether to write/erase this lock in the wallet database, or keep the change in memory only. Ignored for unlocking." },
21552157 },
21562158 RPCResult{
21572159 RPCResult::Type::BOOL, " " , " Whether the command was successful or not"
@@ -2165,6 +2167,8 @@ static RPCHelpMan lockunspent()
21652167 + HelpExampleCli (" listlockunspent" , " " ) +
21662168 " \n Unlock the transaction again\n "
21672169 + HelpExampleCli (" lockunspent" , " true \" [{\\\" txid\\\" :\\\" a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\" ,\\\" vout\\\" :1}]\" " ) +
2170+ " \n Lock the transaction persistently in the wallet database\n "
2171+ + HelpExampleCli (" lockunspent" , " false \" [{\\\" txid\\\" :\\\" a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\" ,\\\" vout\\\" :1}]\" true" ) +
21682172 " \n As a JSON-RPC call\n "
21692173 + HelpExampleRpc (" lockunspent" , " false, \" [{\\\" txid\\\" :\\\" a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\" ,\\\" vout\\\" :1}]\" " )
21702174 },
@@ -2183,9 +2187,13 @@ static RPCHelpMan lockunspent()
21832187
21842188 bool fUnlock = request.params [0 ].get_bool ();
21852189
2190+ const bool persistent{request.params [2 ].isNull () ? false : request.params [2 ].get_bool ()};
2191+
21862192 if (request.params [1 ].isNull ()) {
2187- if (fUnlock )
2188- pwallet->UnlockAllCoins ();
2193+ if (fUnlock ) {
2194+ if (!pwallet->UnlockAllCoins ())
2195+ throw JSONRPCError (RPC_WALLET_ERROR, " Unlocking coins failed" );
2196+ }
21892197 return true ;
21902198 }
21912199
@@ -2236,17 +2244,24 @@ static RPCHelpMan lockunspent()
22362244 throw JSONRPCError (RPC_INVALID_PARAMETER, " Invalid parameter, expected locked output" );
22372245 }
22382246
2239- if (!fUnlock && is_locked) {
2247+ if (!fUnlock && is_locked && !persistent ) {
22402248 throw JSONRPCError (RPC_INVALID_PARAMETER, " Invalid parameter, output already locked" );
22412249 }
22422250
22432251 outputs.push_back (outpt);
22442252 }
22452253
2254+ std::unique_ptr<WalletBatch> batch = nullptr ;
2255+ // Unlock is always persistent
2256+ if (fUnlock || persistent) batch = std::make_unique<WalletBatch>(pwallet->GetDatabase ());
2257+
22462258 // Atomically set (un)locked status for the outputs.
22472259 for (const COutPoint& outpt : outputs) {
2248- if (fUnlock ) pwallet->UnlockCoin (outpt);
2249- else pwallet->LockCoin (outpt);
2260+ if (fUnlock ) {
2261+ if (!pwallet->UnlockCoin (outpt, batch.get ())) throw JSONRPCError (RPC_WALLET_ERROR, " Unlocking coin failed" );
2262+ } else {
2263+ if (!pwallet->LockCoin (outpt, batch.get ())) throw JSONRPCError (RPC_WALLET_ERROR, " Locking coin failed" );
2264+ }
22502265 }
22512266
22522267 return true ;
0 commit comments