New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add scantxoutset RPC method #12196
Add scantxoutset RPC method #12196
Conversation
Why is it pubkeys and not addresses for the pubkey part? (obviously xpubs are xpubs and need to be) |
After a short discussion on IRC (https://botbot.me/freenode/bitcoin-core-dev/2018-01-16/?msg=95804115&page=2) support for addresses and pubkeys makes most sense. Will add support for an array of addresses. |
6993c02
to
4378347
Compare
src/rpc/blockchain.cpp
Outdated
else if (request.params[0].get_str() == "abort") { | ||
CoinsViewScanReserver reserver; | ||
if (reserver.reserve()) { | ||
throw JSONRPCError(RPC_INVALID_PARAMETER, "No scan in progress"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO there is no need to throw, a bool
in the response is enough? Otherwise, missing test.
src/rpc/blockchain.cpp
Outdated
{ | ||
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) | ||
throw std::runtime_error( | ||
"scantxoutset <action> {\"pubkeys\": [\"pubkey\",...], \"xpubs\":[{\"xpub\": \"<xpub>\"}], other options}\n" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove other options
? There are none.
src/rpc/blockchain.cpp
Outdated
|
||
UniValue scantxoutset(const JSONRPCRequest& request) | ||
{ | ||
if (request.fHelp || request.params.size() < 1 || request.params.size() > 2) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
request.params.size() != 2
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nah. You can also call scantxoutset status
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Commit "Blockchain/RPC: Add scantxoutset method to scan UTXO set"
Nah. You can also call scantxoutset status
Right.
However should be request.params.size() > 3
(instead of 2)?
src/rpc/blockchain.cpp
Outdated
" \"pubkeys\":[\"pubkey\",...] (array of strings, optional) An array of HEX encoded public keys\n" | ||
" \"xpubs\": (array of xpub objects that will be used to derive child keys with the given lookup window after m/0/k and m/1/k scheme)\n" | ||
" [\n" | ||
" {\"xpub\":\"<xpub>\", (base58check encoded extended public key (xpub)\n" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit, newline after {
.
src/rpc/blockchain.cpp
Outdated
if (request.params[0].get_str() == "status") { | ||
CoinsViewScanReserver reserver; | ||
if (reserver.reserve()) { | ||
throw JSONRPCError(RPC_INVALID_PARAMETER, "No scan in progress"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing test for error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You mean missing a functional test for that case. Yes. I though about it, but would require a mockup-slowdown argument (-testslowdown
or similar). Otherwise I guess it's hard to properly test this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why would this be an exception, considering that the scan could normally finish between the last call and this one? Generally I think we should avoid exceptions for control flow in our code (and especially in third party code that uses the rpc interface)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, agree that status
should not raise an error when no scan is in progress.
src/rpc/blockchain.cpp
Outdated
static std::mutex g_utxosetscan; | ||
static std::atomic<int> g_scan_progress; | ||
static std::atomic<bool> g_scan_in_progress; | ||
static std::atomic<bool> g_should_abourt_scan; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo, abort.
src/rpc/blockchain.cpp
Outdated
} | ||
|
||
~CoinsViewScanReserver() { | ||
std::lock_guard<std::mutex> lock(g_utxosetscan); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lock only when changing g_scan_in_progress
?
if (m_could_reserve) {
std::lock_guard<std::mutex> lock(g_utxosetscan);
g_scan_in_progress = false;
}
src/rpc/blockchain.cpp
Outdated
else if (request.params[0].get_str() == "start") { | ||
CoinsViewScanReserver reserver; | ||
if (!reserver.reserve()) { | ||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Scan already in progress, use action \"abort\" \"status\""); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove "status"? Otherwise add or
between actions.
src/rpc/blockchain.cpp
Outdated
result.push_back(Pair("searched_items", count)); | ||
} | ||
|
||
for (auto& it : coins) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const auto&
src/rpc/blockchain.cpp
Outdated
explicit CoinsViewScanReserver() : m_could_reserve(false) {} | ||
|
||
bool reserve() { | ||
std::lock_guard<std::mutex> lock(g_utxosetscan); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Assert not reserved?
assert(!m_could_reserve);
std::lock_guard<std::mutex> lock(g_utxosetscan);
if (g_scan_in_progress) return false;
g_scan_in_progress = true;
m_could_reserve = true;
return true;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
Concept ACK, nice! I've wished for UTXO scanning functionality many times, much faster than importing into a watchonly wallet if you only care about spendable UTXOs. |
e54c0e6
to
9bf9baa
Compare
|
|
9bf9baa
to
1490e13
Compare
Overhauled the fee calculation logic (see the dummy sign keystore). |
src/rpc/blockchain.cpp
Outdated
|
||
// flush utxo state and start the scan | ||
FlushStateToDisk(); | ||
bool res = pcoinsdbview->FindScriptPubKey(g_scan_progress, g_should_abort_scan, count, needles, coins); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What prevents the state from being mutated out from under this scan?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think due to the time required to perform a scan, it's something that may be tolerated (although it should be mentioned in the docs). Not sure, but I guess it's the same with gettxoutsetinfo
.
Not sure if you can scan a CCoinsView
of a snapshot state... I guess no.
Locking cs_main would be "meh".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, the rawtx (sweep) is in the same way "outdated" the moment you have received it... maybe you could argue that this is the same for fundrawtx
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@gmaxwell @jonasschnelli The cursor iterates over the state of the CCoinsView at the time it was created; modifying it during iteration is fine. This only works because GetCursor
is not implemented for CCoinsViewCache
, and is invoked directly on the CCoinsViewDB
LevelDB wrapper.
The downside is that this requires a full flush of the database, hurting performance for all of the process (including validation).
NACK supporting addresses. Addresses have no relation to the UTXOs. |
@luke-jr: Why? Addresses are encoded output scripts (scriptPubKey). The rational behind supporting addresses is that a) it may be more efficient then forming every possible known common script from a pubkey and b) that pubkeys are somewhat more difficult to export then the pure "used addresses". |
Addresses are opaque identifiers for a given invoice. That they are currently implemented by encoding a scriptPubKey is irrelevant. |
Does it support mempool/unconfirmed utxos? I had a quick look and didn't seem to, I think it would be useful to have mempool too. Would it make sense to avoid the background job? maybe by keeping the utxo set sorted by scriptPubKey and binary search on it or perhaps some utxo set limited indexing? |
It currently does not scan the mempool (hence the command name
You mean speeding up the scan? I don't think its worth to keep an extra index (changing the sort order would probably slow down verification a lot). |
Rebased |
1490e13
to
2c006f5
Compare
The commit separation here is ugly: CCoinsView::FindScriptPubKey initially checks ShutdownRequested directly, and then this is removed with the RPC changes. |
8cc1a82
to
729c484
Compare
Fixed the ugly commit separation in |
729c484
to
3835de0
Compare
b9b59cc
to
be98b2d
Compare
Fixed relevant points from @Empact |
be98b2d [QA] Add scantxoutset test (Jonas Schnelli) eec7cf7 scantxoutset: mention that scanning by address will miss P2PK txouts (Jonas Schnelli) 94d73d3 scantxoutset: support legacy P2PK script type (Jonas Schnelli) 892de1d scantxoutset: add support for scripts (Jonas Schnelli) 7830494 Blockchain/RPC: Add scantxoutset method to scan UTXO set (Jonas Schnelli) 9048575 Add FindScriptPubKey() to search the UTXO set (Jonas Schnelli) Pull request description: Alternative to #9152. This takes `<n>` pubkeys and optionally `<n>` xpubs (together with a definable lookup windows where the default is 0-1000) and looks up common scripts in the UTXO set of all given or derived keys. The output will be an array similar to `listunspent`. That array is compatible with `createrawtransaction` as well as with `signrawtransaction`. This makes it possible to prepare sweeps and have them signed in a secure (cold) space. Tree-SHA512: a2b22a117cf6e27febeb97e5d6fe30184926d50c0c7cbc77bb4121f490fed65560c52f8eac67a9720d7bf8f420efa42459768685c7e7cc03722859f51a5e1e3b
utACK be98b2d. |
f6b7fc3 Support h instead of ' in hardened descriptor paths (Pieter Wuille) fddea67 Add experimental warning to scantxoutset (Jonas Schnelli) 6495849 [QA] Extend tests to more combinations (Pieter Wuille) 1af237f [QA] Add xpub range tests in scantxoutset tests (Jonas Schnelli) 151600b Swap in descriptors support into scantxoutset (Pieter Wuille) 0652c32 Descriptor tests (Pieter Wuille) fe8a7dc Output descriptors module (Pieter Wuille) e54d760 Add simple FlatSigningProvider (Pieter Wuille) 29943a9 Add more methods to Span class (Pieter Wuille) Pull request description: As promised, here is an implementation of my output descriptor concept (https://gist.github.com/sipa/e3d23d498c430bb601c5bca83523fa82) and integration within the `scantxoutset` RPC that was just added through #12196. It changes the RPC to use descriptors for everything; I hope the interface is simple enough to encompass all use cases. It includes support for P2PK, P2PKH, P2WPKH, P2SH, P2WSH, multisig, xpubs, xprvs, and chains of keys - combined in every possible way. Tree-SHA512: 63b54a96e7a72f5b04a8d645b8517d43ecd6a65a41f9f4e593931ce725a8845ab0baa1e9db6a7243190d8ac841f6e7e2f520d98c539312d78f7fd687d2c7b88f
Thanks for your great efforts implementing this feature, On Oct 01, 2020, When I run this RPC command on Bitcoin Node version 0.20.0, then its response is too slow, I am getting rpc response after 1-2 minutes. Is there any way to speed up this "scantxoutset" RPC command or any alternative available? I asked the same question over bitcoin stackexchange forum, but nobody responded. I know its not the right place to ask such questions, but I am stuck, our mobile wallet is live and we are unable to fetch user "imported" address balances on the fly. Thanks. |
@surindergiri that was like 3 hours before you posted here.. |
2f0b25a rpc: remove scantxoutset EXPERIMENTAL warning (Jon Atack) Pull request description: Remove old warning per IRC wallet meeting discussion at http://www.erisian.com.au/bitcoin-core-dev/log-2021-03-12.html#l-467 This RPC was merged 3 years ago in bitcoin#12196. ACKs for top commit: MarcoFalke: cr ACK 2f0b25a Tree-SHA512: 874ccd5bd19ecbbe91912171ac85af7a4658dc92f6db484ff3d03f07f1b9ba97e1c69d33a5c3ae5c5ec46cac3595a211f55fec0fbf81bac30d66a891c376ce26
2f0b25a rpc: remove scantxoutset EXPERIMENTAL warning (Jon Atack) Pull request description: Remove old warning per IRC wallet meeting discussion at http://www.erisian.com.au/bitcoin-core-dev/log-2021-03-12.html#l-467 This RPC was merged 3 years ago in bitcoin#12196. ACKs for top commit: MarcoFalke: cr ACK 2f0b25a Tree-SHA512: 874ccd5bd19ecbbe91912171ac85af7a4658dc92f6db484ff3d03f07f1b9ba97e1c69d33a5c3ae5c5ec46cac3595a211f55fec0fbf81bac30d66a891c376ce26
merge bitcoin#12196, bitcoin#13697: Add scantxoutset RPC method
Alternative to #9152.
This takes
<n>
pubkeys and optionally<n>
xpubs (together with a definable lookup windows where the default is 0-1000) and looks up common scripts in the UTXO set of all given or derived keys.The output will be an array similar to
listunspent
. That array is compatible withcreaterawtransaction
as well as withsignrawtransaction
.This makes it possible to prepare sweeps and have them signed in a secure (cold) space.