Return-Path: Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id D755F9F0 for ; Wed, 28 Nov 2018 08:31:55 +0000 (UTC) X-Greylist: from auto-whitelisted by SQLgrey-1.7.6 Received: from sender-of-o53.zoho.com (sender-of-o53.zoho.com [135.84.80.218]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id DFB3A77E for ; Wed, 28 Nov 2018 08:31:54 +0000 (UTC) ARC-Seal: i=1; a=rsa-sha256; t=1543393913; cv=none; d=zoho.com; s=zohoarc; b=k3c79iMoBhDK2afqTpELXupy34xZ8a66MQ0tUZBCUuGxZ2VxYWH5QcocDr9ImH87FWFwUa1WkGdS8BNpZUoVXhxOAdtC//XAh1gymryCOb7Q9fM0ffT9p6VY8rOKNmcrtQBwUOHN0ko5WRUIc+ejRAVviuTPHn6QbRMDcAAVDo4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1543393913; h=Content-Type:Date:From:In-Reply-To:MIME-Version:Message-ID:References:Subject:To:ARC-Authentication-Results; bh=y8GAoH4xXjmc2Y4Qtnkx4D3CrdMlt4pSVlRf0jM0Dxc=; b=iKVdGWHz2QE7WLr0acZ2zBjg+lDdl1wqU5t2BPQ8ekQ6WKI0vwF5KWUyystrIJef71HYOwZAUuwzFn5V/KbVxmYXmH0e464HWHxNW+nQwg2SyoEQGHFIOKn5YBkg8NPlX6snmw4JcnjZ2BK1DuLCrRsg3+oywhkLRVAy9ZXJBdo= ARC-Authentication-Results: i=1; mx.zoho.com; dkim=pass header.i=xbt.hk; spf=pass smtp.mailfrom=jl2012@xbt.hk; dmarc=pass header.from= header.from= Received: from [10.7.47.115] (ip-123-255-103-29.wlan.cuhk.edu.hk [123.255.103.29]) by mx.zohomail.com with SMTPS id 15433939125331018.2147366806481; Wed, 28 Nov 2018 00:31:52 -0800 (PST) From: Johnson Lau Content-Type: multipart/alternative; boundary="Apple-Mail=_AA597DAC-952A-47DE-97FB-6FE438CB4F17" Mime-Version: 1.0 (Mac OS X Mail 12.0 \(3445.100.39\)) Date: Wed, 28 Nov 2018 16:31:48 +0800 References: To: Pieter Wuille , bitcoin-dev In-Reply-To: Message-Id: <8BD44CAB-D590-4B2D-8CB7-9CD6792E5EF9@xbt.hk> X-Mailer: Apple Mail (2.3445.100.39) X-ZohoMailClient: External X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,HTML_MESSAGE, MIME_QP_LONG_LINE,RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org X-Mailman-Approved-At: Wed, 28 Nov 2018 14:24:18 +0000 Subject: Re: [bitcoin-dev] Safer sighashes and more granular SIGHASH_NOINPUT X-BeenThere: bitcoin-dev@lists.linuxfoundation.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: Bitcoin Protocol Discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 28 Nov 2018 08:31:56 -0000 --Apple-Mail=_AA597DAC-952A-47DE-97FB-6FE438CB4F17 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=utf-8 > On 28 Nov 2018, at 11:41 AM, Pieter Wuille via bitcoin-dev = wrote: >=20 > So a combined proposal: > * All existing sighash flags, plus NOINPUT and MASK > (ANYONECANPAY/NOINPUT/MASK are encoded in 2 bits). > * A new opcode called OP_MASKEDPUSH, whose only runtime behaviour is > failing if not immediately followed by a push, or when appearing as > last opcode in the script. I suggest to use the place of OP_RESERVED (0x50) as OP_MASKEDPUSH. The = reason is 0x50 is not counted towards the 201 opcode limit, so people = could mask as many pushes as needed. In a new script version, of course, we could make any opcode not being = counted. But that would just create another special case in the = EvalScript() code. (Or, maybe we should limit the use of OP_MASKEDPUSH? I think this is = open for discussion.) > * Signatures are 64 plus an optional sighash byte. A missing sighash > byte implies ALL, and ALL cannot be specified explicitly. > * The sighash is computed from the following: > * A 64-byte constant tag > * Data about the spending transaction: > * The transaction version number > * The hash of txins' prevouts+amounts+sequences (or nothing if = ANYONECANPAY) Do you want to make it 1 hash or 3 hashes? With 3 hashes, it could share = hashPrevouts and hashSequence with BIP143. Making everything 1 hash will = only result in redundent hashing for each input > * The hash of all txouts (or just the corresponding txout if > SINGLE; nothing if NONE) Starting from this sighash version, I think we should forbid the use of = SINGLE without a matching output. Also, the undefined output type should = also be invalid. > * The transaction locktime > * Data about the output being spent: > * The prevout (or nothing if NOINPUT) > * The amount > * The sequence number > * The hash of the scriptPubKey (or nothing if MASK) I think we should just use the scriptPubKey, since sPK is fixed size = (23-byte for p2sh and 35-byte for native segwit). In order to distinguish p2sh and native segwit for MASKED NOINPUT, you = also need to commit to an additional 1-bit value > * Data about the script being executed: > * The hash of the scriptCode (after masking out, if MASK is set) For direct key-spending (i.e. not taprooted script), I suggest to set = the H(scriptCode) to zero, for the following reasons: 1) Since we have already committed to sPK, which is already a *direct* = hash of scriptCode, it is redundant to do it again. 2) This could save one SHA256 compression for direct key-spending, which = is probably 90% of all cases 3) This allows hardware wallet to tell whether they are using = direct-spending path or taproot script path Since we may want 3) anyway, we don=E2=80=99t need to commit to another = 1-bit value if we simply set H(scriptCode) to zero We should also ban MASKED NOINPUT for direct-spending, which doesn=E2=80=99= t make sense. And it is not safe since both H(scriptCode) and sPK are = empty. > * The opcode number of the last executed OP_CODESEPARATOR (or > 0xFFFFFFFF if none) > * The sighash mode This proposal will only use 4 out of the 8 sighash bits. Do we want to = make those 4 unused bits invalid, or ignored? Leaving at least 1 bit = valid but ignored (=E2=80=9Cbit-x"), and 1 bit invalid (=E2=80=9Cbit-y=E2=80= =9D), will allow opt-in/out hardfork replay-protection, for example: * default signatures are those with both bit-x and bit-y unset. * If we want to make default signatures replayable across chains, the = new fork should reject signatures with bit-x, and accept sigs with or = without bit-y. In this case, defaults sigs are valid for both chains. = Sigs with bit-x is valid only for original chain, and sigs with bit-y is = valid only for new chain. * If we want to make default signatures non-replayabble, the new fork = should reject all default sigs, but accept sigs with either bit-x or = bit-y set. In this case, default sig is valid only for original chain. = Sigs with bit-x is valid for both chains, and sigs with bit-y is valid = only for new chain. Replayability is sometimes desirable, for example, an LN opened before a = fork should be able to be settled on both chains --Apple-Mail=_AA597DAC-952A-47DE-97FB-6FE438CB4F17 Content-Transfer-Encoding: quoted-printable Content-Type: text/html; charset=utf-8

On 28 Nov 2018, at 11:41 AM, Pieter Wuille via bitcoin-dev = <bitcoin-dev@lists.linuxfoundation.org> wrote:

So a combined = proposal:
* All = existing sighash flags, plus NOINPUT and MASK
(ANYONECANPAY/NOINPUT/MASK are = encoded in 2 bits).
* A new opcode called OP_MASKEDPUSH, whose only runtime = behaviour is
failing if = not immediately followed by a push, or when appearing as
last opcode in the = script.

I = suggest to use the place of OP_RESERVED (0x50) as OP_MASKEDPUSH. The = reason is 0x50 is not counted towards the 201 opcode limit, so people = could mask as many pushes as needed.

In a new script version, of course, we could make = any opcode not being counted. But that would just create another special = case in the EvalScript() code.

(Or, = maybe we should limit the use of OP_MASKEDPUSH? I think this is open for = discussion.)

* Signatures = are 64 plus an optional sighash byte. A missing sighash
byte implies ALL, and ALL cannot = be specified explicitly.
* The sighash is computed from the following:
 * A 64-byte constant = tag
 * Data = about the spending transaction:
   * The transaction version number
   * The hash of = txins' prevouts+amounts+sequences (or nothing if ANYONECANPAY)

Do you want = to make it 1 hash or 3 hashes? With 3 hashes, it could share = hashPrevouts and hashSequence with BIP143. Making everything 1 hash will = only result in redundent hashing for each input

   * The hash of = all txouts (or just the corresponding txout if
SINGLE; nothing if = NONE)

Starting from this sighash version, I think we = should forbid the use of SINGLE without a matching output. Also, the = undefined output type should also be invalid.

   * The = transaction locktime
 * Data about the output being spent:
   * The prevout = (or nothing if NOINPUT)
   * The amount
   * The sequence number
   * The hash of = the scriptPubKey (or nothing if MASK)

I think we should just use the scriptPubKey, since = sPK is fixed size (23-byte for p2sh and 35-byte for native = segwit).

In order to distinguish = p2sh and native segwit for MASKED NOINPUT, you also need to commit to an = additional 1-bit value

 * Data about the script being executed:
   * The hash of = the scriptCode (after masking out, if MASK is set)

For direct = key-spending (i.e. not taprooted script), I suggest to set the = H(scriptCode) to zero, for the following reasons:
1) Since we = have already committed to sPK, which is already a *direct* hash of = scriptCode, it is redundant to do it again.
2) This could save = one SHA256 compression for direct key-spending, which is probably 90% of = all cases
3) This allows hardware wallet to tell whether they = are using direct-spending path or taproot script path

Since we may want 3) anyway, we don=E2=80=99t need = to commit to another 1-bit value if we simply set H(scriptCode) to = zero

We should also ban MASKED = NOINPUT for direct-spending, which doesn=E2=80=99t make sense. And it is = not safe since both H(scriptCode) and sPK are empty.

   * The opcode = number of the last executed OP_CODESEPARATOR (or
0xFFFFFFFF if none)
 * The sighash = mode

This proposal = will only use 4 out of the 8 sighash bits. Do we want to make those 4 = unused bits invalid, or ignored? Leaving at least 1 bit valid but = ignored (=E2=80=9Cbit-x"), and 1 bit invalid (=E2=80=9Cbit-y=E2=80=9D), = will allow opt-in/out hardfork replay-protection, for = example:

* default signatures are = those with both bit-x and bit-y unset.
* If we want to make = default signatures replayable across chains, the new fork should reject = signatures with bit-x, and accept sigs with or without bit-y. In this = case, defaults sigs are valid for both chains. Sigs with bit-x is valid = only for original chain, and sigs with bit-y is valid only for new = chain.
* If we want to make default signatures = non-replayabble, the new fork should reject all default sigs, but accept = sigs with either bit-x or bit-y set. In this case, default sig is valid = only for original chain. Sigs with bit-x is valid for both chains, and = sigs with bit-y is valid only for new chain.

Replayability is sometimes desirable, for example, = an LN opened before a fork should be able to be settled on both = chains

= --Apple-Mail=_AA597DAC-952A-47DE-97FB-6FE438CB4F17--