Return-Path: <jlrubin@mit.edu> Received: from smtp1.osuosl.org (smtp1.osuosl.org [140.211.166.138]) by lists.linuxfoundation.org (Postfix) with ESMTP id AB13AC000E for <bitcoin-dev@lists.linuxfoundation.org>; 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 <bitcoin-dev@lists.linuxfoundation.org>; 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 <bitcoin-dev@lists.linuxfoundation.org>; 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 <bitcoin-dev@lists.linuxfoundation.org>; 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 <bitcoin-dev@lists.linuxfoundation.org>; Sat, 3 Jul 2021 14:30:58 -0400 Received: by mail-il1-f171.google.com with SMTP id z1so13218450ils.0 for <bitcoin-dev@lists.linuxfoundation.org>; 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: <CAD5xwhjmu-Eee47Ho5eA6E6+aAdnchLU0OVZo=RTHaXnN17x8A@mail.gmail.com> <CAMZUoK=-jrH+fr=tUTHmLojm2-Ff99KYm9H97yhd=7bcOVG=fg@mail.gmail.com> In-Reply-To: <CAMZUoK=-jrH+fr=tUTHmLojm2-Ff99KYm9H97yhd=7bcOVG=fg@mail.gmail.com> From: Jeremy <jlrubin@mit.edu> Date: Sat, 3 Jul 2021 11:30:45 -0700 X-Gmail-Original-Message-ID: <CAD5xwhg0N1byx-G2tk=jjmZSHSBirpaX6OHTnh_x9iDEVF8PrQ@mail.gmail.com> Message-ID: <CAD5xwhg0N1byx-G2tk=jjmZSHSBirpaX6OHTnh_x9iDEVF8PrQ@mail.gmail.com> To: "Russell O'Connor" <roconnor@blockstream.com> Content-Type: multipart/alternative; boundary="000000000000f945a705c63c4597" Cc: Bitcoin Protocol Discussion <bitcoin-dev@lists.linuxfoundation.org> 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 <bitcoin-dev.lists.linuxfoundation.org> List-Unsubscribe: <https://lists.linuxfoundation.org/mailman/options/bitcoin-dev>, <mailto:bitcoin-dev-request@lists.linuxfoundation.org?subject=unsubscribe> List-Archive: <http://lists.linuxfoundation.org/pipermail/bitcoin-dev/> List-Post: <mailto:bitcoin-dev@lists.linuxfoundation.org> List-Help: <mailto:bitcoin-dev-request@lists.linuxfoundation.org?subject=help> List-Subscribe: <https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev>, <mailto:bitcoin-dev-request@lists.linuxfoundation.org?subject=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 <roconnor@blockstream.com> 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 [`<sig>`, `<ms= g>`, `<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] and = the S-value of `<sig>` 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 [`<sig>`, `<msg>`, `<pubKey>`] from the stack and pushes true onto th= e stack if `<sig>` is valid with respect to the raw single-SHA256 hash of `= <msg>` and `<pubKey>` using the secp256k1 elliptic curve. Otherwise, it pop= s three elements and pushes false onto the stack in the case that `<sig>` 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 >> >> - `<sig> <msg> <pubKey> OP_CHECKDATASIG` fails if 15 November 2018 prot= ocol upgrade is not yet activated. >> - `<sig> <msg> OP_CHECKDATASIG` fails if there are fewer than 3 items o= n stack. >> - `<sig> <msg> <pubKey> OP_CHECKDATASIG` fails if `<pubKey>` is not a v= alidly encoded public key. >> - `<sig> <msg> <pubKey> OP_CHECKDATASIG` fails if `<sig>` is not a vali= dly encoded signature with strict DER encoding. >> - `<sig> <msg> <pubKey> OP_CHECKDATASIG` fails if signature `<sig>` is = not empty and does not pass the Low S check. >> - `<sig> <msg> <pubKey> OP_CHECKDATASIG` fails if signature `<sig>` is = not empty and does not pass signature validation of `<msg>` and `<pubKey>`. >> - `<sig> <msg> <pubKey> OP_CHECKDATASIG` pops three elements and pushes= false onto the stack if `<sig>` is an empty byte array. >> - `<sig> <msg> <pubKey> OP_CHECKDATASIG` pops three elements and pushes= true onto the stack if `<sig>` is a valid signature of `<msg>` with respec= t to `<pubKey>`. >> >> 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 >> >> - `<sig> <msg> <pubKey> OP_CHECKDATASIGVERIFY` fails if 15 November 201= 8 protocol upgrade is not yet activated. >> - `<sig> <msg> OP_CHECKDATASIGVERIFY` fails if there are fewer than 3 i= tem on stack. >> - `<sig> <msg> <pubKey> OP_CHECKDATASIGVERIFY`fails if `<pubKey>` is no= t 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 `<pubKey>`. >> - `<sig> <msg> <pubKey> OP_CHECKDATASIGVERIFY` pops the top three stack= elements if `<sig>` is a valid signature of `<msg>` with respect to `<pubK= ey>`. >> >> 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 <p2pkh spend address> (txsig, txpubkey, address, p2pkh spend a= ddress) >> 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 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 <https://twitter.com/JeremyRubin> >> <https://twitter.com/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 <div dir=3D"auto"><div>Awesome to hear that!<div dir=3D"auto"><br></div><di= v dir=3D"auto">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.</div><br><br><div class=3D"gmail_quote= "><div dir=3D"ltr" class=3D"gmail_attr">On Sat, Jul 3, 2021, 10:50 AM Russe= ll O'Connor <<a href=3D"mailto:roconnor@blockstream.com">roconnor@bl= ockstream.com</a>> wrote:<br></div><blockquote class=3D"gmail_quote" sty= le=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div d= ir=3D"ltr"><div>Hi Jermy,</div><div><br></div><div>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.</div><div><br></div><div>BIP-0340 would dispens= e with DER encoding (good riddance).</div><div>BIP-0340 signatures are batc= h verifiable along with other BIP-0340 transaction signatures and taproot t= weak verification.</div><div>Support for variable length messages in BIP-03= 40 has been discussed in <<a href=3D"https://github.com/sipa/bips/issues= /207" target=3D"_blank" rel=3D"noreferrer">https://github.com/sipa/bips/iss= ues/207</a>> and an implementation has recently been merged in <<a hr= ef=3D"https://github.com/bitcoin-core/secp256k1/pull/844" target=3D"_blank"= rel=3D"noreferrer">https://github.com/bitcoin-core/secp256k1/pull/844</a>&= 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.<br></div><div><br></div><div>I think this design w= e are aiming for would be perfectly suited for Bitcoin as well.<br></div></= div><br><div class=3D"gmail_quote"><div dir=3D"ltr" class=3D"gmail_attr">On= Sat, Jul 3, 2021 at 12:32 PM Jeremy via bitcoin-dev <<a href=3D"mailto:= bitcoin-dev@lists.linuxfoundation.org" target=3D"_blank" rel=3D"noreferrer"= >bitcoin-dev@lists.linuxfoundation.org</a>> wrote:<br></div><blockquote = class=3D"gmail_quote" style=3D"margin:0px 0px 0px 0.8ex;border-left:1px sol= id rgb(204,204,204);padding-left:1ex"><div dir=3D"ltr"><div class=3D"gmail_= default">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 <a href=3D"https://github.com/bitcoincashorg/bitcoi= ncash.org/blob/master/spec/op_checkdatasig.md" target=3D"_blank" rel=3D"nor= eferrer">https://github.com/bitcoincashorg/bitcoincash.org/blob/master/spec= /op_checkdatasig.md</a>. 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><= div class=3D"gmail_default"><br>Does anyone have any issue with adapting th= is exact text and implementation to a BIP for Bitcoin using 2 OP_SUCCESSX o= pcodes?</div><div class=3D"gmail_default"><br></div><div class=3D"gmail_def= ault">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=A0<a href=3D"https://www.wpsoftware.net/andrew/blog/ca= t-and-schnorr-tricks-i.html" target=3D"_blank" rel=3D"noreferrer">https://w= ww.wpsoftware.net/andrew/blog/cat-and-schnorr-tricks-i.html</a> just CAT al= one enables such uses).<br><br>Design questions worth considering as modifi= cations:</div><div class=3D"gmail_default"><br>1. Should CSFS require some = sort of tagged hash? Very likely answer is no =E2=80=93 tags interfere with= certain use cases<br>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<br>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.<br>4. Should in= valid public keys types be a NOP to support future extended pubkey types?</= div><div class=3D"gmail_default"><br></div><div class=3D"gmail_default"><br= ><br></div><div class=3D"gmail_default">Best,<br><br><br>Jeremy<pre style= =3D"color:rgb(0,0,0);font-family:arial,helvetica,sans-serif;font-size:small= ;white-space:pre-wrap"><br></pre><pre style=3D"color:rgb(0,0,0);font-family= :arial,helvetica,sans-serif;font-size:small;white-space:pre-wrap">--- 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](<a href=3D"https://en.bitcoin.it/wiki/OP_CHECKSIG" target= =3D"_blank" rel=3D"noreferrer">https://en.bitcoin.it/wiki/OP_CHECKSIG</a>) [2] [Strict DER Encoding](<a href=3D"https://github.com/bitcoin/bips/blob/m= aster/bip-0066.mediawiki" target=3D"_blank" rel=3D"noreferrer">https://gith= ub.com/bitcoin/bips/blob/master/bip-0066.mediawiki</a>) [3] [Low-S and Nullfail Specification](<a href=3D"https://github.com/bitcoi= n/bips/blob/master/bip-0146.mediawiki" target=3D"_blank" rel=3D"noreferrer"= >https://github.com/bitcoin/bips/blob/master/bip-0146.mediawiki</a>) [4] [Bitcoin ABC implementation](<a href=3D"https://reviews.bitcoinabc.org/= D1621" target=3D"_blank" rel=3D"noreferrer">https://reviews.bitcoinabc.org/= D1621</a>) [5] [Bitcoin ABC implementation update](<a href=3D"https://reviews.bitcoina= bc.org/D1646" target=3D"_blank" rel=3D"noreferrer">https://reviews.bitcoina= bc.org/D1646</a>) [6] [Andrew Stone=E2=80=99s OP_DATASIGVERIFY](<a href=3D"https://github.com= /BitcoinUnlimited/BitcoinUnlimited/blob/bucash1.3.0.0/doc/opdatasigverify.m= d" target=3D"_blank" rel=3D"noreferrer">https://github.com/BitcoinUnlimited= /BitcoinUnlimited/blob/bucash1.3.0.0/doc/opdatasigverify.md</a>) [7] [Andrew Stone's article on Scripting](<a href=3D"https://medium.com= /@g.andrew.stone/bitcoin-scripting-applications-decision-based-spending-8e7= b93d7bdb9" target=3D"_blank" rel=3D"noreferrer">https://medium.com/@g.andre= w.stone/bitcoin-scripting-applications-decision-based-spending-8e7b93d7bdb9= </a>) [8] [Peer Review of Andrew Stone's Proposal](<a href=3D"https://github.= com/bitcoincashorg/bitcoincash.org/pull/10" target=3D"_blank" rel=3D"norefe= rrer">https://github.com/bitcoincashorg/bitcoincash.org/pull/10</a>)</pre><= /div><br clear=3D"all"><div><div dir=3D"ltr"><div dir=3D"ltr">--<br><a href= =3D"https://twitter.com/JeremyRubin" target=3D"_blank" rel=3D"noreferrer">@= JeremyRubin</a><a href=3D"https://twitter.com/JeremyRubin" target=3D"_blank= " rel=3D"noreferrer"></a></div></div></div></div> _______________________________________________<br> bitcoin-dev mailing list<br> <a href=3D"mailto:bitcoin-dev@lists.linuxfoundation.org" target=3D"_blank" = rel=3D"noreferrer">bitcoin-dev@lists.linuxfoundation.org</a><br> <a href=3D"https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev" = rel=3D"noreferrer noreferrer" target=3D"_blank">https://lists.linuxfoundati= on.org/mailman/listinfo/bitcoin-dev</a><br> </blockquote></div> </blockquote></div></div></div> --000000000000f945a705c63c4597--