Subject: Re: [bitcoin-dev] TXHASH + CHECKSIGFROMSTACKVERIFY in lieu of CTV and ANYPREVOUT

From: "Russell O'Connor" <[email-masked]>
Date: Fri, 28 Jan 2022 08:56:25 -0500

On Thu, Jan 27, 2022 at 8:34 PM Anthony Towns <[email-masked]> 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.