Replying to Avatar Rusty Russell

yay! Thanks for the feedback!

> a) if the selector is meant to be scriptnum compatible, would be good to make that clear (ie 513 on the stack is interpreted as outputscript+collate not as 0x0102 and tested as outputamount+version.

This builds on the previous BIP, which changes this, but I agree it needs to be explicit.

> b) please use hex for the selector values...

Done.

c) you might consider two separate functions [op_tx and op_txcollate] instead of using a bit selector; makes it slightly easier to statically validate expected stack depth, though still not great.

Understandable, but since we have a bit selector anyway, I prefer this approach.

> d) not sure the ordering of collate-vs-noncollate makes sense - should "output" just always put the new data at the start of the buffer or the end of the stack do you consistently get the last output thing first?

Good catch!

I've switched the definition around to the order I think of it, i.e. txid order. But it means the definition of "output" for the non-collate case is a bit awkward: `"output" means "push a new element on the stack under the previous output elements" (i.e. the last output will be the top stack element).`

> e) input(num)witness seems like a bad idea to me, constraining how other inputs are spent just seems like asking for complexity and bugs.

I agree, so don't do that. However, it's possibly useful too, so it's allowed. Not like you're going to do this "accidentally".

> f) having a way to pull info from other inputs' annex (and your own) would be a win though, but maybe that should be an op_annex getter.

I was tempted to use separate bits for WITNESS_STACK, WITNESS_TAPSCRIPT and WITNESS_ANNEX for this reason, but the entire witness is more robust against future SegWit output types: I don't have to worry too hard about how to interpret those fields.

Note that getting the ANNEX is awkard, due to lack of DROPN. See the very-unfleshed-out OP_MULTI which would make this tenable.

> g) personally I don't think upgradability is a win here, better to upgrade by defining a new opcode than have weird semantics that people will forget to check.

Perhaps, but this argument seems very weak. Who will forget to check? The only possibility is someone who allows arbitrary selection_vectors in their script, and they're already kinda messed up.

> h) the ctv comparison at the end is inaccurate - ctv also commits to scriptSigs.

Oh, good catch! Fixed.

> i) automatically hashing it as you go rather than pushing the whole thing to the stack then hashing it seems worth considering

That seems like a regression to me. People have been proposing combo opcodes precisely because they haven't a decent costing model.

1. OP_SHA256 is a single opcode.

2. You can also now easily append/prepend/insert data that you want to commit to.

3. You have 4MB of stack, which is hard to exhaust (you can, using metadata, but it's difficult).

4. Hashing directly would reduce the cost from 12 varops per byte to 10, and you get 5200 varops (!) for every tx byte.

To reflect the depth of my gratitute for your feedback, I shall now review your lisp approach. Seems the least I can do! 💜

Forums or email seen better for long responses....

re: optxcollate as a separate opcode / auto hashing - I guess I'm thinking that [txcollate+sha256] could be added as a new opcode to existing tapscript without requiring varops budgeting to be applied to existing opcodes, so might be interesting to separate out and explore more immediately.

I think you could exhaust 4MB of stack with a tx spending 400 inputs each with a 10kB scriptPubKey ([1SUB DUP NOTIF p CHECKSIGVERIFY ENDIF]*250 or so for a 1 of 250 multisig maybe) and specifying input_scriptpubkey. Hashing as you go with collate would make that okay.

re: output order, "push a new element under .. last output will be on top" seems contradictory to me. The last/most recent element will be under everything which is the bottom? First/oldest output should be the top and first to be popped afaics.

You might consider moving the witness data to the end of the output and including a flag byte do that you can construct the wtxid correctly with only a single txcollate invocation.

I don't think scriptsig or witness in general is a good thing to introspection, it has too high a risk of making spending utxos together incompatible (already a problem with nlocktime). Pulling out any data requires knowing the script structure and execution path (and also requires DROPN afaics particularly if the other script is using optx or checkmultisig or opmulti), which is hard to get right and easy to get wrong, as occurred with the ctv-bitvm idea recently.

The intent with the annex is to apply some simple structure to it as consensus, so that pulling data from it can be done easily and safely. [X I ANNEX] to get the entry tagged X from the annex for input I (I=-1 for current input perhaps) would be a thought. That would imply the annex should only include a single entry per tag (not clear to me if multiple entries for a tag is desirable or not). I'm leaning towards individual annex entries being limited to perhaps 127 bytes - if you want longer, [SHA256 X -1 ANNEX EQUALVERIFY] lets you put the long thing on the witness while still committing to it.

One reason to limit how much you can introspect other inputs is the costing - in a coinjoin eg you can know in advance what the pubkey etc is but the witness could be arbitrarily large and examining it could increase your script's costs more than you might expect. That has some risk of an O(n^2) blow out, which isn't a consensus risk due to the budgeting, but still seems undesirable if it forces your costs to go up in unexpected ways that you can't really know until you see how the other guy is going to authorise.

Reply to this note

Please Login to reply.

Discussion

No replies yet.