Return-Path: Received: from smtp1.osuosl.org (smtp1.osuosl.org [IPv6:2605:bc80:3010::138]) by lists.linuxfoundation.org (Postfix) with ESMTP id 0A9AAC000E for ; Sat, 3 Jul 2021 17:50:36 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id D9A9F83E11 for ; Sat, 3 Jul 2021 17:50:35 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org X-Spam-Flag: NO X-Spam-Score: -1.899 X-Spam-Level: X-Spam-Status: No, score=-1.899 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, HTML_MESSAGE=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001] autolearn=ham autolearn_force=no Authentication-Results: smtp1.osuosl.org (amavisd-new); dkim=pass (2048-bit key) header.d=blockstream-com.20150623.gappssmtp.com Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id Mtxs_bQOTih8 for ; Sat, 3 Jul 2021 17:50:33 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.8.0 Received: from mail-qt1-x830.google.com (mail-qt1-x830.google.com [IPv6:2607:f8b0:4864:20::830]) by smtp1.osuosl.org (Postfix) with ESMTPS id B0B9983A5C for ; Sat, 3 Jul 2021 17:50:33 +0000 (UTC) Received: by mail-qt1-x830.google.com with SMTP id h2so986976qtq.13 for ; Sat, 03 Jul 2021 10:50:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=blockstream-com.20150623.gappssmtp.com; s=20150623; h=mime-version:references:in-reply-to:from:date:message-id:subject:to; bh=6tiD7blFDQ1D0d8LRjdUrByYOmPPcAZF7xYR6fOmLfM=; b=oyLvskYek/OCiTYAkDXblTtLqFYi+Y8eDkkVJZUGpQHI2VPC3OTKb3tqXk1WZk95wq k+qiHHeiylKMmtd8WMVG+ym3o4Zzyz/CsovQfcMnar0aNR/c0uk6bbGNMb/nTNDSSOJ/ nIEzChC7sM1Wn3jXi5fIZ5Famx0xR6ORpKZFSl31E6WK/jcap7H3b0Oy5CpECYZL1rMo QvtjWVkAs04iQD3/ZGpz5Dj6t5JCPeghxHB2LEbU/x+TzaIoQ8PsKB9tkJX7qGoLJKji DA3LndhXMlkLzyPGAQ7Qswc0eYHXC+HYKWFxzIVIMj9/xK7iPHQm7tN0Sn3za55KIEOD IpeA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to; bh=6tiD7blFDQ1D0d8LRjdUrByYOmPPcAZF7xYR6fOmLfM=; b=dKqZCgJS0Xn+dpK0Pz7cBN+PWBBkUxApPR+kty7k2rFZ7bD6Cm8PRbSs/Ctt8htoT0 N66ynE2jY6tkfsDNTmUz0rfEeg+x5edl6iCIbJmYOhPIAAkophgIspFEz24Dol7oixay cBIf4/EW8s990p/iH7hoyyvcIxjk7wXWc38lUhCDGxwKiD2ly3ZktmOo0OuA/Zy7CJlc VWFc7H72fBwmR9YCaxpDw8UywM7Bpy426n+eKruov+7kOoWwNn6cGmN0p4Yq5i/OVnau gTWC+Nv1exJbMylwv+ftLj19Ipp8TGgNliVwUrYjDMoYA05RD8/1/DJSU6ZSlxvFGg2b 1vBw== X-Gm-Message-State: AOAM531LzcLrff2cUUncYrbuDuyciIHTVjA2IXAbuw89KmLsqHEvvN26 2nVimSYZ/oX3gKN2XbzY1bR0SfC371QS13x7CdMSag== X-Google-Smtp-Source: ABdhPJzwqhaQm4xiMyskxqNBPr9cVL8ljH1WycKUywV+2io+gTZBdSxj+GdvoRiCYUnbyFbrMUsNLP9cJgICkYOsjq4= X-Received: by 2002:ac8:5fcf:: with SMTP id k15mr5325768qta.335.1625334632377; Sat, 03 Jul 2021 10:50:32 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: From: "Russell O'Connor" Date: Sat, 3 Jul 2021 13:50:21 -0400 Message-ID: To: Jeremy , Bitcoin Protocol Discussion Content-Type: multipart/alternative; boundary="0000000000006786e305c63bb57c" Subject: Re: [bitcoin-dev] CHECKSIGFROMSTACK/{Verify} BIP for Bitcoin X-BeenThere: bitcoin-dev@lists.linuxfoundation.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: Bitcoin Protocol Discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 03 Jul 2021 17:50:36 -0000 --0000000000006786e305c63bb57c Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Hi Jermy, As you are aware, we, and by we I mean mostly Sanket, are developing an updated OP_CHECKSIGFROMSTACK implementation for tapscript on elements. The plan here would be to effectively support the an interface to the variable-length extension of BIP-0340 schnorr signatures. BIP-0340 would dispense with DER encoding (good riddance). BIP-0340 signatures are batch verifiable along with other BIP-0340 transaction signatures and taproot tweak verification. Support for variable length messages in BIP-0340 has been discussed in < https://github.com/sipa/bips/issues/207> and an implementation has recently been merged in . The BIP has not yet been updated but the difference is that the message m does not have to be 32-bytes (it is recommended that the message be a 32-bit tagged hash or a message with a 64-bit application specific prefix). The CHECKSIGFROMSTACK operation (in tapscript) would use a stack item for this m value to BIP-0340 signature verification and would not necessarily have to be 32 bytes. I think this design we are aiming for would be perfectly suited for Bitcoin as well. On Sat, Jul 3, 2021 at 12:32 PM Jeremy via bitcoin-dev < bitcoin-dev@lists.linuxfoundation.org> wrote: > Reproduced below is the BIP text from Bitcoin Cash's (MIT-Licensed) > specification for "CheckDataSig", more or less the same thing as > CHECKSIGFROMSTACK > https://github.com/bitcoincashorg/bitcoincash.org/blob/master/spec/op_che= ckdatasig.md. > In contrast to Element's implementation, it does not have Element's bugs > around verify semantics and uses the nullfail rule, and there is a > specification document so it seemed like the easiest starting point for > discussion v.s. drafting something from scratch. > > Does anyone have any issue with adapting this exact text and > implementation to a BIP for Bitcoin using 2 OP_SUCCESSX opcodes? > > Note that with *just* CheckSigFromStack, while you can do some very > valuable use cases, but without OP_CAT it does not enable sophisticated > covenants (and as per > https://www.wpsoftware.net/andrew/blog/cat-and-schnorr-tricks-i.html just > CAT alone enables such uses). > > Design questions worth considering as modifications: > > 1. Should CSFS require some sort of tagged hash? Very likely answer is no > =E2=80=93 tags interfere with certain use cases > 2. Should CSFS split the signature=E2=80=99s R & S value stack items for = some > applications that otherwise may require OP_CAT? E.g. using a pinned R val= ue > allows you to extract a private key if ever double signed, using 2 R valu= es > allows pay-to-reveal-key contracts. Most likely answer is no, if that is > desired then OP_CAT can be introduced > 3. Should CSFS support a cheap way to reference the taproot internal or > external key? Perhaps, can be handled with undefined upgradeable keytypes= . > One might want to use the internal key, if the signed data should be vali= d > independent of the tapscript tree. One might want to use the external key= , > if the data should only be valid for a single tapscript key + tree. > 4. Should invalid public keys types be a NOP to support future extended > pubkey types? > > > > Best, > > > Jeremy > > > --- > layout: specification > title: OP_CHECKDATASIG and OP_CHECKDATASIGVERIFY Specification > category: spec > date: 2018-08-20 > activation: 1542300000 > version: 0.6 > --- > > OP_CHECKDATASIG > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > > OP_CHECKDATASIG and OP_CHECKDATASIGVERIFY check whether a signature is va= lid with respect to a message and a public key. > > OP_CHECKDATASIG permits data to be imported into a script, and have its v= alidity checked against some signing authority such as an "Oracle". > > OP_CHECKDATASIG and OP_CHECKDATASIGVERIFY are designed to be implemented = similarly to OP_CHECKSIG [1]. Conceptually, one could imagine OP_CHECKSIG f= unctionality being replaced by OP_CHECKDATASIG, along with a separate Op Co= de to create a hash from the transaction based on the SigHash algorithm. > > OP_CHECKDATASIG Specification > ----------------------------- > > ### Semantics > > OP_CHECKDATASIG fails immediately if the stack is not well formed. To be = well formed, the stack must contain at least three elements [``, ``, ``] in this order where `` is the top element and > * `` must be a validly encoded public key > * `` can be any string > * `` must follow the strict DER encoding as described in [2] and t= he S-value of `` must be at most the curve order divided by 2 as descr= ibed in [3] > > If the stack is well formed, then OP_CHECKDATASIG pops the top three elem= ents [``, ``, ``] from the stack and pushes true onto the= stack if `` is valid with respect to the raw single-SHA256 hash of `<= msg>` and `` using the secp256k1 elliptic curve. Otherwise, it pops= three elements and pushes false onto the stack in the case that `` is= the empty string and fails in all other cases. > > Nullfail is enforced the same as for OP_CHECKSIG [3]. If the signature do= es not match the supplied public key and message hash, and the signature is= not an empty byte array, the entire script fails. > > ### Opcode Number > > OP_CHECKDATASIG uses the previously unused opcode number 186 (0xba in hex= encoding) > > ### SigOps > > Signature operations accounting for OP_CHECKDATASIG shall be calculated t= he same as OP_CHECKSIG. This means that each OP_CHECKDATASIG shall be count= ed as one (1) SigOp. > > ### Activation > > Use of OP_CHECKDATASIG, unless occuring in an unexecuted OP_IF branch, wi= ll make the transaction invalid if it is included in a block where the medi= an timestamp of the prior 11 blocks is less than 1542300000. > > ### Unit Tests > > - ` OP_CHECKDATASIG` fails if 15 November 2018 proto= col upgrade is not yet activated. > - ` OP_CHECKDATASIG` fails if there are fewer than 3 items on= stack. > - ` OP_CHECKDATASIG` fails if `` is not a va= lidly encoded public key. > - ` OP_CHECKDATASIG` fails if `` is not a valid= ly encoded signature with strict DER encoding. > - ` OP_CHECKDATASIG` fails if signature `` is n= ot empty and does not pass the Low S check. > - ` OP_CHECKDATASIG` fails if signature `` is n= ot empty and does not pass signature validation of `` and ``. > - ` OP_CHECKDATASIG` pops three elements and pushes = false onto the stack if `` is an empty byte array. > - ` OP_CHECKDATASIG` pops three elements and pushes = true onto the stack if `` is a valid signature of `` with respect= to ``. > > OP_CHECKDATASIGVERIFY Specification > ----------------------------------- > > ### Semantics > > OP_CHECKDATASIGVERIFY is equivalent to OP_CHECKDATASIG followed by OP_VER= IFY. It leaves nothing on the stack, and will cause the script to fail imme= diately if the signature check does not pass. > > ### Opcode Number > > OP_CHECKDATASIGVERIFY uses the previously unused opcode number 187 (0xbb = in hex encoding) > > ### SigOps > > Signature operations accounting for OP_CHECKDATASIGVERIFY shall be calcul= ated the same as OP_CHECKSIGVERIFY. This means that each OP_CHECKDATASIGVER= IFY shall be counted as one (1) SigOp. > > ### Activation > > Use of OP_CHECKDATASIGVERIFY, unless occuring in an unexecuted OP_IF bran= ch, will make the transaction invalid if it is included in a block where th= e median timestamp of the prior 11 blocks is less than 1542300000. > > ### Unit Tests > > - ` OP_CHECKDATASIGVERIFY` fails if 15 November 2018= protocol upgrade is not yet activated. > - ` OP_CHECKDATASIGVERIFY` fails if there are fewer than 3 it= em on stack. > - ` OP_CHECKDATASIGVERIFY`fails if `` is not= a validly encoded public key. > - ` OP_CHECKDATASIGVERIFY` fails if `` is not a= validly encoded signature with strict DER encoding. > - ` OP_CHECKDATASIGVERIFY` fails if signature `= ` is not empty and does not pass the Low S check. > - ` OP_CHECKDATASIGVERIFY` fails if `` is not a= valid signature of `` with respect to ``. > - ` OP_CHECKDATASIGVERIFY` pops the top three stack = elements if `` is a valid signature of `` with respect to ``. > > Sample Implementation [4, 5] > ---------------------------- > > ```c++ > case OP_CHECKDATASIG: > case OP_CHECKDATASIGVERIFY: { > // Make sure this remains an error before activat= ion. > if ((flags & SCRIPT_ENABLE_CHECKDATASIG) =3D=3D 0= ) { > return set_error(serror, SCRIPT_ERR_BAD_OPCOD= E); > } > > // (sig message pubkey -- bool) > if (stack.size() < 3) { > return set_error( > serror, SCRIPT_ERR_INVALID_STACK_OPERATIO= N); > } > > valtype &vchSig =3D stacktop(-3); > valtype &vchMessage =3D stacktop(-2); > valtype &vchPubKey =3D stacktop(-1); > > if (!CheckDataSignatureEncoding(vchSig, flags, > serror) || > !CheckPubKeyEncoding(vchPubKey, flags, serror= )) { > // serror is set > return false; > } > > bool fSuccess =3D false; > if (vchSig.size()) { > valtype vchHash(32); > CSHA256() > .Write(vchMessage.data(), vchMessage.size= ()) > .Finalize(vchHash.data()); > uint256 message(vchHash); > CPubKey pubkey(vchPubKey); > fSuccess =3D pubkey.Verify(message, vchSig); > } > > if (!fSuccess && (flags & SCRIPT_VERIFY_NULLFAIL)= && > vchSig.size()) { > return set_error(serror, SCRIPT_ERR_SIG_NULLF= AIL); > } > > popstack(stack); > popstack(stack); > popstack(stack); > stack.push_back(fSuccess ? vchTrue : vchFalse); > if (opcode =3D=3D OP_CHECKDATASIGVERIFY) { > if (fSuccess) { > popstack(stack); > } else { > return set_error(serror, > SCRIPT_ERR_CHECKDATASIGV= ERIFY); > } > } > } break; > ``` > > Sample Usage > ------------ > > The following example shows a spend and redeem script for a basic use of = CHECKDATASIG. This example validates the signature of some data, provides = a placeholder where you would then process that data, and finally allows on= e of 2 signatures to spend based on the outcome of the data processing. > > ### spend script: > ``` > push txsignature > push txpubkey > push msg > push sig > ``` > ### redeem script: > ``` > (txsig, txpubkey msg, sig) > OP_OVER (txsig, txpubkey, msg, sig, msg) > push data pubkey (txsig, txpubkey, msg, sig, msg, pubkey) > OP_CHECKDATASIGVERIFY (txsig, txpubkey, msg) > ``` > Now that msg is on the stack top, the script can write predicates on it, > resulting in the message being consumed and a true/false condition left o= n the stack: (txpubkey, txsig, boolean) > ``` > OP_IF (txsig, txpubkey) > OP_DUP (txsig, txpubkey, txpubkey) > OP_HASH160 (txsig, txpubkey, address) > push (txsig, txpubkey, address, p2pkh spend ad= dress) > OP_EQUALVERIFY (txsig, txpubkey) > OP_CHECKSIG > OP_ELSE > (same as if clause but a different ) > OP_ENDIF > ``` > > History > ------- > > This specification is based on Andrew Stone=E2=80=99s OP_DATASIGVERIFY pr= oposal [6, 7]. It is modified from Stone's original proposal based on a syn= thesis of all the peer-review and feedback received [8]. > > References > ---------- > > [1] [OP_CHECKSIG](https://en.bitcoin.it/wiki/OP_CHECKSIG) > > [2] [Strict DER Encoding](https://github.com/bitcoin/bips/blob/master/bip= -0066.mediawiki) > > [3] [Low-S and Nullfail Specification](https://github.com/bitcoin/bips/bl= ob/master/bip-0146.mediawiki) > > [4] [Bitcoin ABC implementation](https://reviews.bitcoinabc.org/D1621) > > [5] [Bitcoin ABC implementation update](https://reviews.bitcoinabc.org/D1= 646) > > [6] [Andrew Stone=E2=80=99s OP_DATASIGVERIFY](https://github.com/BitcoinU= nlimited/BitcoinUnlimited/blob/bucash1.3.0.0/doc/opdatasigverify.md) > > [7] [Andrew Stone's article on Scripting](https://medium.com/@g.andrew.st= one/bitcoin-scripting-applications-decision-based-spending-8e7b93d7bdb9) > > [8] [Peer Review of Andrew Stone's Proposal](https://github.com/bitcoinca= shorg/bitcoincash.org/pull/10) > > > -- > @JeremyRubin > > _______________________________________________ > bitcoin-dev mailing list > bitcoin-dev@lists.linuxfoundation.org > https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev > --0000000000006786e305c63bb57c Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Hi Jermy,

As you are aware, = we, and by we I mean mostly Sanket, are developing an updated OP_CHECKSIGFR= OMSTACK implementation for tapscript on elements.=C2=A0 The plan here would= be to effectively support the an interface to the variable-length extensio= n of BIP-0340 schnorr signatures.

BIP-0340 would d= ispense with DER encoding (good riddance).
BIP-0340 signatures ar= e batch verifiable along with other BIP-0340 transaction signatures and tap= root tweak verification.
Support for variable length messages in = BIP-0340 has been discussed in <https://github.com/sipa/bips/issues/207> and an implemen= tation has recently been merged in <https://github.com/bitcoin-core/secp256k1/pull/8= 44>.=C2=A0 The BIP has not yet been updated but the difference is th= at the message m does not have to be 32-bytes (it is recommended that the m= essage be a 32-bit tagged hash or a message with a 64-bit application speci= fic prefix). The CHECKSIGFROMSTACK operation (in tapscript) would use a sta= ck item for this m value to BIP-0340 signature verification and would not n= ecessarily have to be 32 bytes.

I think this d= esign we are aiming for would be perfectly suited for Bitcoin as well.
<= /div>

On Sat, Jul 3, 2021 at 12:32 PM Jeremy via bitcoin-dev <bitcoin-dev= @lists.linuxfoundation.org> wrote:
Rep= roduced below is the BIP text from Bitcoin Cash's (MIT-Licensed) specif= ication for "CheckDataSig", more or less the same thing as CHECKS= IGFROMSTACK https://github.com/bit= coincashorg/bitcoincash.org/blob/master/spec/op_checkdatasig.md. In con= trast to Element's implementation, it does not have Element's bugs = around verify semantics and uses the nullfail rule, and there is a specific= ation document so it seemed like the easiest starting point for discussion = v.s. drafting something from scratch.
Does anyone have any issue with adapting this exact text and implementatio= n to a BIP for Bitcoin using 2 OP_SUCCESSX opcodes?

Note that with *just* Che= ckSigFromStack, while you can do some very valuable use cases, but without = OP_CAT it does not enable sophisticated covenants (and as per=C2=A0https://www.wpsoftware.net/andrew/blog/cat-and-schnorr-tri= cks-i.html just CAT alone enables such uses).

Design questions w= orth considering as modifications:

1.= Should CSFS require some sort of tagged hash? Very likely answer is no =E2= =80=93 tags interfere with certain use cases
2. Should CSFS split the si= gnature=E2=80=99s R & S value stack items for some applications that ot= herwise may require OP_CAT? E.g. using a pinned R value allows you to extra= ct a private key if ever double signed, using 2 R values allows pay-to-reve= al-key contracts. Most likely answer is no, if that is desired then OP_CAT = can be introduced
3. Should CSFS support a cheap way to reference the ta= proot internal or external key? Perhaps, can be handled with undefined upgr= adeable keytypes. One might want to use the internal key, if the signed dat= a should be valid independent of the tapscript tree. One might want to use = the external key, if the data should only be valid for a single tapscript k= ey + tree.
4. Should invalid public keys types be a NOP to support futur= e extended pubkey types?



Best,
=

Jeremy

---
layout: specification
title: OP_CHECKDATASIG and OP_CHECKDATASIGVERIFY Specification
category: spec
date: 2018-08-20
activation: 1542300000
version: 0.6
---

OP_CHECKDATASIG
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

OP_CHECKDATASIG and OP_CHECKDATASIGVERIFY check whether a signature is vali=
d with respect to a message and a public key.

OP_CHECKDATASIG permits data to be imported into a script, and have its val=
idity checked against some signing authority such as an "Oracle".

OP_CHECKDATASIG and OP_CHECKDATASIGVERIFY are designed to be implemented si=
milarly to OP_CHECKSIG [1]. Conceptually, one could imagine OP_CHECKSIG fun=
ctionality being replaced by OP_CHECKDATASIG, along with a separate Op Code=
 to create a hash from the transaction based on the SigHash algorithm.

OP_CHECKDATASIG Specification
-----------------------------

### Semantics

OP_CHECKDATASIG fails immediately if the stack is not well formed. To be we=
ll formed, the stack must contain at least three elements [`<sig>`, `=
<msg>`, `<pubKey>`] in this order where `<pubKey>` is the=
 top element and
  * `<pubKey>` must be a validly encoded public key
  * `<msg>` can be any string
  * `<sig>` must follow the strict DER encoding as described in [2] a=
nd the S-value of `<sig>` must be at most the curve order divided by =
2 as described in [3]

If the stack is well formed, then OP_CHECKDATASIG pops the top three elemen=
ts [`<sig>`, `<msg>`, `<pubKey>`] from the stack and push=
es true onto the stack if `<sig>` is valid with respect to the raw si=
ngle-SHA256 hash of `<msg>` and `<pubKey>` using the secp256k1 =
elliptic curve. Otherwise, it pops three elements and pushes false onto the=
 stack in the case that `<sig>` is the empty string and fails in all =
other cases.

Nullfail is enforced the same as for OP_CHECKSIG [3]. If the signature does=
 not match the supplied public key and message hash, and the signature is n=
ot an empty byte array, the entire script fails.

### Opcode Number

OP_CHECKDATASIG uses the previously unused opcode number 186 (0xba in hex e=
ncoding)

### SigOps

Signature operations accounting for OP_CHECKDATASIG shall be calculated the=
 same as OP_CHECKSIG. This means that each OP_CHECKDATASIG shall be counted=
 as one (1) SigOp.

### Activation

Use of OP_CHECKDATASIG, unless occuring in an unexecuted OP_IF branch, will=
 make the transaction invalid if it is included in a block where the median=
 timestamp of the prior 11 blocks is less than 1542300000.

### Unit Tests

 - `<sig> <msg> <pubKey> OP_CHECKDATASIG` fails if 15 Nov=
ember 2018 protocol upgrade is not yet activated.
 - `<sig> <msg> OP_CHECKDATASIG` fails if there are fewer than =
3 items on stack.
 - `<sig> <msg> <pubKey> OP_CHECKDATASIG` fails if `<p=
ubKey>` is not a validly encoded public key.
 - `<sig> <msg> <pubKey> OP_CHECKDATASIG` fails if `<s=
ig>` is not a validly encoded signature with strict DER encoding.
 - `<sig> <msg> <pubKey> OP_CHECKDATASIG` fails if signat=
ure `<sig>` is not empty and does not pass the Low S check.
 - `<sig> <msg> <pubKey> OP_CHECKDATASIG` fails if signat=
ure `<sig>` is not empty and does not pass signature validation of `&=
lt;msg>` and `<pubKey>`.
 - `<sig> <msg> <pubKey> OP_CHECKDATASIG` pops three elem=
ents and pushes false onto the stack if `<sig>` is an empty byte arra=
y.
 - `<sig> <msg> <pubKey> OP_CHECKDATASIG` pops three elem=
ents and pushes true onto the stack if `<sig>` is a valid signature o=
f `<msg>` with respect to `<pubKey>`.

OP_CHECKDATASIGVERIFY Specification
-----------------------------------

### Semantics

OP_CHECKDATASIGVERIFY is equivalent to OP_CHECKDATASIG followed by OP_VERIF=
Y. It leaves nothing on the stack, and will cause the script to fail immedi=
ately if the signature check does not pass.

### Opcode Number

OP_CHECKDATASIGVERIFY uses the previously unused opcode number 187 (0xbb in=
 hex encoding)

### SigOps

Signature operations accounting for OP_CHECKDATASIGVERIFY shall be calculat=
ed the same as OP_CHECKSIGVERIFY. This means that each OP_CHECKDATASIGVERIF=
Y shall be counted as one (1) SigOp.

### Activation

Use of OP_CHECKDATASIGVERIFY, unless occuring in an unexecuted OP_IF branch=
, will make the transaction invalid if it is included in a block where the =
median timestamp of the prior 11 blocks is less than 1542300000.

### Unit Tests

 - `<sig> <msg> <pubKey> OP_CHECKDATASIGVERIFY` fails if =
15 November 2018 protocol upgrade is not yet activated.
 - `<sig> <msg> OP_CHECKDATASIGVERIFY` fails if there are fewer=
 than 3 item on stack.
 - `<sig> <msg> <pubKey> OP_CHECKDATASIGVERIFY`fails if `=
<pubKey>` is not a validly encoded public key.
 - `<sig> <msg> <pubKey> OP_CHECKDATASIGVERIFY` fails if =
`<sig>` is not a validly encoded signature with strict DER encoding.
 - `<sig> <msg> <pubKey> OP_CHECKDATASIGVERIFY` fails if =
signature `<sig>` is not empty and does not pass the Low S check.
 - `<sig> <msg> <pubKey> OP_CHECKDATASIGVERIFY` fails if =
`<sig>` is not a valid signature of `<msg>` with respect to `&l=
t;pubKey>`.
 - `<sig> <msg> <pubKey> OP_CHECKDATASIGVERIFY` pops the =
top three stack elements if `<sig>` is a valid signature of `<msg&=
gt;` with respect to `<pubKey>`.

Sample Implementation [4, 5]
----------------------------

```c++
                    case OP_CHECKDATASIG:
                    case OP_CHECKDATASIGVERIFY: {
                        // Make sure this remains an error before activatio=
n.
                        if ((flags & SCRIPT_ENABLE_CHECKDATASIG) =3D=3D=
 0) {
                            return set_error(serror, SCRIPT_ERR_BAD_OPCODE)=
;
                        }

                        // (sig message pubkey -- bool)
                        if (stack.size() < 3) {
                            return set_error(
                                serror, SCRIPT_ERR_INVALID_STACK_OPERATION)=
;
                        }

                        valtype &vchSig =3D stacktop(-3);
                        valtype &vchMessage =3D stacktop(-2);
                        valtype &vchPubKey =3D stacktop(-1);

                        if (!CheckDataSignatureEncoding(vchSig, flags,
                                                        serror) ||
                            !CheckPubKeyEncoding(vchPubKey, flags, serror))=
 {
                            // serror is set
                            return false;
                        }

                        bool fSuccess =3D false;
                        if (vchSig.size()) {
                            valtype vchHash(32);
                            CSHA256()
                                .Write(vchMessage.data(), vchMessage.size()=
)
                                .Finalize(vchHash.data());
                            uint256 message(vchHash);
                            CPubKey pubkey(vchPubKey);
                            fSuccess =3D pubkey.Verify(message, vchSig);
                        }

                        if (!fSuccess && (flags & SCRIPT_VERIFY=
_NULLFAIL) &&
                            vchSig.size()) {
                            return set_error(serror, SCRIPT_ERR_SIG_NULLFAI=
L);
                        }

                        popstack(stack);
                        popstack(stack);
                        popstack(stack);
                        stack.push_back(fSuccess ? vchTrue : vchFalse);
                        if (opcode =3D=3D OP_CHECKDATASIGVERIFY) {
                            if (fSuccess) {
                                popstack(stack);
                            } else {
                                return set_error(serror,
                                                 SCRIPT_ERR_CHECKDATASIGVER=
IFY);
                            }
                        }
                    } break;
```

Sample Usage
------------

The following example shows a spend and redeem script for a basic use of CH=
ECKDATASIG.  This example validates the signature of some data, provides a =
placeholder where you would then process that data, and finally allows one =
of 2 signatures to spend based on the outcome of the data processing.

### spend script:
```
push txsignature
push txpubkey
push msg
push sig
```
### redeem script:
```
                                (txsig, txpubkey msg, sig)
OP_OVER                         (txsig, txpubkey, msg, sig, msg)
push data pubkey                (txsig, txpubkey, msg, sig, msg, pubkey)
OP_CHECKDATASIGVERIFY           (txsig, txpubkey, msg)
```
Now that msg is on the stack top, the script can write predicates on it,
resulting in the message being consumed and a true/false condition left on =
the stack: (txpubkey, txsig, boolean)
```
OP_IF                           (txsig, txpubkey)
  OP_DUP                        (txsig, txpubkey, txpubkey)
  OP_HASH160                    (txsig, txpubkey, address)
  push <p2pkh spend address>    (txsig, txpubkey, address, p2pkh spen=
d address)
  OP_EQUALVERIFY                (txsig, txpubkey)
  OP_CHECKSIG
OP_ELSE
  (same as if clause but a different <p2pkh spend address>)
OP_ENDIF
```

History
-------

This specification is based on Andrew Stone=E2=80=99s OP_DATASIGVERIFY prop=
osal [6, 7]. It is modified from Stone's original proposal based on a s=
ynthesis of all the peer-review and feedback received [8].

References
----------

[1] [OP_CHECKSIG](https://en.bitcoin.it/wiki/OP_CHECKSIG)

[2] [Strict DER Encoding](https://github.com/bitcoin/bips=
/blob/master/bip-0066.mediawiki)

[3] [Low-S and Nullfail Specification](https://github.com=
/bitcoin/bips/blob/master/bip-0146.mediawiki)

[4] [Bitcoin ABC implementation](https://reviews.bitcoinabc.org/D1621)

[5] [Bitcoin ABC implementation update](https://reviews.bitcoinabc.org/D1646)

[6] [Andrew Stone=E2=80=99s OP_DATASIGVERIFY](https://github.com/BitcoinUnlimited/BitcoinUnlimited/b=
lob/bucash1.3.0.0/doc/opdatasigverify.md)

[7] [Andrew Stone's article on Scripting](https://medium.com/@g.andrew.stone/bitcoin-scr=
ipting-applications-decision-based-spending-8e7b93d7bdb9)

[8] [Peer Review of Andrew Stone's Proposal](https://githu=
b.com/bitcoincashorg/bitcoincash.org/pull/10)

_______________________________________________
bitcoin-dev mailing list
= bitcoin-dev@lists.linuxfoundation.org
https://lists.linuxfoundation.org/mail= man/listinfo/bitcoin-dev
--0000000000006786e305c63bb57c--