From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from smtp1.osuosl.org (smtp1.osuosl.org [140.211.166.138]) by lists.linuxfoundation.org (Postfix) with ESMTP id AB13AC000E for ; Sat, 3 Jul 2021 18:31:02 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id A005F83DAC for ; Sat, 3 Jul 2021 18:31:02 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org X-Spam-Flag: NO X-Spam-Score: -4.199 X-Spam-Level: X-Spam-Status: No, score=-4.199 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, HTML_MESSAGE=0.001, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_PASS=-0.001] autolearn=ham autolearn_force=no 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 lPoH9xxOPkJO for ; Sat, 3 Jul 2021 18:31:00 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.8.0 Received: from outgoing.mit.edu (outgoing-auth-1.mit.edu [18.9.28.11]) by smtp1.osuosl.org (Postfix) with ESMTPS id 5ACCB83DA2 for ; Sat, 3 Jul 2021 18:31:00 +0000 (UTC) Received: from mail-il1-f171.google.com (mail-il1-f171.google.com [209.85.166.171]) (authenticated bits=0) (User authenticated as jlrubin@ATHENA.MIT.EDU) by outgoing.mit.edu (8.14.7/8.12.4) with ESMTP id 163IUwPA020133 (version=TLSv1/SSLv3 cipher=AES128-GCM-SHA256 bits=128 verify=NOT) for ; Sat, 3 Jul 2021 14:30:58 -0400 Received: by mail-il1-f171.google.com with SMTP id z1so13218450ils.0 for ; Sat, 03 Jul 2021 11:30:58 -0700 (PDT) X-Gm-Message-State: AOAM5321FUQreYnM7zAxzkJ/vP/ZmC04KDyYCfOj3KkW8W2fmwA0EHUM WsqW1l7o8QrhKXsUq1UBG8APsoPNE1hU6Zd2ZqM= X-Google-Smtp-Source: ABdhPJyEuztlkc/a5KebV5ukNFkephX3asdRGenawAyNZfvCWkTslE1Ve3TNEbUehFz0lg/FyhWdzG1rzJ4jZLTZa/A= X-Received: by 2002:a92:6f0a:: with SMTP id k10mr4211114ilc.105.1625337057853; Sat, 03 Jul 2021 11:30:57 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: From: Jeremy Date: Sat, 3 Jul 2021 11:30:45 -0700 X-Gmail-Original-Message-ID: Message-ID: To: "Russell O'Connor" Content-Type: multipart/alternative; boundary="000000000000f945a705c63c4597" Cc: Bitcoin Protocol Discussion 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 18:31:02 -0000 --000000000000f945a705c63c4597 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Awesome to hear that! Actually I don't think I did know (or I forgot/didn't catch it) that there was an updated spec for elements, I searched around for what I could find and came up empty handed. Do you have any links for that? That sounds perfect to me. On Sat, Jul 3, 2021, 10:50 AM Russell O'Connor wrote: > 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. T= he > 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 < > https://github.com/bitcoin-core/secp256k1/pull/844>. 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_ch= eckdatasig.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 n= o >> =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 va= lue >> allows you to extract a private key if ever double signed, using 2 R val= ues >> 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 keytype= s. >> One might want to use the internal key, if the signed data should be val= id >> independent of the tapscript tree. One might want to use the external ke= y, >> 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 v= alid with respect to a message and a public key. >> >> OP_CHECKDATASIG permits data to be imported into a script, and have its = validity 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 = functionality being replaced by OP_CHECKDATASIG, along with a separate Op C= ode 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 = the S-value of `` must be at most the curve order divided by 2 as desc= ribed in [3] >> >> If the stack is well formed, then OP_CHECKDATASIG pops the top three ele= ments [``, ``, ``] from the stack and pushes true onto th= e stack if `` is valid with respect to the raw single-SHA256 hash of `= ` and `` using the secp256k1 elliptic curve. Otherwise, it pop= s three elements and pushes false onto the stack in the case that `` i= s the empty string and fails in all other cases. >> >> Nullfail is enforced the same as for OP_CHECKSIG [3]. If the signature d= oes not match the supplied public key and message hash, and the signature i= s not an empty byte array, the entire script fails. >> >> ### Opcode Number >> >> OP_CHECKDATASIG uses the previously unused opcode number 186 (0xba in he= x encoding) >> >> ### SigOps >> >> Signature operations accounting for OP_CHECKDATASIG shall be calculated = the same as OP_CHECKSIG. This means that each OP_CHECKDATASIG shall be coun= ted as one (1) SigOp. >> >> ### Activation >> >> Use of OP_CHECKDATASIG, unless occuring in an unexecuted OP_IF branch, w= ill make the transaction invalid if it is included in a block where the med= ian timestamp of the prior 11 blocks is less than 1542300000. >> >> ### Unit Tests >> >> - ` OP_CHECKDATASIG` fails if 15 November 2018 prot= ocol upgrade is not yet activated. >> - ` OP_CHECKDATASIG` fails if there are fewer than 3 items o= n stack. >> - ` OP_CHECKDATASIG` fails if `` is not a v= alidly encoded public key. >> - ` OP_CHECKDATASIG` fails if `` is not a vali= dly encoded signature with strict DER encoding. >> - ` OP_CHECKDATASIG` fails if signature `` is = not empty and does not pass the Low S check. >> - ` OP_CHECKDATASIG` fails if signature `` is = not 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 respec= t to ``. >> >> OP_CHECKDATASIGVERIFY Specification >> ----------------------------------- >> >> ### Semantics >> >> OP_CHECKDATASIGVERIFY is equivalent to OP_CHECKDATASIG followed by OP_VE= RIFY. It leaves nothing on the stack, and will cause the script to fail imm= ediately 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 calcu= lated the same as OP_CHECKSIGVERIFY. This means that each OP_CHECKDATASIGVE= RIFY shall be counted as one (1) SigOp. >> >> ### Activation >> >> Use of OP_CHECKDATASIGVERIFY, unless occuring in an unexecuted OP_IF bra= nch, will make the transaction invalid if it is included in a block where t= he median timestamp of the prior 11 blocks is less than 1542300000. >> >> ### Unit Tests >> >> - ` OP_CHECKDATASIGVERIFY` fails if 15 November 201= 8 protocol upgrade is not yet activated. >> - ` OP_CHECKDATASIGVERIFY` fails if there are fewer than 3 i= tem on stack. >> - ` OP_CHECKDATASIGVERIFY`fails if `` is no= t 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 activa= tion. >> if ((flags & SCRIPT_ENABLE_CHECKDATASIG) =3D=3D = 0) { >> return set_error(serror, SCRIPT_ERR_BAD_OPCO= DE); >> } >> >> // (sig message pubkey -- bool) >> if (stack.size() < 3) { >> return set_error( >> serror, SCRIPT_ERR_INVALID_STACK_OPERATI= ON); >> } >> >> valtype &vchSig =3D stacktop(-3); >> valtype &vchMessage =3D stacktop(-2); >> valtype &vchPubKey =3D stacktop(-1); >> >> if (!CheckDataSignatureEncoding(vchSig, flags, >> serror) || >> !CheckPubKeyEncoding(vchPubKey, flags, serro= r)) { >> // serror is set >> return false; >> } >> >> bool fSuccess =3D false; >> if (vchSig.size()) { >> valtype vchHash(32); >> CSHA256() >> .Write(vchMessage.data(), vchMessage.siz= e()) >> .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_NULL= FAIL); >> } >> >> 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_CHECKDATASIG= VERIFY); >> } >> } >> } 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 o= ne 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 (txsig, txpubkey, address, p2pkh spend a= ddress) >> 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 p= roposal [6, 7]. It is modified from Stone's original proposal based on a sy= nthesis 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/bi= p-0066.mediawiki) >> >> [3] [Low-S and Nullfail Specification](https://github.com/bitcoin/bips/b= lob/master/bip-0146.mediawiki) >> >> [4] [Bitcoin ABC implementation](https://reviews.bitcoinabc.org/D1621) >> >> [5] [Bitcoin ABC implementation update](https://reviews.bitcoinabc.org/D= 1646) >> >> [6] [Andrew Stone=E2=80=99s OP_DATASIGVERIFY](https://github.com/Bitcoin= Unlimited/BitcoinUnlimited/blob/bucash1.3.0.0/doc/opdatasigverify.md) >> >> [7] [Andrew Stone's article on Scripting](https://medium.com/@g.andrew.s= tone/bitcoin-scripting-applications-decision-based-spending-8e7b93d7bdb9) >> >> [8] [Peer Review of Andrew Stone's Proposal](https://github.com/bitcoinc= ashorg/bitcoincash.org/pull/10) >> >> >> -- >> @JeremyRubin >> >> _______________________________________________ >> bitcoin-dev mailing list >> bitcoin-dev@lists.linuxfoundation.org >> https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev >> > --000000000000f945a705c63c4597 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Awesome to hear that!

Actually I don't think I did know (or I forgot/didn'= t catch it) that there was an updated spec for elements, I searched around = for what I could find and came up empty handed. Do you have any links for t= hat? That sounds perfect=C2=A0to me.


On Sat, Jul 3, 2021, 10:50 AM Russe= ll O'Connor <roconnor@bl= ockstream.com> wrote:
Hi Jermy,

As you are aware, we, an= d by we I mean mostly Sanket, are developing an updated OP_CHECKSIGFROMSTAC= K implementation for tapscript on elements.=C2=A0 The plan here would be to= effectively support the an interface to the variable-length extension of B= IP-0340 schnorr signatures.

BIP-0340 would dispens= e with DER encoding (good riddance).
BIP-0340 signatures are batc= h verifiable along with other BIP-0340 transaction signatures and taproot t= weak verification.
Support for variable length messages in BIP-03= 40 has been discussed in <https://github.com/sipa/bips/iss= ues/207> and an implementation has recently been merged in <https://github.com/bitcoin-core/secp256k1/pull/844&= gt;.=C2=A0 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 pre= fix). The CHECKSIGFROMSTACK operation (in tapscript) would use a stack item= for this m value to BIP-0340 signature verification and would not necessar= ily have to be 32 bytes.

I think this design w= e 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-Lice= nsed) specification for "CheckDataSig", more or less the same thi= ng as CHECKSIGFROMSTACK https://github.com/bitcoincashorg/bitcoincash.org/blob/master/spec= /op_checkdatasig.md. In contrast to Element's implementation, it do= es not have Element's bugs around verify semantics and uses the nullfai= l rule, and there is a specification document so it seemed like the easiest= starting point for discussion v.s. drafting something from scratch.
<= div class=3D"gmail_default">
Does anyone have any issue with adapting th= is exact text and implementation to a BIP for Bitcoin using 2 OP_SUCCESSX o= pcodes?

Note that with *just* CheckSigFromStack, while you can do some very v= aluable use cases, but without OP_CAT it does not enable sophisticated cove= nants (and as per=C2=A0https://w= ww.wpsoftware.net/andrew/blog/cat-and-schnorr-tricks-i.html just CAT al= one enables such uses).

Design questions worth considering as modifi= cations:

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 value allows you to extract a private key if ever d= ouble signed, using 2 R values allows pay-to-reveal-key contracts. Most lik= ely answer is no, if that is desired then OP_CAT can be introduced
3. Sh= ould CSFS support a cheap way to reference the taproot internal or external= key? Perhaps, can be handled with undefined upgradeable keytypes. One migh= t want to use the internal key, if the signed data should be valid independ= ent of the tapscript tree. One might want to use the external key, if the d= ata should only be valid for a single tapscript key + tree.
4. Should in= valid 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 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://gith=
ub.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.bitcoina=
bc.org/D1646)

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

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

[8] [Peer Review of Andrew Stone's Proposal](https://github.com/bitcoincashorg/bitcoincash.org/pull/10)
<= /div>
_______________________________________________
bitcoin-dev mailing list
bitcoin-dev@lists.linuxfoundation.org
https://lists.linuxfoundati= on.org/mailman/listinfo/bitcoin-dev
--000000000000f945a705c63c4597--