--- Log opened Mon Apr 26 00:00:37 2021 01:24 -!- felixweis [sid154231@gateway/web/irccloud.com/x-rjfaljpefwtmhbry] has quit [Read error: Connection reset by peer] 01:24 -!- elichai2 [sid212594@gateway/web/irccloud.com/x-uflnueqedawpmbec] has quit [Read error: Connection reset by peer] 01:29 -!- felixweis [sid154231@gateway/web/irccloud.com/x-hrgkjieufsancvyx] has joined ##miniscript 01:30 -!- elichai2 [sid212594@gateway/web/irccloud.com/x-ctdbnypmeoivqbxx] has joined ##miniscript 02:01 -!- harrigan [~harrigan@ptr-93-89-242-235.ip.airwire.ie] has quit [Read error: Connection reset by peer] 02:02 -!- harrigan [~harrigan@ptr-93-89-242-235.ip.airwire.ie] has joined ##miniscript 04:55 -!- queip [~queip@unaffiliated/rezurus] has quit [Ping timeout: 252 seconds] 05:02 -!- queip [~queip@unaffiliated/rezurus] has joined ##miniscript 06:19 -!- harrigan [~harrigan@ptr-93-89-242-235.ip.airwire.ie] has quit [Read error: Connection reset by peer] 06:20 -!- harrigan [~harrigan@ptr-93-89-242-235.ip.airwire.ie] has joined ##miniscript 06:24 -!- harrigan [~harrigan@ptr-93-89-242-235.ip.airwire.ie] has quit [Read error: Connection reset by peer] 06:26 -!- harrigan [~harrigan@ptr-93-89-242-235.ip.airwire.ie] has joined ##miniscript 06:46 -!- dr_orlovsky [~dr-orlovs@31.14.40.19] has joined ##miniscript 06:46 -!- dr-orlovsky [~dr-orlovs@31.14.40.19] has quit [Ping timeout: 265 seconds] 07:12 -!- mol [~mol@unaffiliated/molly] has joined ##miniscript 07:13 -!- molz_ [~mol@unaffiliated/molly] has joined ##miniscript 07:15 -!- mol_ [~mol@unaffiliated/molly] has quit [Ping timeout: 252 seconds] 07:16 -!- mol [~mol@unaffiliated/molly] has quit [Ping timeout: 246 seconds] 07:35 < andytoshi> darosior: fwiw pieter and i spent some time thinking about this and we don't think it would break the type system 07:35 < andytoshi> OTOH, if rust-bitcoin is out of sync with everybody else 07:36 < andytoshi> i think that rust-bitcoin should change, even though it breaks jeremyrubin 07:36 < andytoshi> on the third hand, i think that rust-bitcoin is correct.. 07:36 < andytoshi> but on the fourth hand i really don't care, this feels like an unimportant edge case 08:36 < darosior> andytoshi: yes the only issue is with compiling a policy thresh(1, a, b, ..) now as it implies having to use nested or()s 08:37 < darosior> Thanks for thinking about it, ultimately i can't decide what's the Right Thing to do but the patch to rust-bitcoin is ready (modulo the policy compiler thing) :) 09:08 -!- harrigan [~harrigan@ptr-93-89-242-235.ip.airwire.ie] has quit [Read error: Connection reset by peer] 09:10 -!- harrigan [~harrigan@ptr-93-89-242-235.ip.airwire.ie] has joined ##miniscript 10:36 < jeremyrubin> andytoshi: I think it doesn't quite break me, because I use policy (so IDGAF) 10:37 < jeremyrubin> it just breaks reading old Miniscripts possibly? 10:52 < darosior> jeremyrubin: Yes then if you are fine with it too we can just move forward with the simple fix to rust-bitcoin and postpone a possible language change to later? 10:52 < sipa> is this the k=1 and k=n in thresh issue? 10:53 < jeremyrubin> I think it's inadvisable to do so, as it needs to be done as 2 major version releases 10:53 < jeremyrubin> sipa: yes 10:54 < jeremyrubin> darosior: I would also want to test that it actually works 10:54 < sipa> and it's in miniscript right, not in policy? 10:55 < sipa> that the C++ code rejects k=1 and k=n while rust-miniscript accepts those? 10:55 < jeremyrubin> yes 10:57 < sipa> but those are also never optimal (some variant of nested ors/ands will always be more optimal than CMS based constructions) 10:58 < jeremyrubin> IMO miniscript should be disinterested in optimality, that's a policy concern 11:00 < jeremyrubin> there are plenty of non optimal but comprehensible miniscripts 11:05 < jeremyrubin> I think I cared more about this when I was trying to target miniscript directly, because it makes generic tooling hell. Now that I target policy i shouldn't care as much, but if deterministic policy is permanently infeasible and I go back to making bare miniscripts then it becomes annoying again 11:06 < jeremyrubin> I guess it points to in any case making a basic policy lang that is just miniscript but it scans to substitute thresh clauses before compiling 11:07 < jeremyrubin> anyways i'll stop pestering I know this is annoying 11:08 < sipa> i'm just trying to swap in enough context to have an opinion 11:09 < sipa> i kind of agree with the "disinterested in optimality", but on the other hand, the choice of available constructions in miniscript is informed by optimality: tons of potential alternatives were discarded simply because they're never better than other ones which are included 11:12 < jeremyrubin> I also think from certain perspectives to the extent anyone has actually used rust-miniscript in the wild (maybe me? am i the only mainnet user?) changing this breaks compatibility and makes scripts no longer parseable 11:12 < jeremyrubin> whereas expanding it doesn't hurt anyone 11:12 < sipa> that's a reasonable argument 11:12 < jeremyrubin> so maybe it's lucky that this isn't somehow a big grievous error 11:12 < jeremyrubin> and we should be more careful about such spec nonconformances in the future 11:13 < sipa> the fact that the implementations differ is a bigger issue than the question of which of the two the "right" one is 11:15 -!- mol [~mol@unaffiliated/molly] has joined ##miniscript 11:16 -!- mol_ [~mol@unaffiliated/molly] has joined ##miniscript 11:17 -!- molz_ [~mol@unaffiliated/molly] has quit [Ping timeout: 246 seconds] 11:20 -!- mol [~mol@unaffiliated/molly] has quit [Ping timeout: 240 seconds] 11:24 < jeremyrubin> sipa: yeah I agree with that 11:24 < jeremyrubin> FWIW I don't think anything I currently have on mainnet would cause me to not be able to parse existing outputs if rust changed, just theoretical 11:25 < jeremyrubin> and if it is a breaking change, then semver should make sure my software at least works 11:29 < sipa> the whole question of how to standardize miniscript (and by extension, descriptors) is a hard one, because i think we'll need optional parts (on the one hand some implementations may choose to not support pre-segwit descriptors etc 11:29 < sipa> i don't think it's as simple as having version numbers in the spec 11:31 -!- jeremyrubin [~jr@024-176-247-182.res.spectrum.com] has quit [Ping timeout: 245 seconds] 11:32 -!- jeremyrubin [~jr@024-176-247-182.res.spectrum.com] has joined ##miniscript 11:32 < jeremyrubin> you almost need some feature flag system or something, but then that would require adding a versionbyte somewhere to the miniscript... 11:33 < jeremyrubin> differentiating "this script is garbage" and "this script is garbage to me" is very tricky indeed 11:34 < jeremyrubin> darosior: out of curiosity why do you need rust-miniscript patched in particular v.s. just sanity checking your own scripts for well formedness? 11:34 < jeremyrubin> are you using policy or miniscript raw? 11:35 < sipa> jeremyrubin: i'm not sure; i was hoping for a "spec" that effectively makes every fragment optional to support, but if a particular script is supported, it has to match the spec 11:35 < sipa> i don't think there is a difference between "this script is garbage" and "this script is garbage to me"; in both cases you should refuse to work with it 11:35 < jeremyrubin> btw sipa I think thresh as defined is not ever optimal for N, but I could imagine a hypothetical weighted version of thresh where you have clauses that carry more weight than others. 11:36 < jeremyrubin> sipa: more about what you return to a user "your software may need an update because we detected an unknown feature flag" 11:37 < sipa> jeremyrubin: i think in that case nested or/and is going to be even more optimal (put the most likely ones first in an or_i or so) 11:38 < sipa> uniform probability 1-of-n is where thresh is already closest to what can be using nested or, but nested even there is better 11:38 < jeremyrubin> possibly? a proof of that would be cool (not saying I don't beleive you, but the flat structure of thresh is just compelling) 11:39 < jeremyrubin> e.g., if it's some big set of things thresh N, then you would need your or circuit to handle all possible subsets that pass the thresh 11:39 < jeremyrubin> can imagine that getting pathological 11:39 < sipa> we're talking about 1-of-N only here 11:39 < jeremyrubin> and the no repeated key rule gets messy 11:40 < jeremyrubin> ah I'm talking about "[4/26/21 11:35] btw sipa I think thresh as defined is not ever optimal for N, but I could imagine a hypothetical weighted version of thresh where you have clauses that carry more weight than others." 11:40 < sipa> k-of-N can't be implemented using just a tree of ors 11:40 < sipa> and also, the point under discussion is whether 1-of-n (and n-of-n) thresh should be supported 11:41 < jeremyrubin> I guess let me summarize my train of thought 11:41 < sipa> for n-of-n it's i think easy to show that nested and is always better 11:42 < sipa> for 1-of-n, the optimality will depend on the probability of the branches, but i think uniform probability is where thresh is closest to nested ors, but still not quite there 11:42 < jeremyrubin> Ah I see 11:42 < jeremyrubin> right since you need a path in the tree 11:43 < jeremyrubin> which can be huffman coded 11:43 < sipa> or it can just be a sequence of or_b's 11:43 < sipa> even that is better than thresh 11:43 < jeremyrubin> but if you don't have any information, you can still do log(n) with ors? 11:43 < jeremyrubin> log(n) dissats 11:44 < sipa> there are likely other or-based tree structures that are even better 11:44 < jeremyrubin> really? if you have uniform? 11:44 < sipa> but just compare thresh(1,...) with or_b(or_b(or_b(...),...),...) 11:44 < sipa> oh, no 11:45 < sipa> the or_b need O(1) opcodes extra per argument 11:45 < sipa> while the thresh has a constant OP_1 OP_EQUAL 11:45 < jeremyrubin> yeah 11:47 < sipa> do you agree that if we can prove that some or-based construction is better than thresh(1,...) for any uniform 1-of-n policy, then this is also the case for non-uniform ones? 11:47 < jeremyrubin> hmmm 11:47 < jeremyrubin> perhaps if you make n = 2^m? 11:48 < sipa> no, it's far more generic 11:48 < jeremyrubin> I think there's also possibly a preference to use thresh if you don't want to favor any spending path over any other. 11:48 < jeremyrubin> this might be useful for e.g. privacy reasons 11:48 < sipa> that's a weird argument 11:49 < jeremyrubin> exposing tree structure leaks information about the script? 11:49 < sipa> just sort them randomly or lexicographically if you don't want to reveal more 11:49 < sipa> (if on average it's still cheaper, which i believe will be the case) 11:49 < jeremyrubin> I would need to think on your question a bit more before agreeing to it 11:49 < sipa> but you do bring up a good point 11:50 < jeremyrubin> I think it has to be true 11:50 < jeremyrubin> given that uniform is the no information case 11:51 < jeremyrubin> so adding information can only monotonically improve compilation? 11:51 < sipa> what we care about is also: construct the optimal 1-of-n policy using or-based constructions for the assumption every branch is equally likely.... is it still the case than that construction is cheaper than thresh(1,...) *even* if the actual branch probabilities are not uniform (specifically, even if they're always the worst case) 11:51 < jeremyrubin> The only way I could see that going awry is if the distribution is somehow fat tailed, in which case using probabilities the straightforward way could lead to a blowup in EV 11:51 < jeremyrubin> but scripts are bounded size, so that's a bit absurd 11:53 < jeremyrubin> sipa: it seems that works case would be O(log(n)) dissatisfactions 11:53 < jeremyrubin> The thing that hurts my head is the wrappers required mostly 11:53 < jeremyrubin> I'm very uncertain that it won't be the case that either w/ current primitives or some future primitives that wrappers wouldn't make something else more efficient 11:54 < jeremyrubin> but as noted (maybe in rust-bitcoin?) 11:55 < jeremyrubin> [Saturday, April 24, 2021] [10:26:48 AM PDT] anyways andytoshi i am comfortable with admitting the reason that i want deterministic policy is that i am not smart enough to figure out how to write bare miniscript :) 11:55 < sipa> why do you need to write bare miniscript? we have compilers :p 11:55 < jeremyrubin> wrappers are very immemorable to me so I can't really even load the state into my mind 11:55 < sipa> write your logic to generate policy, feed it to a compiler, and then output the result of that (which is miniscript, and thus stable) 11:56 < jeremyrubin> sipa: because I want deterministic compilation and that's currently a stated non goal 11:56 < jeremyrubin> sipa: and I need users able to substitute sub clauses, so I can't use policy as a development tool 11:57 < jeremyrubin> anyways didn't mean to get back to a tired point 11:57 < sipa> :) 11:57 < jeremyrubin> but it's the same reason why i'm unsure about or trees 11:57 < jeremyrubin> reasoning about wrappers required makes my head spin 11:58 < jeremyrubin> I think that as N gets bigger, these things hold for sure 11:58 < jeremyrubin> well i gues not even 11:58 < jeremyrubin> since the program size is always N for N clauses 11:58 < jeremyrubin> (tree OR or thresh) 11:59 < sipa> well we know that the cost difference between or-construction-targetted-for-uniform-but-fed-worst-case and thresh(1,...) is at most n-2 weight (because sequence of or_b's gives that) 11:59 < sipa> it has the exact same types either way as well for its arguments 12:00 < sipa> so for n=2, there is no difference 12:00 < sipa> ehhh 12:00 < sipa> wait 12:01 < jeremyrubin> btw if you're just socratic'ing me and already know these things, don't let me burn your time 12:01 < sipa> no, i don't know the answer 12:01 < sipa> wait, we're talking about thresh or thresh_m? 12:02 < jeremyrubin> is thresh_m multisig? 12:02 < sipa> oh, yes, it was renamed to multi 12:02 < sipa> yeah 12:02 < jeremyrubin> multi: 1 ≤ k ≤ n 12:03 < sipa> because for generic thresh, the answer is obvious 12:03 < jeremyrubin> i think multi is more efficient because of CMS opcode 12:03 < sipa> thresh(1,...) can be drop-in replaced with a chain of or_b's, which will always be more efficient 12:03 < jeremyrubin> hmmm 12:03 < jeremyrubin> wait 12:04 < jeremyrubin> multi is not always better than thresh 12:04 < sipa> pretty sure it is; it's just not always applicable (it needs key arguments) 12:04 < jeremyrubin> no it's not because witness size of keys in program v.s. hashes? 12:05 < sipa> oh you mean due to pk_h's? 12:05 < jeremyrubin> pk_h key in thresh can be better than multi 12:05 < jeremyrubin> yeah 12:05 < sipa> yeah, agree 12:05 < sipa> but if we for a moment assume that multi isn't usable for whatever reason 12:05 < jeremyrubin> lol 12:05 < sipa> compare (a b BOOLOR c BOOLOR d BOOLOR) with (a b ADD c ADD d ADD 1 EQUAL) 12:05 < jeremyrubin> thresh with keys either pk_h or pk_k depending on how likely they are (brain blowup) 12:06 < sipa> they're exactly equivalent in terms of semantics/types, but the BOOLOR construction is always better 12:06 < sipa> it's literally 2 opcodes less, always 12:06 < jeremyrubin> Ah since boolor is always the same type as add? 12:07 < jeremyrubin> But I thought thresh on a can take a different type than boolor? 12:07 < jeremyrubin> or_b X is Bd, Z is Wd 12:07 < jeremyrubin> thresh a is Bdu, others are Wdu? 12:08 < jeremyrubin> I guess Bdu subsets Bd? 12:08 < sipa> yes 12:08 < sipa> right, add is more restrictive even; it needs arguments that are exactly 1 for true, rather than just nonzero value 12:08 < jeremyrubin> BTW would you be opposed to rewriting the type names in the spec to be written in a more trait-y way if someone made a PR 12:09 < jeremyrubin> e.g., Base + Dissat + Unit 12:09 < sipa> that looks really verbose 12:09 < sipa> but i admit that the current notation isn't very readable 12:10 < jeremyrubin> Assume that what is written once will be read 1000 times, so readability is better than writing 12:10 < sipa> it's just the only way i could make things fit on one line in the table 12:10 < jeremyrubin> hahaha 12:10 < sipa> andor(X,Y,Z); eX and (sX or sY or sZ); s=sZ and (sX or sY); f=fZ and (sX or fY); e=eZ and (sX or fY) 12:11 < jeremyrubin> hm? 12:11 < sipa> that's copy-pasted from the table 12:11 < sipa> how would you write it instead? 12:11 < jeremyrubin> ah 12:13 < sipa> just to reiterate, do you agree that regardless of branch probability, or_b(or_b(or_b(A,B),C),D) is always strictly better than thresh(1,A,B,C,D), and a drop-in replacement for it (if the latter was legal to use in a particular context, then so is the former) 12:13 < jeremyrubin> where X: Expressive, OneOf: Signed 12:14 < jeremyrubin> and honestly i have no clue how to read the second clause 12:14 < jeremyrubin> I guess it's an implication? 12:14 < sipa> which one? 12:16 < jeremyrubin> impl Signed for T where Signed: All(T::Z : Signed, OneOf(T::X : Signed, T::Y : Signed)) 12:17 < jeremyrubin> Not sure Rust traits are perfect, but I think something similar would be a bit more comprehensible 12:17 < jeremyrubin> this is a nit though 12:17 < sipa> i have a hard time reading that 12:18 < jeremyrubin> ok, no worries I guess. just noting that any time I look at e.g. andor, I spend a nontrivial amount of time trying to read what's going on 12:18 < sipa> i can sort of guess of course, but i can't say that's obviously more readable either 12:19 < sipa> each their own biases of course 12:19 < jeremyrubin> I guess one can say it's confusing to me why subscripting makes sense 12:19 < sipa> that's fair 12:19 < jeremyrubin> because it's a property of X not the other way around? 12:20 < sipa> could use function notation, i guess 12:20 < sipa> or swap the "big" and "small" fonts 12:20 < sipa> those are kind of arbitrary 12:20 < sipa> Z_f would make more sense than f_Z 12:20 < jeremyrubin> is_expressive(andor(x,y,z)) :- is_expressive(z) and (is_expressive(y) or is_expressive(x)) 12:20 < jeremyrubin> prolog 12:21 < sipa> haha 12:21 < jeremyrubin> actually not the worst 12:21 < sipa> indeed 12:21 < jeremyrubin> might even end up with a working miniscript typechecker 12:21 < sipa> probably 12:22 < jeremyrubin> todo: rewrite miniscript types in prolog 12:22 < jeremyrubin> too bad roconnor isn't here 12:23 < jeremyrubin> actually sounds kinda fun, been meaning to learn prolog 12:23 < sipa> i liked prolog 12:24 < sipa> conceptually as a language, not to do anything practical in 12:25 < jeremyrubin> [4/26/21 12:13] just to reiterate, do you agree that regardless of branch probability, or_b(or_b(or_b(A,B),C),D) is always strictly better than thresh(1,A,B,C,D), and a drop-in replacement for it (if the latter was legal to use in a particular context, then so is the former) 12:26 < jeremyrubin> I think I buy that 12:37 < jeremyrubin> in any case, the issue with multi and pk_h has me sorta convinced on the not caring about optimality front, unless we want to somehow analyze the thresholds in multi as well to see if it's optimal 12:38 < jeremyrubin> What's the n/k for uniform multi where you should do pk_h for all keys? 12:38 < jeremyrubin> is there a straighforward formula 12:38 < sipa> there probably is 12:39 < jeremyrubin> do policy compilers discover it? 12:40 < sipa> i believe the c++ one does 12:41 < jeremyrubin> At the policy level right? 12:42 < jeremyrubin> i guess it would be crazy at the ms level since user can know probabilities 12:42 < jeremyrubin> that's a diff betweenn thresh and multi, so maybe multi doesn't mean anything for what should be parseable thresh 12:43 < sipa> i don't know what this would mean at ms level 12:43 < jeremyrubin> ah actually nvm 12:43 < sipa> it's something a policy compiler can do, and policy compilers inherently work with policies 12:44 < jeremyrubin> multi(n, a...n) should never use any pk_h 12:44 < sipa> does not compute 12:44 < jeremyrubin> uhh 12:44 < sipa> you're giving 2 distinct miniscripts 12:45 < jeremyrubin> multi(n, pk_h(key_1), ..., pk_h(key_n)) is always worse than multi(n, key_1,..., key_n) 12:45 < jeremyrubin> (except bare script, but let's ignore) 12:45 < sipa> do you mean: thresh(k, pk(A), pk(B), ...) should never be compiled to something using pk_h 12:45 < jeremyrubin> i'm talking about miniscript 12:45 < jeremyrubin> not policy 12:46 < sipa> jeremyrubin: i agree, but don't forget the l and u wrappers 12:46 < jeremyrubin> hmm why? 12:46 < jeremyrubin> What type is pk_h? 12:46 < jeremyrubin> what type does multi expect? 12:46 < sipa> which avoid the need to provide the full pubkey when dissatisfying 12:47 < sipa> multi doesn't expect any type; it's a terminal 12:47 < jeremyrubin> oh, 12:47 < sipa> its subexpressions are keys, not miniscripts 12:47 < sipa> so i guess not quite a terminal, but it isn't a combinator 12:47 < jeremyrubin> not super clear from the spec 12:48 < sipa> multi(k,key1,...,keyn) 12:48 < jeremyrubin> pk_k(key) 12:49 < jeremyrubin> wasn't clear it can't accept a K typed arg 12:49 < sipa> hm ok 12:49 < jeremyrubin> (it doesn't say anything afaict about what type key_1 is? 12:50 < jeremyrubin> maybe worth defining types L and T? Literal/terminal? 12:51 < jeremyrubin> then it is pk_k(key) key is L BT 12:51 < sipa> meh 12:51 < sipa> i don't think it's ambiguous 12:54 < jeremyrubin> I agree it's clear looking at the rust code 12:55 < jeremyrubin> Multi(usize, Vec), 12:56 < jeremyrubin> anyways, I think it is relatively interesting that we don't have the ability to make multi work with pk_h, maybe useful... but I think 20 byte keys are maybe bad? 12:57 < sipa> why? 12:57 < jeremyrubin> why are they bad? 12:57 < sipa> yes 12:58 < jeremyrubin> e.g. https://diyhpl.us/wiki/transcripts/scalingbitcoin/tokyo-2018/edgedevplusplus/p2pkh-p2wpkh-p2h-p2wsh/ 12:59 < jeremyrubin> maybe instagibbs was fudding ;) 13:00 < sipa> what specifically are you talking about? 13:00 < sipa> the 80-bit security thing? 13:01 < jeremyrubin> yes 13:01 < sipa> that doesn't apply to individual keys, only to script hashes (or in a post-musig world, keys that can be aggregates) 13:01 < sipa> for individual key hashes you really just need 128-bit hashes 13:01 < jeremyrubin> what if we want to generically handle keys passed in by user? 13:02 < jeremyrubin> we might not know if it's an aggregate key 13:02 < jeremyrubin> (btw very interested to read what the attack is on 20 byte hashes for agg keys) 13:02 < sipa> in a descriptor world you do :p 13:02 < sipa> i mean: sure, the user could have done the aggregation elsewhere 13:03 < sipa> but then i don't think they'd be using descriptors etc in the first place - you need interactive protocols etc to do so with ecdsa 13:03 < jeremyrubin> People might load watchonly? 13:03 < jeremyrubin> FWIW I am actively trying to figure out what I should be promoting as "the paradigm" for accepting keys from users in Sapio (can't make people, but can give good examples) 13:03 < sipa> in taproot descriptors i don't intend to support pk_h in the first place 13:04 < jeremyrubin> maybe it's descriptors always? 13:04 < sipa> ? 13:04 < jeremyrubin> I also considered no PubKeys, just EPKs 13:04 < sipa> ? 13:04 < jeremyrubin> in a Sapio contract, a user can pass in some public key for the contract to use. 13:05 < jeremyrubin> Maybe the paradigm I promote as "standard" should be to not do that 13:05 < sipa> what's EPK? 13:05 < jeremyrubin> ExtendedPubKey 13:05 < sipa> oh, ok 13:05 < jeremyrubin> The standard could be "we really need to know if this is a musig key, a hd key, or a plain key" 13:05 < sipa> don't have much of an opinion there 13:06 < sipa> well, that's the point of descriptors 13:06 < sipa> all information necessary for spending 13:06 < sipa> so if it's a musig key, it should be presented as such 13:06 < jeremyrubin> I thought descriptors are more at the script level than the key level? 13:06 < sipa> well yes but if you're building descriptors you'll need to get that information to put it in the output 13:07 < jeremyrubin> yeah 13:07 < jeremyrubin> I'm just trying to think of the type system constraints 13:07 < jeremyrubin> It seems it would be nice to separate descriptors into key types and script types 13:08 < jeremyrubin> these are annoying problems, e.g. someone might think they can plug in a taproot key and use the underlying scripts 13:08 < jeremyrubin> ugh 13:08 < sipa> see KEY and SCRIPT expressions listed here: https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md 13:09 < jeremyrubin> yeah, a standalone KEY descriptor type is relatively useful 13:10 < jeremyrubin> because users might e.g. generate a MuSig key for use in a protocol, and that needs to be transported somehow before the final descriptor is made 13:11 < jeremyrubin> and that's sort of the conundrum, like if Sapio contracts just accept a key with no metadata, but it's required for some security reason to know if it is aggregated or not (p2sh) we need that metadata. 13:12 < jeremyrubin> s/p2sh/pk_h/ 13:13 < sipa> btw, the attack against 160-bit script hashes is this: we construct a 2-of-2 multisig together; you give me your pubkey J; i now mount a wagner attack, looking for A on the one hand and B on the other hand such that H(multi(2,J,A)) == H(multi(1,B)), this takes 2^80 for a 160-bit H; now i tell you my pubkey is A (and if you ask, I do have the privkey for it), you construct the P2SH address from 13:13 < sipa> H(multi(2,J,A)), deposit funds into it, and steal... 13:13 < sipa> by revealing the redeemscript as multi(1,B) 13:14 < sipa> s/wagner/collision/ 13:15 < jeremyrubin> Ah i see, that's smart. If you want to prevent this, you need to precommit and add a communication round to what the PKs are 13:16 < jeremyrubin> but it isn't non-interactive safe 13:16 < sipa> indeed 13:16 < sipa> precomitting fixes this indeed 13:16 < jeremyrubin> BTW I think rust-miniscript basically punts on the issue of key descriptors 13:16 < sipa> yes 13:16 < sipa> keys are abstract types 13:16 < jeremyrubin> you can make miniscript work ith arbitrary MiniscriptKey type 13:16 < jeremyrubin> yeah 13:17 < jeremyrubin> Not sure if C++ is similar 13:17 < sipa> it is 13:17 < jeremyrubin> btw semi considering making Sapio able to call out to C++ miniscript optionally 13:17 < sipa> in the compiler, key expressions are strings for example; in signing code they're CKeyId; in descriptors they're descriptor key expressions, ... 13:18 < jeremyrubin> or e.g. any arbitrary external compiler 13:18 < jeremyrubin> sipa: BTW have you checked that C++ code is not vuln to the translation attack? 13:19 < sipa> what translation attack? 13:19 < sipa> i make no promises in general about that code, it's unreviewed entirely pretty much 13:19 < jeremyrubin> basically suppose you have a Miniscript and you are going to convert it to Miniscript 13:19 < jeremyrubin> the non duplicated key check has to happen after translation 13:19 < jeremyrubin> rust-miniscript does not do this currently 13:20 < jeremyrubin> so it's possible to bypass the dup key check 13:20 < sipa> the c++ code has no duplicate key check 13:20 < jeremyrubin> even better :p 13:20 < jeremyrubin> FWIW I agree it's probably not needed 13:20 < jeremyrubin> once you are in taproot world dup keys are ~ok as long as you add codeseps or check each branch 13:21 < sipa> yes 13:21 < jeremyrubin> err 13:21 < jeremyrubin> don't have any *duplicate* branches 13:22 < jeremyrubin> BTW; was curios on why not sign the branch path instead of just scriptcode 13:22 < sipa> i believe it doesn't add anything 13:22 < jeremyrubin> it does if you have duplicate branches 13:22 < jeremyrubin> but otherwise i agree 13:23 < jeremyrubin> And there are reasons to have duplicate branches IMO 13:23 < sipa> because the scriptpubkey is signed too, and the branch is just witness data w.r.t. to that 13:23 < sipa> interesting; can you tell me when they'd be useful? 13:23 < jeremyrubin> I think it's something like this; 13:25 < jeremyrubin> Well I guess a few reasons; let me think out loud 13:25 < jeremyrubin> 1 is if I want to give someone the script contents of a subtree but not the whole thing 13:25 < jeremyrubin> I suppose this can be done by just providing all the branches with a stubbed out other descriptors 13:26 < jeremyrubin> but i reveal more "structure" of the tree v.s. just giving an entire subtree 13:27 < sipa> i generally think that whenever you're working with complex scripts, nobody should agree to participate without knowing the full tree 13:27 < jeremyrubin> Someone also might do them (bad?) for wtxid malleability 13:27 < jeremyrubin> so signing branch path eliminates wtxid malleabiltiy 13:28 < sipa> at signing time partial information may be acceptable (i.e. the output already exists, and you could give a co-signer a script + branch + output and ask them to sign with that if they agree with spending; the other spending paths are irrelevant to them at that point) 13:28 * sipa food 13:28 < jeremyrubin> I think the use case I had in mind was more like a form of delegate on reveal 13:29 < jeremyrubin> E.g., I put my childs key in my utxos always, and then I can just tell them it's there later 13:29 < jeremyrubin> But I might not tell them the rest of my backup programs 13:29 < jeremyrubin> s/child/watchtower system/ 13:29 < jeremyrubin> ttyl 13:29 < jeremyrubin> good chat! 13:32 < jeremyrubin> I was also thinking about a possibility where you include it in multiple positions to play some fee games, but I can't think of where that'd be useful 13:32 < jeremyrubin> I guess that is one cool use case 13:33 < jeremyrubin> You can use WTXID malleability for a fee bumping protocol 13:33 < jeremyrubin> E.g., sign txn with lower tree position and feerate X, have a higher tree position w/ same script 13:33 < jeremyrubin> shrink witness, grow fees 13:34 < jeremyrubin> beneficial because it doesn't require RBF/resigning/CPFP, alternative presigneds 13:34 < jeremyrubin> but TBH sounds like a dumb party trick 13:35 < sipa> yeah, trying to think throigh that too 13:35 < sipa> but i think you can only shoot yourself in the foot 13:35 < sipa> by including the same script at multiple distinct heights 13:37 < jeremyrubin> I think most of the use cases can be emulated by tweaking the keys / pushpop a random number 13:38 < sipa> commit to the the tree depth in all derived keys :) 13:38 < jeremyrubin> that doesn't fix it 13:38 < jeremyrubin> you need the path 13:38 < jeremyrubin> e.g., two sibling scripts have same depth 13:38 < sipa> yes, but that's harmless 13:38 < sipa> they have the same weight to spend 13:38 < jeremyrubin> wtxid malleability 13:39 < sipa> oh right 13:39 < jeremyrubin> which I guess is fine 13:39 < sipa> it's undesirable 13:40 < sipa> but if that's the concern, there are much easier ways in which the script creator can construct necessarily-malleable spends 13:40 < jeremyrubin> I think it's enough of a odd case that if you want it you can get it 13:40 < jeremyrubin> yeah 15:24 -!- jeremyrubin [~jr@024-176-247-182.res.spectrum.com] has quit [Ping timeout: 265 seconds] 15:25 -!- jeremyrubin [~jr@024-176-247-182.res.spectrum.com] has joined ##miniscript 16:41 -!- shesek [~shesek@unaffiliated/shesek] has quit [Remote host closed the connection] 16:42 -!- shesek [~shesek@164.90.217.137] has joined ##miniscript 16:42 -!- shesek [~shesek@164.90.217.137] has quit [Changing host] 16:42 -!- shesek [~shesek@unaffiliated/shesek] has joined ##miniscript 16:43 -!- mol [~mol@unaffiliated/molly] has joined ##miniscript 16:46 -!- mol_ [~mol@unaffiliated/molly] has quit [Ping timeout: 268 seconds] 19:46 -!- mol [~mol@unaffiliated/molly] has quit [Read error: Connection reset by peer] 19:46 -!- mol [~mol@unaffiliated/molly] has joined ##miniscript --- Log closed Tue Apr 27 00:00:38 2021