* [bitcoin-dev] Examining ScriptPubkeys in Bitcoin Script @ 2023-10-20 3:40 Rusty Russell 2023-10-20 14:19 ` Brandon Black 2023-10-27 7:00 ` Anthony Towns 0 siblings, 2 replies; 8+ messages in thread From: Rusty Russell @ 2023-10-20 3:40 UTC (permalink / raw) To: Bitcoin Protocol Discussion Hi all, I've done an exploration of what would be required (given OP_TX/OP_TXHASH or equivalent way of pushing a scriptPubkey on the stack) to usefully validate Taproot outputs in Bitcoin Script. Such functionality is required for usable vaults, at least. https://rusty.ozlabs.org/2023/10/20/examining-scriptpubkey-in-script.html (If anyone wants to collaborate to produce a prototype, and debug my surely-wrong script examples, please ping me!) TL;DR: if we have OP_TXHASH/OP_TX, and add OP_MULTISHA256 (or OP_CAT), OP_KEYADDTWEAK and OP_LESS (or OP_CONDSWAP), and soft-fork weaken the OP_SUCCESSx rule (or pop-script-from-stack), we can prove a two-leaf tapscript tree in about 110 bytes of Script. This allows useful spending constraints based on a template approach. Thanks! Rusty. ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [bitcoin-dev] Examining ScriptPubkeys in Bitcoin Script 2023-10-20 3:40 [bitcoin-dev] Examining ScriptPubkeys in Bitcoin Script Rusty Russell @ 2023-10-20 14:19 ` Brandon Black 2023-10-22 4:16 ` Rusty Russell 2023-10-27 7:00 ` Anthony Towns 1 sibling, 1 reply; 8+ messages in thread From: Brandon Black @ 2023-10-20 14:19 UTC (permalink / raw) To: Rusty Russell, Bitcoin Protocol Discussion On 2023-10-20 (Fri) at 14:10:37 +1030, Rusty Russell via bitcoin-dev wrote: > I've done an exploration of what would be required (given > OP_TX/OP_TXHASH or equivalent way of pushing a scriptPubkey on the > stack) to usefully validate Taproot outputs in Bitcoin Script. Such > functionality is required for usable vaults, at least. So you're proposing this direction as an alternative to the more constrained OP_UNVAULT that replaces a specific leaf in the taptree in a specific way? I think the benefits of OP_UNVAULT are pretty big vs. a generic construction (e.g. ability to unvault multiple inputs sharing the same scriptPubkey to the same output). > TL;DR: if we have OP_TXHASH/OP_TX, and add OP_MULTISHA256 (or OP_CAT), > OP_KEYADDTWEAK and OP_LESS (or OP_CONDSWAP), and soft-fork weaken the > OP_SUCCESSx rule (or pop-script-from-stack), we can prove a two-leaf > tapscript tree in about 110 bytes of Script. This allows useful > spending constraints based on a template approach. I agree that this is what is needed. I started pondering this in response to some discussion about the benefits of OP_CAT or OP_2SHA256 for BitVM. Personally I'd use OP_TAGGEDCATHASH that pops a tag (empty tag can be special cased to plain sha256) and a number (n) of elements to hash, then tagged-hashes the following 'n' elements from the stack. Best, --Brandon ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [bitcoin-dev] Examining ScriptPubkeys in Bitcoin Script 2023-10-20 14:19 ` Brandon Black @ 2023-10-22 4:16 ` Rusty Russell 0 siblings, 0 replies; 8+ messages in thread From: Rusty Russell @ 2023-10-22 4:16 UTC (permalink / raw) To: Brandon Black, Bitcoin Protocol Discussion Brandon Black <freedom@reardencode.com> writes: > On 2023-10-20 (Fri) at 14:10:37 +1030, Rusty Russell via bitcoin-dev wrote: >> I've done an exploration of what would be required (given >> OP_TX/OP_TXHASH or equivalent way of pushing a scriptPubkey on the >> stack) to usefully validate Taproot outputs in Bitcoin Script. Such >> functionality is required for usable vaults, at least. > > So you're proposing this direction as an alternative to the more > constrained OP_UNVAULT that replaces a specific leaf in the taptree in a > specific way? I think the benefits of OP_UNVAULT are pretty big vs. a > generic construction (e.g. ability to unvault multiple inputs sharing > the same scriptPubkey to the same output). I would have to write the scripts exactly (and I'm already uncomfortable that I haven't actually tested the ones I wrote so far!) to properly evaluate. In general, script makes it hard to do N-input evaluation (having no iteration). It would be useful to attempt this though, as it might enlighted us as to OP_TXHASH input selection: for example, we might want to have an "all *but* one input" mode for this kind of usage. Dealing with satsoshi amounts is possible, but really messy (that's my next post). >> TL;DR: if we have OP_TXHASH/OP_TX, and add OP_MULTISHA256 (or OP_CAT), >> OP_KEYADDTWEAK and OP_LESS (or OP_CONDSWAP), and soft-fork weaken the >> OP_SUCCESSx rule (or pop-script-from-stack), we can prove a two-leaf >> tapscript tree in about 110 bytes of Script. This allows useful >> spending constraints based on a template approach. > > I agree that this is what is needed. I started pondering this in > response to some discussion about the benefits of OP_CAT or OP_2SHA256 > for BitVM. Given these examples, I think it's clear that OP_MULTISHA256 is almost as powerful as OP_CAT, without the stack limit problems. And OP_2SHA256 is not sufficient in general for CScriptNum generation, for example. > Personally I'd use OP_TAGGEDCATHASH that pops a tag (empty tag can be > special cased to plain sha256) and a number (n) of elements to hash, > then tagged-hashes the following 'n' elements from the stack. That's definitely a premature optimization to save two opcodes. Cheers, Rusty. ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [bitcoin-dev] Examining ScriptPubkeys in Bitcoin Script 2023-10-20 3:40 [bitcoin-dev] Examining ScriptPubkeys in Bitcoin Script Rusty Russell 2023-10-20 14:19 ` Brandon Black @ 2023-10-27 7:00 ` Anthony Towns 2023-10-28 4:49 ` Rusty Russell 1 sibling, 1 reply; 8+ messages in thread From: Anthony Towns @ 2023-10-27 7:00 UTC (permalink / raw) To: Rusty Russell, Bitcoin Protocol Discussion On Fri, Oct 20, 2023 at 02:10:37PM +1030, Rusty Russell via bitcoin-dev wrote: > I've done an exploration of what would be required (given > OP_TX/OP_TXHASH or equivalent way of pushing a scriptPubkey on the > stack) to usefully validate Taproot outputs in Bitcoin Script. Such > functionality is required for usable vaults, at least. > > https://rusty.ozlabs.org/2023/10/20/examining-scriptpubkey-in-script.html > > (If anyone wants to collaborate to produce a prototype, and debug my > surely-wrong script examples, please ping me!) > > TL;DR: if we have OP_TXHASH/OP_TX, and add OP_MULTISHA256 (or OP_CAT), > OP_KEYADDTWEAK and OP_LESS (or OP_CONDSWAP), and soft-fork weaken the > OP_SUCCESSx rule (or pop-script-from-stack), we can prove a two-leaf > tapscript tree in about 110 bytes of Script. This allows useful > spending constraints based on a template approach. I think there's two reasons to think about this approach: (a) we want to do vault operations specifically, and this approach is a good balance between being: - easy to specify and implement correctly, and - easy to use correctly. (b) we want to make bitcoin more programmable, so that we can do contracting experiments directly in wallet software, without needing to justify new soft forks for each experiment, and this approach provides a good balance amongst: - opening up a wide range of interesting experiments, - making it easy to understand the scope/consequences of opening up those experiments, - being easy to specify and implement correctly, and - being easy to use correctly. Hopefully that's a fair summary? Obviously what balance is "good" is always a matter of opinion -- if you consider it hard to do soft forks, then it's perhaps better to err heavily towards being easy to specify/implement, rather than easy to use, for example. For (a) I'm pretty skeptical about this approach for vault operations -- it's not terribly easy to specify/implement (needing 5 opcodes, one of which has a dozen or so flags controlling how it behaves, then also needs to change the way OP_SUCCESS works), and it seems super complicated to use. By comparison, while the bip 345 OP_VAULT proposal also proposes 3 new opcodes (OP_CTV, OP_VAULT, OP_VAULT_RECOVER) [0], those opcodes can be implemented fairly directly (without requiring different semantics for OP_SUCCESS, eg) and can be used much more easily [1]. [0] Or perhaps 4, if OP_REVAULT were to be separated out from OP_VAULT, cf https://github.com/bitcoin/bips/pull/1421#discussion_r1357788739 [1] https://github.com/jamesob/opvault-demo/blob/57f3bb6b8717acc7ce1eae9d9d8a2661f6fa54e5/main.py#L125-L133 I'm not sure, but I think the "deferred check" setup might also provide additional functionality beyond what you get from cross-input introspection; that is, with it, you can allow multiple inputs to safely contribute funds to common outputs, without someone being able to combine multiple inputs into a tx where the output amount is less than the sum of all the contributions. Without that feature, you can mimic it, but only so long as all the input scripts follow known templates that you can exactly match. So to me, for the vault use case, the TXHASH/MULTISHA256/KEYADDTWEAK/LESS/CAT/OP_SUCCESS approach just doesn't really seem very appealing at all in practical terms: lots of complexity, hard to use, and doesn't really seem like it works very well even after you put in tonnes of effort to get it to work at all? I think in the context of (b), ie enabling experimentation more generally, it's much more interesting. eg, CAT alone would allow for various interesting constraints on signatures ("you must sign this tx with the given R value -- so attempting to double spend, eg via a feebump, will reveal the corresponding private key"), and adding CSFS would allow you to include authenticated data in a script, eg market data sourced from a trusted oracle. But even then, it still seems fairly crippled -- script is a very limited programming language, and it just isn't really very helpful if you want to do things that are novel. It doesn't allow you to (eg) loop over the inputs and select just the ones you're interested in, you need the opcode to do the looping for you, and that has to be hardcoded as a matter of consensus (eg, Steven Roose's TXHASH [2] proposal allows you to select the first-n inputs/outputs, but not the last-n). [2] https://github.com/bitcoin/bips/pull/1500 I've said previously [3] that I think using a lisp variant would be a promising solution here: you can replace script's "two stacks of byte-strings" with "(recursive) lists of byte-strings", and go from a fairly limited language, to a fairly complete one. I've been experimenting with this on and off since then [4], and so far I haven't seen anything much to dissuade me from that view. I think you can get a pretty effective language with perhaps 43 opcodes [5] (compared to script's ~60 active opcodes), and I don't think you need to do anything too fancy to implement it. [3] https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2022-March/020036.html [4] https://github.com/ajtowns/lisp-play/ [5] https://github.com/ajtowns/lisp-play/blob/5975870423f9dace902ef42208b965f9d8a0f005/btclisp.py#L738 Here's an example. I've included a "CSFS" equivalent opcode, namely "(bip340_verify pk msg sig)" that validates a signature per BIP340, and also a "(bip342_txmsg)" opcode that generates a "msg" corresponding to the BIP 342 "Signature Validation" spec (just calling the bitcoind core test framework code), which then allows me to verify existing signatures on existing transactions via lisp code, rather than executing the actual script. But what if we wanted to experiment with a new SIGHASH mode? For that, I've added an OP_TX like opcode, '(tx N)' that allows you to select various information about the tx by choosing N -- '(tx 1)' gives you the locktime, '(tx 10)' gives you your input's nSequence, '(tx (10 . 3))' gives you the nSequence of the 4th input, eg. With that, it's possible to select whichever bits of the transaction you like, in whatever order you like, and pass the results through the '(sha256)' opcode, then pass that into the signature check. Unlike the OP_TXHASH proposals and the like, it's possible (though perhaps not *easy*) to exactly mimic existing hash constructs, eg "(bip342_txmsg)" (for SIGHASH_ALL) can be constructed manually via: ENV=(a (i 14 '(a 8 8 12 (+ 10 '1) (- 14 '1) (cat 3 (a 12 10))) '3)) ^-- (basically a for loop, so that "(a 1 1 'X '0 K)" will invoke "X" with values [0, K), and cat the results together; used with K=(tx '2) to do inputs, and (tx '3) to dou outputs) PROGRAM=(a '(sha256 4 4 '0x00 6 3) (sha256 '\"TapSighash\") (cat '0x00 (tx '0) (tx '1) (sha256 (a 1 1 '(cat (tx (c '11 1)) (tx (c '12 1))) '0 (tx '2) 'nil)) (sha256 (a 1 1 '(tx (c '15 1)) '0 (tx '2) 'nil)) (sha256 (a 1 1 '(a '(cat (strlen 1) 1) (tx (c '16 '0))) '0 (tx '2) 'nil)) (sha256 (a 1 1 '(tx (c '10 1)) '0 (tx '2) 'nil)) (sha256 (a 1 1 '(cat (tx (c '20 1)) (a '(cat (strlen 1) 1) (tx (c '21 1)))) '0 (tx '3) 'nil)) (i (tx '7) '0x03 '0x01) (substr (cat (tx '4) '0x00000000) 'nil '4) (i (tx '7) (sha256 (a '(cat (strlen 1) 1) (tx '7))) 'nil)) (cat (tx '6) '0x00 '0xffffffff)) ^-- (sha256's the sha256 of TapSighash twice, then the epoch, then the sigmsg, then the extension; with the SIGHASH_ALL logic being hardcoded) That's obviously not easy to read, but it's also essentially programming in assembler, and would be much improved by having a higher-level macro-enabled lisp variation that allows you to define your own symbols/variable names, and translate that down to the raw code. (Or even just having a parser that allows you to add comments, I guess) What I've implemented is essentially an eager interpretor with some tail call optimisations to allow memory to be freed up a bit earlier. I think it would be better to do it as a properly lazy iinterpretor though -- that way you can actually have the same memory efficiency as streaming sha256 operators provide, even with the additional flexibility provided by iteration/recursion/function calls. There are various other tricks that aren't done in my python testbed, eg encoding/decoding lists as a byte stream rather than a parenthesised string; working out whether string comparison should be normal or reversed (so that you can comapre proof-of-work) or both, providing other crypto ops like ecdsa, doing bignum maths rather than just uint64, keeping track of allocations when an exception occurs, providing an easy way to tell how much computation will be required to evaluate an input script and inflate the tx's weight correspondingly if necessary, etc. I've also only done fairly toy-level problems: factorial and fibonacci calculations, reimplementing an existing sighash, etc. I think doing TLUV or VAULT or graftroot should be feasible (at least given opcodes to provide secp256k1 tweaks and deferred-checks), but haven't actually done it. Anyway, this seems to me to be a much more promising approach for experimentation than trying to fit everything into script's square hole [6], and perhaps also more promising than Simplicity for the reasons discussed at the end of [3]. Once you have the nicer structure that a lisp-like language provides, compared to script, I think OP_TX, OP_CAT, OP_CSFS etc all end up working pretty great. [6] https://twitter.com/TiredActor/status/1609641593836822530 Cheers, aj ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [bitcoin-dev] Examining ScriptPubkeys in Bitcoin Script 2023-10-27 7:00 ` Anthony Towns @ 2023-10-28 4:49 ` Rusty Russell 2023-10-30 16:20 ` James O'Beirne 2023-10-31 13:05 ` Anthony Towns 0 siblings, 2 replies; 8+ messages in thread From: Rusty Russell @ 2023-10-28 4:49 UTC (permalink / raw) To: Anthony Towns, Bitcoin Protocol Discussion Anthony Towns <aj@erisian.com.au> writes: > On Fri, Oct 20, 2023 at 02:10:37PM +1030, Rusty Russell via bitcoin-dev wrote: >> I've done an exploration of what would be required (given >> OP_TX/OP_TXHASH or equivalent way of pushing a scriptPubkey on the >> stack) to usefully validate Taproot outputs in Bitcoin Script. Such >> functionality is required for usable vaults, at least. >> >> https://rusty.ozlabs.org/2023/10/20/examining-scriptpubkey-in-script.html >> >> (If anyone wants to collaborate to produce a prototype, and debug my >> surely-wrong script examples, please ping me!) >> >> TL;DR: if we have OP_TXHASH/OP_TX, and add OP_MULTISHA256 (or OP_CAT), >> OP_KEYADDTWEAK and OP_LESS (or OP_CONDSWAP), and soft-fork weaken the >> OP_SUCCESSx rule (or pop-script-from-stack), we can prove a two-leaf >> tapscript tree in about 110 bytes of Script. This allows useful >> spending constraints based on a template approach. > > I think there's two reasons to think about this approach: > > (a) we want to do vault operations specifically, and this approach is > a good balance between being: > - easy to specify and implement correctly, and > - easy to use correctly. > > (b) we want to make bitcoin more programmable, so that we can do > contracting experiments directly in wallet software, without needing > to justify new soft forks for each experiment, and this approach > provides a good balance amongst: > - opening up a wide range of interesting experiments, > - making it easy to understand the scope/consequences of opening up > those experiments, > - being easy to specify and implement correctly, and > - being easy to use correctly. > > Hopefully that's a fair summary? Obviously what balance is "good" > is always a matter of opinion -- if you consider it hard to do soft > forks, then it's perhaps better to err heavily towards being easy to > specify/implement, rather than easy to use, for example. > > For (a) I'm pretty skeptical about this approach for vault operations > -- it's not terribly easy to specify/implement (needing 5 opcodes, one > of which has a dozen or so flags controlling how it behaves, then also > needs to change the way OP_SUCCESS works), and it seems super complicated > to use. But AFAICT there are multiple perfectly reasonable variants of vaults, too. One would be: 1. master key can do anything 2. OR normal key can send back to vault addr without delay 3. OR normal key can do anything else after a delay. Another would be: 1. normal key can send to P2WPKH(master) 2. OR normal key can send to P2WPKH(normal key) after a delay. > By comparison, while the bip 345 OP_VAULT proposal also proposes 3 new > opcodes (OP_CTV, OP_VAULT, OP_VAULT_RECOVER) [0], those opcodes can be > implemented fairly directly (without requiring different semantics for > OP_SUCCESS, eg) and can be used much more easily [1]. I'm interested in vaults because they're a concrete example I can get my head around. Not because I think they'll be widely used! So I feel that anyone who has the ability to protect two distinct keys, and make two transactions per transfer is not a great candidate for optimization or convenience. > I'm not sure, but I think the "deferred check" setup might also > provide additional functionality beyond what you get from cross-input > introspection; that is, with it, you can allow multiple inputs to safely > contribute funds to common outputs, without someone being able to combine > multiple inputs into a tx where the output amount is less than the sum > of all the contributions. Without that feature, you can mimic it, but > only so long as all the input scripts follow known templates that you > can exactly match. Agreed, I don't think you would implement anything but 1:1 unvaulting in bitcoin script, except as a party trick. > So to me, for the vault use case, the > TXHASH/MULTISHA256/KEYADDTWEAK/LESS/CAT/OP_SUCCESS approach just doesn't > really seem very appealing at all in practical terms: lots of complexity, > hard to use, and doesn't really seem like it works very well even after > you put in tonnes of effort to get it to work at all? Well, I found the vault BIP really hard to understand. I think it wants to be a new address format, not script opcodes. I don't think spelling it out in script is actually that much more complex to use, either. "Use these templates". And modulo consolidation, I think it works as well. > I think in the context of (b), ie enabling experimentation more generally, > it's much more interesting. eg, CAT alone would allow for various > interesting constraints on signatures ("you must sign this tx with the > given R value -- so attempting to double spend, eg via a feebump, will > reveal the corresponding private key"), and adding CSFS would allow you > to include authenticated data in a script, eg market data sourced from > a trusted oracle. Oh, oracles like this are the first CSFS use case I've heard of that doesn't seem like abusing signatures to do hashing; nice! (Seems like there should be a way to do this without CSFS, but I can't see it...) > But even then, it still seems fairly crippled -- script is a very > limited programming language, and it just isn't really very helpful > if you want to do things that are novel. It doesn't allow you to (eg) > loop over the inputs and select just the ones you're interested in, you > need the opcode to do the looping for you, and that has to be hardcoded > as a matter of consensus (eg, Steven Roose's TXHASH [2] proposal allows > you to select the first-n inputs/outputs, but not the last-n). Indeed, but I still think there's much room for improvement before a replacement. It's hard to compare the hobbled script we have today with an alternative, since most interesting cases are impossible. Cheers, Rusty. ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [bitcoin-dev] Examining ScriptPubkeys in Bitcoin Script 2023-10-28 4:49 ` Rusty Russell @ 2023-10-30 16:20 ` James O'Beirne 2023-10-31 2:24 ` Rusty Russell 2023-10-31 13:05 ` Anthony Towns 1 sibling, 1 reply; 8+ messages in thread From: James O'Beirne @ 2023-10-30 16:20 UTC (permalink / raw) To: Rusty Russell, Bitcoin Protocol Discussion [-- Attachment #1: Type: text/plain, Size: 1288 bytes --] On Sat, Oct 28, 2023 at 12:51 AM Rusty Russell via bitcoin-dev < bitcoin-dev@lists.linuxfoundation.org> wrote: > But AFAICT there are multiple perfectly reasonable variants of vaults, > too. One would be: > > 1. master key can do anything > 2. OR normal key can send back to vault addr without delay > 3. OR normal key can do anything else after a delay. > > Another would be: > 1. normal key can send to P2WPKH(master) > 2. OR normal key can send to P2WPKH(normal key) after a delay. > I'm confused by what you mean here. I'm pretty sure that BIP-345 VAULT handles the cases that you're outlining, though I don't understand your terminology -- "master" vs. "normal", and why we are caring about P2WPKH vs. anything else. Using the OP_VAULT* codes can be done in an arbitrary arrangement of tapleaves, facilitating any number of vaultish spending conditions, alongside other non-VAULT leaves. Well, I found the vault BIP really hard to understand. I think it wants > to be a new address format, not script opcodes. > Again confused here. This is like saying "CHECKLOCKTIMEVERIFY wants to be a new address format, not a script opcode." That said, I'm sure some VAULT patterns could be abstracted into the miniscript/descriptor layer to good effect. [-- Attachment #2: Type: text/html, Size: 1834 bytes --] ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [bitcoin-dev] Examining ScriptPubkeys in Bitcoin Script 2023-10-30 16:20 ` James O'Beirne @ 2023-10-31 2:24 ` Rusty Russell 0 siblings, 0 replies; 8+ messages in thread From: Rusty Russell @ 2023-10-31 2:24 UTC (permalink / raw) To: James O'Beirne, Bitcoin Protocol Discussion "James O'Beirne" <james.obeirne@gmail.com> writes: > On Sat, Oct 28, 2023 at 12:51 AM Rusty Russell via bitcoin-dev < > bitcoin-dev@lists.linuxfoundation.org> wrote: > >> But AFAICT there are multiple perfectly reasonable variants of vaults, >> too. One would be: >> >> 1. master key can do anything >> 2. OR normal key can send back to vault addr without delay >> 3. OR normal key can do anything else after a delay. >> >> Another would be: >> 1. normal key can send to P2WPKH(master) >> 2. OR normal key can send to P2WPKH(normal key) after a delay. >> > > I'm confused by what you mean here. I'm pretty sure that BIP-345 VAULT > handles the cases that you're outlining, though I don't understand your > terminology -- "master" vs. "normal", and why we are caring about P2WPKH > vs. anything else. Using the OP_VAULT* codes can be done in an arbitrary > arrangement of tapleaves, facilitating any number of vaultish spending > conditions, alongside other non-VAULT leaves. I was thinking from a user POV: the "master" key is the one they keep super safe in case of emergencies, the "normal" is the delayed spend key. OP_VAULT certainly can encapsulate this, but I have yet to do the kind of thorough review that I'd need to evaluate the various design decisions. > Well, I found the vault BIP really hard to understand. I think it wants >> to be a new address format, not script opcodes. >> > > Again confused here. This is like saying "CHECKLOCKTIMEVERIFY wants to be a > new address format, not a script opcode." I mean in an ideal world, Bitcoin Script would be powerful enough to implement vaults, and once a popular use pattern emerged we'd introduce a new address type, defined to expand to that template. Like P2WPK or P2PKH. Sadly, we're not in that world! BIP 345 introduces a number of separate mechanisms, such as limited script delegation, iteration and amount arithmetic which are not expressible in Script (ok, amount arithmetic kind of is, but ick!). To form a real opinion, I need to consider all these elements, and whether they should exist inside OP_VAULT, or as separate things. That's a slow process, sorry :( > That said, I'm sure some VAULT patterns could be abstracted into the > miniscript/descriptor layer to good effect. That would be very interesting, but hard. Volunteers? :) Cheers, Rusty. ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [bitcoin-dev] Examining ScriptPubkeys in Bitcoin Script 2023-10-28 4:49 ` Rusty Russell 2023-10-30 16:20 ` James O'Beirne @ 2023-10-31 13:05 ` Anthony Towns 1 sibling, 0 replies; 8+ messages in thread From: Anthony Towns @ 2023-10-31 13:05 UTC (permalink / raw) To: Rusty Russell, Bitcoin Protocol Discussion On Sat, Oct 28, 2023 at 03:19:30PM +1030, Rusty Russell via bitcoin-dev wrote: [Quoted text has been reordered] > > I think there's two reasons to think about this approach: > > (a) we want to do vault operations specifically, > I'm interested in vaults because they're a concrete example I can get my > head around. Not because I think they'll be widely used! I don't think that's likely to make for a very productive discussion: we shouldn't be changing consensus to support toy examples, after all. If there's a *useful* thing to do that would be possible with similar consensus changes, lets discuss that thing; if there's nothing useful that needs these consensus changes, then lets discuss something useful that doesn't need consensus changes instead. To me, it seems pretty likely that if you're designing an API where you don't expect anyone to actually use it for anything important, then you're going to end up making pretty bad API -- after all, why put in the effort to understand the use case and make a good API if you're sure it will never be useful anyway? There are some articles on API design that I quite like: https://ozlabs.org/~rusty/index.cgi/tech/2008-03-30.html https://ozlabs.org/~rusty/index.cgi/tech/2008-04-01.html I'd rate the "lets have a mass of incomprehensible script that no one really understands and is incredibly dangerous to modify, and just make it a template" approach as somewhere between "3. Read the documentation and you'll get it right" (at best) and "-5 Do it right and it will sometimes break at runtime" (more likely). Anyway, for the specific examples: > But AFAICT there are multiple perfectly reasonable variants of vaults, > too. One would be: > > 1. master key can do anything > 2. OR normal key can send back to vault addr without delay > 3. OR normal key can do anything else after a delay. I don't think there's any point having (2) here unless you're allowing for consolidation transactions (two or more vault inputs spending to a single output that's the same vault), which you've dismissed as a party trick. > Another would be: > 1. normal key can send to P2WPKH(master) > 2. OR normal key can send to P2WPKH(normal key) after a delay. I don't think there's any meaningful difference here between (2) here and (3) above -- after the delay, you post one transaction spending to p2wpkh(normal) signed by the normal key, then immediately post a second transaction spending that new output, which is also signed with the normal key, so you've just found a way of saying "normal key can do anything else after a delay" that takes up more blockspace. Both these approaches mirror the model that kanzure posted about in 2018 [0] (which can already be done via presigned transactions) and they share the same fundamental flaw [1], namely that once someone compromises the "normal key", all they have to do is wait for the legitimate owner to trigger a spend, at which point they can steal the funds by racing the owner, with the owner having no recourse beyond burning most of the vault's funds to fees. (I think the above two variants are meaningfully worse than kanzure's in that someone with the normal key just needs to wait for the vault utxo to age, at which point they can steal the funds immediately. In kanzure's model, you first need to broadcast a trigger transaction, then wait for it to age before funds can be stolen, which isn't the greatest protection, but it at least adds some difficulty) [0] https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2019-August/017229.html [1] https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2019-August/017231.html also, https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2022-April/020284.html If you don't mind that flaw, you can setup a vault along the lines of kanzure's design with BIP 345 fairly simply: A: ipk=master, tapscript=<normal> SWAP OVER CHECKSIGVERIFY 1 "CHECKSIGVERIFY 144 CSV" OP_VAULT (witness values: <revault-amt> <revault-idx> <spend-idx> <sig>) B: ipk=master tapscript=<normal> CHECKSIGVERIFY 144 CSV You put funds into the vault by creating a utxo with address "A", at which point you can do anything with the funds via the master key, or you can trigger an unvault via the normal key, moving funds to address "B", which then has a 144 block delay before it can be spent via the normal key. That also natively supports vault spends that only include part of the vault value, or that combine two or more (compatible) vaults into a single payment. To avoid the flaw, you need to precommit to the spend that you're authorising, while still allowing clawback/recovery by the owner. One way to make that work with BIP 345 is using BIP 119's CTV to force a precommitment to the spend: A: ipk=master, tapscript=<masterspkhash> OP_VAULT_RECOVER tapscript=<normal> CHECKSIGVERIFY 1 "CTV DROP 144 CSV" OP_VAULT (witness values: <revault-amt> <revault-idx> <spend-idx> <spendcommit> <sig>) B: ipk=master tapscript=<masterspkhash> OP_VAULT_RECOVER tapscript=<spendcommit> CTV DROP 144 CSV Once you have funds in the vault in address A, you can spend them directly via a key path spend with the master private key, or you can make them only spendable via the master key via the OP_VAULT_RECOVER path, or you can do a precommitted spend via the OP_VAULT path by including "spendcommit", the CTV hash of where you want to send funds to. That moves funds into address B, which again can be recovered to the master key via the first two paths, or after a day you can use the CTV path to complete the vault withdrawal. Again, that natively supports vault spends that only include part of the vault value, or that combine two or more (compatible) vaults into a single payment. > Oh, oracles like this are the first CSFS use case I've heard of that > doesn't seem like abusing signatures to do hashing; nice! > > (Seems like there should be a way to do this without CSFS, but I can't > see it...) It's not really a novel observation: oracles are the third item listed on the optech topic page for CSFS [2]... The scriptless way of getting similar functionality is via discreet log contracts [3], where the oracle with public key P, picks an event, publishes a unique (hardened) public key R for that event, and when the outcome of the event (m) is known, publishes 's' such that sG = R + H(R,P,m)*P, so that (R,s) is a valid BIP 340 schnorr signature for message m and pubkey P. That can then be used via an adaptor signature eg to make on-chain contracts [4], eg. [2] https://bitcoinops.org/en/topics/op_checksigfromstack/ [3] https://www.dlc.wiki/ https://bitcoinops.org/en/topics/discreet-log-contracts/ [4] https://suredbits.com/category/discreet-log-contracts/ https://atomic.finance/blog/discreet-log-contracts/ Cheers, aj ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2023-11-01 12:06 UTC | newest] Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2023-10-20 3:40 [bitcoin-dev] Examining ScriptPubkeys in Bitcoin Script Rusty Russell 2023-10-20 14:19 ` Brandon Black 2023-10-22 4:16 ` Rusty Russell 2023-10-27 7:00 ` Anthony Towns 2023-10-28 4:49 ` Rusty Russell 2023-10-30 16:20 ` James O'Beirne 2023-10-31 2:24 ` Rusty Russell 2023-10-31 13:05 ` Anthony Towns
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox