@@ -2137,8 +2137,9 @@ static RPCHelpMan lockunspent()
2137
2137
" If no transaction outputs are specified when unlocking then all current locked transaction outputs are unlocked.\n "
2138
2138
" A locked transaction output will not be chosen by automatic coin selection, when spending bitcoins.\n "
2139
2139
" 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 "
2142
2143
" Also see the listunspent call\n " ,
2143
2144
{
2144
2145
{" unlock" , RPCArg::Type::BOOL, RPCArg::Optional::NO, " Whether to unlock (true) or lock (false) the specified transactions" },
@@ -2152,6 +2153,7 @@ static RPCHelpMan lockunspent()
2152
2153
},
2153
2154
},
2154
2155
},
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." },
2155
2157
},
2156
2158
RPCResult{
2157
2159
RPCResult::Type::BOOL, " " , " Whether the command was successful or not"
@@ -2165,6 +2167,8 @@ static RPCHelpMan lockunspent()
2165
2167
+ HelpExampleCli (" listlockunspent" , " " ) +
2166
2168
" \n Unlock the transaction again\n "
2167
2169
+ 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" ) +
2168
2172
" \n As a JSON-RPC call\n "
2169
2173
+ HelpExampleRpc (" lockunspent" , " false, \" [{\\\" txid\\\" :\\\" a08e6907dbbd3d809776dbfc5d82e371b764ed838b5655e72f463568df1aadf0\\\" ,\\\" vout\\\" :1}]\" " )
2170
2174
},
@@ -2183,9 +2187,13 @@ static RPCHelpMan lockunspent()
2183
2187
2184
2188
bool fUnlock = request.params [0 ].get_bool ();
2185
2189
2190
+ const bool persistent{request.params [2 ].isNull () ? false : request.params [2 ].get_bool ()};
2191
+
2186
2192
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
+ }
2189
2197
return true ;
2190
2198
}
2191
2199
@@ -2236,17 +2244,24 @@ static RPCHelpMan lockunspent()
2236
2244
throw JSONRPCError (RPC_INVALID_PARAMETER, " Invalid parameter, expected locked output" );
2237
2245
}
2238
2246
2239
- if (!fUnlock && is_locked) {
2247
+ if (!fUnlock && is_locked && !persistent ) {
2240
2248
throw JSONRPCError (RPC_INVALID_PARAMETER, " Invalid parameter, output already locked" );
2241
2249
}
2242
2250
2243
2251
outputs.push_back (outpt);
2244
2252
}
2245
2253
2254
+ std::unique_ptr<WalletBatch> batch = nullptr ;
2255
+ // Unlock is always persistent
2256
+ if (fUnlock || persistent) batch = std::make_unique<WalletBatch>(pwallet->GetDatabase ());
2257
+
2246
2258
// Atomically set (un)locked status for the outputs.
2247
2259
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
+ }
2250
2265
}
2251
2266
2252
2267
return true ;
0 commit comments