On Thu, Jan 27, 2022 at 8:34 PM Anthony Towns <aj@erisian.com.au> wrote:
> An Alternative Proposal::
>  ...

> For similar reasons, TXHASH is not amenable to extending the set of txflags
> at a later date.

> I believe the difficulties with upgrading TXHASH can be mitigated by
> designing a robust set of TXHASH flags from the start.  For example having
> bits to control whether [...]

I don't think that's really feasible -- eg, what you propose don't cover
SIGHASH_GROUP:

 https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2021-July/019243.html

For more complex interactions, I was imagining combining this TXHASH proposal with CAT and/or rolling SHA256 opcodes.  If TXHASH ended up supporting relative or absolute input/output indexes then users could assemble the hashes of the particular inputs and outputs they care about into a single signed message.
 
> That all said, even if other txhash flag modes are needed in the future,
> adding TXHASH2 always remains an option.

I think baking this in from day 0 might be better: make TXHASH be
a multibyte opcode, so that when you decode "0xBB" on the stack,
you also decode a serialize.h:VarInt as the version number.

I wouldn't be opposed to this.

> '<anyprevout-pubkey> CHECKSIGVERIFY can be simulated by '<apo_style_flag> TXHASH <pubkey> CHECKSIGFROMSTACKVERIFY'.

I don't think that's quite right. BIP 118 anyprevout is done by taking
the pubkey "P", marking it as "APO-capable" (by prefixing it with 0x01),
and then getting a sighash and sig from the witness. Doing the same
with TXHASH/CSFSV would just be replacing "<APO:P> CHECKSIGVERIFY" with
"TXHASH <P> CSFSV" with the witness providing both the signature and
txhash flag, just as separate elements rather than concatenated. (The
"APO-capable" part is implicit in the "TXHASH" opcode)

Indeed. The TXHASH variant does require splitting the signature and txhash flag across two stack items.  So it wouldn't be an operationally identical drop in replacement.
 
> In addition to the CTV and ANYPREVOUT applications, with
> CHECKSIGFROMSTACKVERIFY we can verify signatures on arbitrary messages
> signed by oracles for oracle applications.  This is where we see the
> benefit of decomposing operations into primitive pieces.  By giving users
> the ability to program their own use cases from components, we get more
> applications out of fewer op codes!

While I see the appeal of this from a language design perspective;
I'm not sure it's really the goal we want. When I look at bitcoin's
existing script, I see a lot of basic opcodes to do simple arithmetic and
manipulate the stack in various ways, but the opcodes that are actually
useful are more "do everything at once" things like check(multi)sig or
sha256. It seems like what's most useful on the blockchain is a higher
level language, rather than more of blockchain assembly language made
up of small generic pieces. I guess "program their own use cases from
components" seems to be coming pretty close to "write your own crypto
algorithms" here...

Which operations in Script are actually composable today?

CHECKSIG composes with nothing else (other than possibly other CHECKSIGs) as there are no other operations that manipulate pubkey keys or signature data.

CLTV and CSV in principle can be composed with addition and subtraction and comparison operations.  But where are you going to get other values to add and subtract from?  I suppose you could compare the relative and absolute locktimes to each other.

What do the HASH functions compose with?  Without CAT you cannot construct messages to hash.  You can hash the result of the arithmetic operations, but you are limited to hashing 32-bit (or 33-bit if you are generous) strings, which is too little entropy to have any security properties.  You can hash a public key or a signature I suppose.

I don't think there is much in the way of lessons to be drawn from how we see Bitcoin Script used today with regards to programs built out of reusable components.  User's haven't been composing programs, not because they don't find composition useful, but rather because the existing primitives do not lend themselves to being composed at all.

There is one aspect of Bitcoin Script that is composable, which is (monotone) boolean combinations of the few primitive transaction conditions that do exist.  The miniscript language captures nearly the entirety of what is composable in Bitcoin Script today: which amounts to conjunctions, disjunctions (and thresholds) of signatures, locktimes, and revealing hash preimages.

TXHASH + CSFSV won't be enough by itself to allow for very interesting programs Bitcoin Script yet, we still need CAT and friends for that, but CSFSV is at least a step in that direction.  CSFSV can take arbitrary messages and these messages can be fixed strings, or they can be hashes of strings (that need to be revealed), or they can be hashes returned from TXHASH, or they can be locktime values, or they can be values that are added or subtracted from locktime values, or they can be values used for thresholds, or they can be other pubkeys for delegation purposes, or they can be other signatures ... for who knows what purpose.