From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from smtp2.osuosl.org (smtp2.osuosl.org [IPv6:2605:bc80:3010::133]) by lists.linuxfoundation.org (Postfix) with ESMTP id DBD9FC000E for ; Sat, 3 Jul 2021 20:13:06 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id ABE28401F0 for ; Sat, 3 Jul 2021 20:13:06 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org X-Spam-Flag: NO X-Spam-Score: -1.9 X-Spam-Level: X-Spam-Status: No, score=-1.9 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_PASS=-0.001] autolearn=ham autolearn_force=no Authentication-Results: smtp2.osuosl.org (amavisd-new); dkim=pass (2048-bit key) header.d=blockstream-com.20150623.gappssmtp.com Received: from smtp2.osuosl.org ([127.0.0.1]) by localhost (smtp2.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id zH6l1UPHIZfT for ; Sat, 3 Jul 2021 20:13:04 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.8.0 Received: from mail-qv1-xf2c.google.com (mail-qv1-xf2c.google.com [IPv6:2607:f8b0:4864:20::f2c]) by smtp2.osuosl.org (Postfix) with ESMTPS id 514F5401D5 for ; Sat, 3 Jul 2021 20:13:04 +0000 (UTC) Received: by mail-qv1-xf2c.google.com with SMTP id h18so6504414qve.1 for ; Sat, 03 Jul 2021 13:13:04 -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 :cc; bh=sIadC1bPhOi+rK9nC8f5NbXuLZvAloVEVX4og9sssaE=; b=HLpof99LiQWFlKP0+H0GapL9jweWabV2S5leUymjdoHu34zsyhTutDBdl1FPqJQOur 5i7w/2I1Vx8oMSEL88mgoPQyS/td9ABCUcY8GED6N6BdfFKxyDt7oRsdJld+9bibgp9H hFXsZ5rqC3UAAlWFLsB6hCosXFNWL7mcYRr3lefsHxSKojMHDmDV8NP0PaAn7kPSIUgw ajUZyNmUu+Yjc/clAUcyVWilfqFeYUPnIElODWf4+KjmndjSoQ0MbUf+XhfUMAB8kuLy fR88fxTVXAhlYbCfspAe3QAEcDB5I7zHE9pPm/oIf57412bupxFp7ALD5XbMDmQ2qFlO fV+A== 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:cc; bh=sIadC1bPhOi+rK9nC8f5NbXuLZvAloVEVX4og9sssaE=; b=WasApouOlB/VaiZkH+SIwad6cs2vbygWKnQPo1Ah9U6Hmz1TVhdX1QM1RhoMHjU824 tK2gaz0f0sJUVN7od/DUcEqY4x5acmChvOHe31IQK95OHsrd20fXoK4gUHliJz1fsT+w e6Vq/0EVTVwdV95aJ3WkdRDflOXH4isSk5MamNO70qC/VeCUJ8bYnrvOMDozOmqB1DlK tIZMZ0toQlSCk6DklLO0i9jdaa/FRTny7mc8HjnxQ9XNVoVfA81iDmSyYhsTAywMbWeK 2FRrnz4Vqft04vjELU3rTJjRvSUrYjchJsPAsEQtgYlI9Be7xu/Ov64xxd9a3aGeMIwS XoxQ== X-Gm-Message-State: AOAM5329bGt1wNZ4I8avrp0NicaWtu+fdISKUblK7N6yqQwIRZExSYS9 Y4jy3VqiOeby9ZBNoRfTgxhUGBZRKuPbSVz2SgBvpA== X-Google-Smtp-Source: ABdhPJxigqZrVLfXj0AOrgL6NFyrEyBbpBdUOt4kCwmoA3M5XpEWJ4fBypKY2+5/aujRORsgELQLWht2Dxi6EnltjDo= X-Received: by 2002:a05:6214:e68:: with SMTP id jz8mr5319916qvb.13.1625343183155; Sat, 03 Jul 2021 13:13:03 -0700 (PDT) MIME-Version: 1.0 References: In-Reply-To: From: "Russell O'Connor" Date: Sat, 3 Jul 2021 16:12:51 -0400 Message-ID: To: Jeremy Content-Type: multipart/alternative; boundary="000000000000120b8405c63db347" 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 20:13:07 -0000 --000000000000120b8405c63db347 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable There is one line written at https://github.com/ElementsProject/elements/pull/949/files#r660130155. I suppose we need to decide on which variants of *VERIFY and *ADD we want to include (presumably all of them) and choose which opcodes they will be assigned to. And I guess for CHECKSIGFROMSTACKADD will want to place the n value between the signature and the message on the stack. ... So I suppose we will need more than one sentence. The semantics would be basically to call secp256k1_schnorrsig_verify < https://github.com/bitcoin-core/secp256k1/blob/0440945fb5ce69d335fed32827b5= 166e84b02e05/include/secp256k1_schnorrsig.h#L158>, treating pubkeys and signatures the same way the other CHECKSIG operations do, and in passing the (variable length) message from the stack. CHECKSIGFROMSTACK would also be subject to the same sigops budget that CHECKSIG has in tapscript. On Sat, Jul 3, 2021 at 2:30 PM Jeremy wrote: > Awesome to hear that! > > Actually I don't think I did know (or I forgot/didn't catch it) that ther= e > 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. = 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 < >> 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 CHECKSIGFROMST= ACK >> 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_c= heckdatasig.md. >>> In contrast to Element's implementation, it does not have Element's bug= s >>> 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 fo= r some >>> applications that otherwise may require OP_CAT? E.g. using a pinned R v= alue >>> allows you to extract a private key if ever double signed, using 2 R va= lues >>> allows pay-to-reveal-key contracts. Most likely answer is no, if that i= s >>> 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 keytyp= es. >>> One might want to use the internal key, if the signed data should be va= lid >>> independent of the tapscript tree. One might want to use the external k= ey, >>> 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 = valid 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 implemente= d similarly to OP_CHECKSIG [1]. Conceptually, one could imagine OP_CHECKSIG= functionality 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 b= e 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 des= cribed in [3] >>> >>> If the stack is well formed, then OP_CHECKDATASIG pops the top three el= ements [``, ``, ``] from the stack and pushes true onto t= he stack if `` is valid with respect to the raw single-SHA256 hash of = `` and `` using the secp256k1 elliptic curve. Otherwise, it po= ps 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 = does 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 h= ex encoding) >>> >>> ### SigOps >>> >>> Signature operations accounting for OP_CHECKDATASIG shall be calculated= the same as OP_CHECKSIG. This means that each OP_CHECKDATASIG shall be cou= nted 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 me= dian timestamp of the prior 11 blocks is less than 1542300000. >>> >>> ### Unit Tests >>> >>> - ` OP_CHECKDATASIG` fails if 15 November 2018 pro= tocol upgrade is not yet activated. >>> - ` OP_CHECKDATASIG` fails if there are fewer than 3 items = on stack. >>> - ` OP_CHECKDATASIG` fails if `` is not a = validly encoded public key. >>> - ` OP_CHECKDATASIG` fails if `` is not a val= idly 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 pushe= s false onto the stack if `` is an empty byte array. >>> - ` OP_CHECKDATASIG` pops three elements and pushe= s true onto the stack if `` is a valid signature of `` with respe= ct to ``. >>> >>> OP_CHECKDATASIGVERIFY Specification >>> ----------------------------------- >>> >>> ### Semantics >>> >>> OP_CHECKDATASIGVERIFY is equivalent to OP_CHECKDATASIG followed by OP_V= ERIFY. It leaves nothing on the stack, and will cause the script to fail im= mediately if the signature check does not pass. >>> >>> ### Opcode Number >>> >>> OP_CHECKDATASIGVERIFY uses the previously unused opcode number 187 (0xb= b in hex encoding) >>> >>> ### SigOps >>> >>> Signature operations accounting for OP_CHECKDATASIGVERIFY shall be calc= ulated the same as OP_CHECKSIGVERIFY. This means that each OP_CHECKDATASIGV= ERIFY shall be counted as one (1) SigOp. >>> >>> ### Activation >>> >>> Use of OP_CHECKDATASIGVERIFY, unless occuring in an unexecuted OP_IF br= anch, 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 >>> >>> - ` OP_CHECKDATASIGVERIFY` fails if 15 November 20= 18 protocol upgrade is not yet activated. >>> - ` OP_CHECKDATASIGVERIFY` fails if there are fewer than 3 = item on stack. >>> - ` OP_CHECKDATASIGVERIFY`fails if `` is n= ot 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 stac= k 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 activ= ation. >>> if ((flags & SCRIPT_ENABLE_CHECKDATASIG) =3D=3D= 0) { >>> return set_error(serror, SCRIPT_ERR_BAD_OPC= ODE); >>> } >>> >>> // (sig message pubkey -- bool) >>> if (stack.size() < 3) { >>> return set_error( >>> serror, SCRIPT_ERR_INVALID_STACK_OPERAT= ION); >>> } >>> >>> valtype &vchSig =3D stacktop(-3); >>> valtype &vchMessage =3D stacktop(-2); >>> valtype &vchPubKey =3D stacktop(-1); >>> >>> if (!CheckDataSignatureEncoding(vchSig, flags, >>> serror) || >>> !CheckPubKeyEncoding(vchPubKey, flags, serr= or)) { >>> // serror is set >>> return false; >>> } >>> >>> bool fSuccess =3D false; >>> if (vchSig.size()) { >>> valtype vchHash(32); >>> CSHA256() >>> .Write(vchMessage.data(), vchMessage.si= ze()) >>> .Finalize(vchHash.data()); >>> uint256 message(vchHash); >>> CPubKey pubkey(vchPubKey); >>> fSuccess =3D pubkey.Verify(message, vchSig)= ; >>> } >>> >>> if (!fSuccess && (flags & SCRIPT_VERIFY_NULLFAI= L) && >>> vchSig.size()) { >>> return set_error(serror, SCRIPT_ERR_SIG_NUL= LFAIL); >>> } >>> >>> 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_CHECKDATASI= GVERIFY); >>> } >>> } >>> } break; >>> ``` >>> >>> Sample Usage >>> ------------ >>> >>> The following example shows a spend and redeem script for a basic use o= f CHECKDATASIG. This example validates the signature of some data, provide= s 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 (txsig, txpubkey, address, p2pkh spend = address) >>> 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 = proposal [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/b= ip-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/Bitcoi= nUnlimited/BitcoinUnlimited/blob/bucash1.3.0.0/doc/opdatasigverify.md) >>> >>> [7] [Andrew Stone's article on Scripting](https://medium.com/@g.andrew.= stone/bitcoin-scripting-applications-decision-based-spending-8e7b93d7bdb9) >>> >>> [8] [Peer Review of Andrew Stone's Proposal](https://github.com/bitcoin= cashorg/bitcoincash.org/pull/10) >>> >>> >>> -- >>> @JeremyRubin >>> >>> _______________________________________________ >>> bitcoin-dev mailing list >>> bitcoin-dev@lists.linuxfoundation.org >>> https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev >>> >> --000000000000120b8405c63db347 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
There is one line written at https://github.co= m/ElementsProject/elements/pull/949/files#r660130155. I suppose we need= to decide on which variants of *VERIFY and *ADD we want to include (presum= ably all of them) and choose which opcodes they will be assigned to.=C2=A0 = And I guess for CHECKSIGFROMSTACKADD will want to place the n value between= the signature and the message on the stack.=C2=A0 ... So I suppose we will= need more than one sentence.

The semantics wo= uld be basically to call secp256k1_schnorrsig_= verify <https://github.com/bitcoin-core/secp256k1/blob/0440945fb5ce69d335fed328= 27b5166e84b02e05/include/secp256k1_schnorrsig.h#L158>, treating pubk= eys and signatures the same way the other CHECKSIG operations do, and in pa= ssing the (variable length) message from the stack.=C2=A0 CHECKSIGFROMSTACK= would also be subject to the same sigops budget that CHECKSIG has in tapsc= ript.

On Sat, Jul 3, 2021 at 2:30 PM Jeremy <jlrubin@mit.edu> wrote:
Awesome to hear that!

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

On Sat, J= ul 3, 2021, 10:50 AM Russell O'Connor <roconnor@blockstream.com> wrote:
<= div>Hi Jermy,

As you are aware, we, and by we I me= an mostly Sanket, are developing an updated OP_CHECKSIGFROMSTACK implementa= tion for tapscript on elements.=C2=A0 The plan here would be to effectively= support the an interface to the variable-length extension of BIP-0340 schn= orr signatures.

BIP-0340 would dispense with DER e= ncoding (good riddance).
BIP-0340 signatures are batch verifiable= along with other BIP-0340 transaction signatures and taproot tweak verific= ation.
Support for variable length messages in BIP-0340 has been = discussed in <https://github.com/sipa/bips/issues/207&= gt; and an implementation has recently been merged in <https://github.com/bitcoin-core/secp256k1/pull/844>.=C2=A0 T= he BIP has not yet been updated but the difference is that the message m do= es 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 CH= ECKSIGFROMSTACK 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 "CheckD= ataSig", more or less the same thing as CHECKSIGFROMSTACK https://github.com/bitcoinc= ashorg/bitcoincash.org/blob/master/spec/op_checkdatasig.md. In contrast= to Element's implementation, it does not have Element's bugs aroun= d 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 w= ith adapting this exact text and implementation to a BIP for Bitcoin using = 2 OP_SUCCESSX opcodes?

Note that with *just* Check= SigFromStack, 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/ca= t-and-schnorr-tricks-i.html just CAT alone enables such uses).

D= esign 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 value allows you to extract a pr= ivate key if ever double signed, using 2 R values 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 i= nternal or external key? Perhaps, can be handled with undefined upgradeable= keytypes. One might want to use the internal key, if the signed data shoul= d be valid independent of the tapscript tree. One might want to use the ext= ernal key, if the data should only be valid for a single tapscript key + tr= ee.
4. Should invalid public keys types be a NOP to support future exten= ded 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
--000000000000120b8405c63db347--