19:00:45 <meshcollider> #startmeeting 19:00:45 <lightningbot> Meeting started Fri Mar 1 19:00:45 2019 UTC. The chair is meshcollider. Information about MeetBot at http://wiki.debian.org/MeetBot. 19:00:45 <lightningbot> Useful Commands: #action #agreed #help #info #idea #link #topic. 19:00:47 <provoostenator> hi 19:00:48 <sipa> present 19:00:51 <meshcollider> #bitcoin-core-dev Wallet Meeting: wumpus sipa gmaxwell jonasschnelli morcos luke-jr sdaftuar jtimon cfields petertodd kanzure bluematt instagibbs phantomcircuit codeshark michagogo marcofalke paveljanik NicolasDorier jl2012 achow101 meshcollider jnewbery maaku fanquake promag provoostenator aj Chris_Stewart_5 dongcarl gwillen jamesob ken281221 ryanofsky gleb 19:00:58 <instagibbs> hi 19:01:17 <meshcollider> Topics for this week? 19:01:31 <achow101> Hi 19:01:50 <sipa> i guess there isn't anything wallet-related for 0.18 19:02:27 <provoostenator> #15453 19:02:29 <gribble> https://github.com/bitcoin/bitcoin/issues/15453 | Starting bitcoin-qt with -nowallet and then opening a wallet does not show the wallet · Issue #15453 · bitcoin/bitcoin · GitHub 19:02:36 <provoostenator> Is tagged with 0.18 anyway 19:03:02 <provoostenator> With a cliff-hanger from promag 19:03:23 <meshcollider> That's a Qt issue though right 19:03:59 <achow101> It only effects people who self compile 19:04:26 <achow101> As the issue is with qt versions 19:06:21 <provoostenator> It seems so, in which case it should be OK as long as we backport the fix onto the 0.18 branch. 19:07:17 <meshcollider> Mhm 19:07:35 <meshcollider> Other than that, yeah, we managed to get all the wallet PRs for 0.18 reviewed and merged pretty efficiently so nice work 19:09:11 <provoostenator> Proposed topic: descriptor based wallets 19:09:36 <provoostenator> (briefly anyway, since everyone is focussed on 0.18) 19:11:30 <provoostenator> sipa: one thing we talked about before that would be useful for my HWW PR is away to compose descriptors in code 19:12:01 <provoostenator> If you're able to whip up an example for e.g. sh(wpkh(xpub)) I can probably figure out the rest 19:12:25 <provoostenator> It's just my C++ is a bit rusty when it comes to unique_ptr and abstract classes. 19:12:38 <sipa> provoostenator: it's not that trivial anymore in the current code 19:12:56 <sipa> i briefly had a look, but it would need some restructuring 19:13:07 <provoostenator> Ok, glad to know it's not just me :-) 19:14:33 <provoostenator> The use case here is that we fetch an xpub from a hardware wallet and then construct a descriptor with that. 19:14:45 <sipa> with the 0.18 things out of the way, i'll try to find time to do the ismine/keypool abstraction i've talked about before 19:15:13 <provoostenator> ismine/keypool stuff also very useful. 19:16:12 <provoostenator> An alternative approach would be to be require the hardware wallet (driver) to give a full descriptor, or a set of potential desrciptors from which we pick one or more. 19:16:39 <meshcollider> #topic descriptor based wallets 19:16:47 <provoostenator> But that choice shouldn't be determined by implementation details such as this I think. 19:17:02 <sipa> provoostenator: you can always construct the descriptor in string form 19:17:25 <sipa> i agree that's suboptimal, but it means having an API to construct descriptors shouldn't be a blocker 19:17:47 <provoostenator> That's what I'm doing in the prototype. 19:18:15 <instagibbs> I've done this previously as well, constructing manually 19:18:18 <provoostenator> There's not really any blockers left in that PR, so I'm mostly focussing on getting it merge-worthy. 19:19:19 <provoostenator> Although it would be safer when combined with native-descriptor wallets, because the behavior of getnewaddress doesn't jive well with BIP44/49/84 that wallets use. 19:19:45 <provoostenator> (that hardware wallets tend to use) 19:19:55 <instagibbs> provoostenator, you're safe as long as you don't use getnewaddress with a watchonly wallet :D 19:20:24 <meshcollider> are hardware wallets working on implementing things like returning descriptors? 19:20:26 <provoostenator> instagibbs: so you use deriveaddresses? 19:20:43 <instagibbs> provoostenator, no I just assume people aren't going to dust my cold wallet :P 19:20:49 <provoostenator> meshcollider: not that I know, but HWI python coud easiliy do that. 19:20:56 <instagibbs> meshcollider, unlikely to get that standardized, no 19:21:15 <meshcollider> Mhm 19:21:30 <instagibbs> ledger has basically said they won't bother supporting PSBT like ever 19:21:42 <meshcollider> Oh, thats a shame 19:21:43 <instagibbs> I can't imagine they'd do descriptors 19:21:46 <sipa> well they don't need to 19:21:52 <instagibbs> sipa, right, it's fine 19:22:07 <instagibbs> just giving context 19:22:09 <sipa> i mean: i wouldn't even recommend that hw wallets directly implement psbt 19:22:18 <sipa> all you need is a software driver that supports it 19:22:25 <sipa> same with descriptors 19:22:36 <sipa> they're a software (and bitcoin core specifically...) kinda thing 19:22:58 <provoostenator> Basically Bitcoin Core could give an account number and then HWI would, if the device supports SegWit return three descriptors: "pkh([44'/0'/account]xpub/0/*])", "sh(wpkh([49'/0'/account]xpub/0/*]))" and "wpkh([84'/0'/account]xpub/0/*])" (plus change), and then our wallet imports one or all 19:23:10 <achow101> hwi already uses descriptors 19:24:04 <provoostenator> But the current importmulti logic doesn't handle the above correctly, native descriptor wallets would. 19:24:30 <provoostenator> So then you can get a bech32 address and it will grab it from the wpkh(84' tree, or fail if that's absent. 19:25:45 <provoostenator> We probably only need two address types: default and wrapped-segwit. Default is either legacy pkh() or native segwith (wpkh or script hash). 19:26:17 <sipa> you'd mark certain records as the provider for certain types of addresses 19:27:43 <sipa> if you don't have one for native segwit addresses, then requesting a native segwit address will fail 19:28:15 <provoostenator> Right, I guess it's fine to hold on to the current address_type concept then. 19:28:29 <provoostenator> legacy, p2sh_segwit and bech32 19:28:48 <provoostenator> But simply fail if the right descriptor isn't available. 19:29:27 <provoostenator> Do descriptors needs to "marked" for that? Or can you just infer it? 19:29:50 <meshcollider> The default ones would need to be marked in case you have others too 19:29:58 <sipa> well i'm imagining you can have multiple records 19:32:13 <provoostenator> One default record in case there's multiple records of the same address type. 19:32:13 <sipa> (especially if you have a wallet that at some point switched over to a new key/descriptor/hwwallet for whatever reason, but still want to keep access to old transaction history with the previous ones) 19:32:13 <provoostenator> I was thinking of adding a purpose enum: receive, change, other 19:32:13 <sipa> yes 19:32:14 <provoostenator> For each address type there can only be one descriptor with receive/change 19:32:23 <sipa> why? 19:32:32 <provoostenator> Because that indicates the default 19:32:47 <sipa> what a descriptor is used for should be independent of whether it's the default imo 19:32:54 <provoostenator> That makes sense 19:33:06 <provoostenator> So then in addition to purpose, we also need to track the default descriptors. 19:33:11 <sipa> if you transition to a new one, the one you used for change before doesn't stop being change 19:33:52 <sipa> i think that's all in https://gist.github.com/sipa/125cfa1615946d0c3f3eec2ad7f250a2 already 19:34:11 <provoostenator> How do we identify descriptors if there's more than one? Just an increasing int as we add them, or by their checksum (seems brittle) or something else? 19:34:48 <sipa> seems like an implementation detail 19:35:38 <provoostenator> Well, it matters for RPC arguments, but for now I'm avoiding that problem by not allowing more than one of each purpose :-) 19:36:11 <sipa> do you need to expose internal identifiers? 19:36:44 <sipa> (i haven't thought much about this) 19:36:51 <meshcollider> Identify them by checksum :p 19:37:28 <sipa> if so, it seems best that records have a unique user-provided name, and you use that name in rpc to refer to them 19:37:31 <provoostenator> sipa: getnewaddress "Buy new cow" bech32 [how do I tell which non-default descriptor to use] 19:37:48 <instagibbs> why not force them to switch first, then call getnewaddress 19:37:50 <sipa> provoostenator: is that necessary? 19:38:00 <provoostenator> Name makes sense 19:38:08 <sipa> provoostenator: you can't getnewaddress from an old keypool now either 19:38:21 <meshcollider> Other records are more for things like watch-only, etc 19:38:38 <meshcollider> Internal stuff 19:38:42 <provoostenator> True, if non-default descriptors can only be used for archival purposes then there's no need to support them in getnewaddress 19:39:03 <sipa> that's what i was thinking yes; they're just there to not lose old transaction history 19:39:07 <sipa> or to watch 19:39:12 <provoostenator> It also depends on how much we want to push for 1-wallet-1-goal 19:39:23 <provoostenator> Rather than put-whatever-you-want-in-a-single-walllet 19:40:09 <sipa> right; but in a pure watch-only wallet (where "watch only" truly means you're watching someone else's wallet, not just "i don't have the private key right here"), you probably don't want to have any "default newaddress provider" 19:40:15 <provoostenator> I also prefer keeping wallets simple in that sense, especially to keep the GUI sane. 19:40:19 <sipa> because there shouldn't be a way to create new addresses 19:41:29 <provoostenator> Agree that getnewaddress should require >= IsSolveable 19:41:40 <sipa> descriptors are always solvable 19:41:59 <sipa> (except the "raw" and "script" ones, but those can't be used to derive anything anyway) 19:42:06 <provoostenator> Ah yes 19:42:12 <sipa> solvability is not the point 19:42:37 <meshcollider> thats the difference between is "mine" and is "spendable" 19:43:04 <sipa> so right now "watchonly" means "i don't happen to have the private key in my wallet.dat file" 19:43:10 <sipa> i think that's a mistake 19:43:44 <meshcollider> Agree, this rework is the perfect time to tighten up definition of things like that too 19:43:45 <sipa> the distinction between "my money" and "watched money" is useful, but it's somewhat independent from where the private keys live 19:44:23 <sipa> especially in a hwwallet/offline storage/... kinda world... the case where the private key is actually in your wallet.dat file (even for your own coins) should be the exception 19:45:34 <sipa> oh, i guess i should bring this up here, i did a talk at SBC19 about miniscript, and i'll work on getting support for it in core 19:45:53 <sipa> so that our signer (including psbt, etc) can deal with more complicated scripts than just single key and multisig 19:46:46 <provoostenator> So we can do things like GreenAddress style multisig or timeout & single sig? 19:46:50 <sipa> yeah 19:47:16 <meshcollider> Was the talk recorded 19:47:28 <sipa> https://www.youtube.com/watch?v=XM1lzN4Zfks 19:47:34 <meshcollider> Thanks 19:47:38 <provoostenator> I wonder what the setup UX would look like if e.g. you had two hardware wallets and wanted such a 2-of-2 or timeout & 1-of-2. 19:47:53 <sipa> provoostenator: that's a question for you :) 19:48:00 <sipa> i'm perfectly fine with psbt rpcs :P 19:48:20 <instagibbs> gui coin control tho 19:48:20 <achow101> sipa: replacing the signer with miniscript would probably be a good time to also distinguish between signing and finalizing 19:48:32 <sipa> achow101: hmm? 19:48:55 <provoostenator> Right, I guess there would be an RPC where you give it a meta-descriptor or miniscript, then it goes and fetches xpubs from both devices in sequence and imports the right descriptors 19:49:11 <provoostenator> Plus asking some sanity check questions to the driver like "can you sign stuff with nlocktime" 19:49:20 <achow101> ProduceSignature makes both the signature and scriptSig/witness 19:49:20 <instagibbs> provoostenator, the descriptor will be parsed into miniscript, afaik 19:49:25 <sipa> provoostenator: the workflow is that you'd use the miniscript compiler to convert a policy to a descriptor 19:49:28 <instagibbs> ^ 19:49:29 <sipa> and then import the descriptor 19:49:30 <instagibbs> yeah 19:49:42 <sipa> the compiler could be built-in, but doesn't need to be 19:49:51 <provoostenator> Do you put xpubs in the miniscript or does that happen later? 19:50:00 <achow101> But under the psbt model, those should be distinct. 19:50:06 <sipa> provoostenator: yeah 19:50:17 <sipa> the compiler just passes those though, i imagine 19:50:58 <sipa> (miniscript is just the name of the subset of script; i use "policy" language to refer to the input of the compiler) 19:51:06 <sipa> i know, i suck at naming things 19:51:21 <sipa> and this is genuinely confusing because there are several things that look kinda similar 19:51:47 <provoostenator> signerfetchkeys "miniscript with rules $device_fingerprint_1 $device_fingerprint_1" 19:51:50 <sipa> achow101: yeah, i guess it can simplify things if we split up the signer and finalizer in the code too 19:51:53 <provoostenator> Piece of cake 19:54:48 <meshcollider> Is there anything else anyone wants to talk about in the last few minutes 19:58:53 <meshcollider> #endmeeting