summaryrefslogtreecommitdiff
path: root/05/7fa4f4e7cda5469502336ecf4f3c3d4c4ced3e
blob: 4ee5697609117d9498366dab7392022d58032ebe (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
Return-Path: <pieter.wuille@gmail.com>
Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org
	[172.17.192.35])
	by mail.linuxfoundation.org (Postfix) with ESMTPS id 55945B0B
	for <bitcoin-dev@lists.linuxfoundation.org>;
	Wed, 28 Nov 2018 03:41:16 +0000 (UTC)
X-Greylist: whitelisted by SQLgrey-1.7.6
Received: from mail-ot1-f42.google.com (mail-ot1-f42.google.com
	[209.85.210.42])
	by smtp1.linuxfoundation.org (Postfix) with ESMTPS id A7D7B19B
	for <bitcoin-dev@lists.linuxfoundation.org>;
	Wed, 28 Nov 2018 03:41:15 +0000 (UTC)
Received: by mail-ot1-f42.google.com with SMTP id 32so22251051ota.12
	for <bitcoin-dev@lists.linuxfoundation.org>;
	Tue, 27 Nov 2018 19:41:15 -0800 (PST)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025;
	h=mime-version:references:in-reply-to:from:date:message-id:subject:to; 
	bh=SnSPwnkmMnkXGPIRENYhXMOnv8nnh4T9XM5b5AJptd8=;
	b=h41LZQaot/0xUE0RGMXoE5M/6CvDtdvz7ZWKJXutHZ6TmyENjDYwcmcKeiXJ8LDGjc
	yUrryRlbD1EcZCWv7MumyX0dk6sq4o3+KsyU6l8Eb0S/NcnF0vscVzk1YizzbYMvh673
	ZXsPS2MI9Egq93qUbB9yKvL6oJCHgPSvZdwKFluyd5pR9OASw6/WUIyLuXjJbgXIE+Mp
	lue/+WkT/Xa0p0zh6Z95lfWCBoXNKXYp/dEpRoISdCNjxOfzrqg57SIdDqJkkOGRDG/z
	C5gDXtXpn6COeodGpPqHWbX2gd7Fid0Ku6VZqv4RdT+QgJVVgfLVc0n9BEe8raWKXqGL
	5MYA==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
	d=1e100.net; s=20161025;
	h=x-gm-message-state:mime-version:references:in-reply-to:from:date
	:message-id:subject:to;
	bh=SnSPwnkmMnkXGPIRENYhXMOnv8nnh4T9XM5b5AJptd8=;
	b=sJZ2pczsPLhpMxNZOBeEoq2L42X/WOFR7bVm0UnHRL9txecQGM1soa2KGQ9SJLFvCW
	+uWBw04YWwVYkFIZdDPjICyE00kf9eXzRMqQ/dEfvFTnYQ83OOmPL1TpZaJ02Mo/3EMQ
	gQBbCr7iYujWgdwhSp98ZPgj8E3vzLHHAXzHUFwoTFsHgsNsVXXlYYwCk0fOgdRUGbYk
	KEKBjYz5ND9vRXj6jYoVVf3aoqtY1rievAtXyV6+aUx+69LItnS4BdcEP74dtbp5ePxy
	XzwZ49XZDVwQ2YEGWjHAQ6j8Ja917e3SaZjyaAX7vANbJ+yVusMsUN0iJUifiloD77N1
	G1NQ==
X-Gm-Message-State: AA+aEWZoQy+hmTE3r2h0aCKcq1Od/bkdmjixIjgLUQIWYeLGYK4hYv4S
	ldYNj62NBROD0gupwui4Ke2HddIMvqf5qMqZBUIX53mK
X-Google-Smtp-Source: AFSGD/XKe4B3FF9RBu1lbTzYHt5nmcqB3jbQyLCZsG4JGYQ07ZWyQC+jNMiwUD8F9b8RRW/G8xexUuJTb7kJX20a/zU=
X-Received: by 2002:a9d:63cd:: with SMTP id e13mr21049347otl.319.1543376474452;
	Tue, 27 Nov 2018 19:41:14 -0800 (PST)
MIME-Version: 1.0
References: <CAPg+sBhuPG-2GXc+Bp0yv5ywry2fk56LPLT4AY0Kcs+YEoz4FA@mail.gmail.com>
In-Reply-To: <CAPg+sBhuPG-2GXc+Bp0yv5ywry2fk56LPLT4AY0Kcs+YEoz4FA@mail.gmail.com>
From: Pieter Wuille <pieter.wuille@gmail.com>
Date: Tue, 27 Nov 2018 19:41:02 -0800
Message-ID: <CAPg+sBiu0BjZEtz-t7m3M+TnAEDG_k1GKtxwkOKh6qrSezUO7g@mail.gmail.com>
To: Bitcoin Dev <bitcoin-dev@lists.linuxfoundation.org>
Content-Type: text/plain; charset="UTF-8"
X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED,
	DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM,
	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 04:58:04 +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 <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: Wed, 28 Nov 2018 03:41:16 -0000

On Mon, 19 Nov 2018 at 14:37, Pieter Wuille <pieter.wuille@gmail.com> wrote:
> Here is a combined proposal:
> * Three new sighash flags are added: SIGHASH_NOINPUT, SIGHASH_NOFEE, and SIGHASH_SCRIPTMASK.
> * A new opcode OP_MASK is added, which acts as a NOP during execution.
> * The sighash is computed like in BIP143, but:
>   * If SIGHASH_SCRIPTMASK is present, for every OP_MASK in scriptCode the subsequent opcode/push is removed.
>   * The scriptPubKey being spent is added to the sighash, unless SIGHASH_SCRIPTMASK is set.
>   * The transaction fee is added to the sighash, unless SIGHASH_NOFEE is set.
>   * hashPrevouts, hashSequence, and outpoint are set to null when SIGHASH_NOINPUT is set (like BIP118, but not for scriptCode).

Thanks for all the input so far. Going over the suggestions and other ideas:

* OP_MASK should be required to be followed by a push, as suggested by
Anthony Towns. The alternative would permit substituting arbitrary
opcodes for masked pushes, which is at least very hard to reason
about. This would effectively turn it into a multi-byte OP_MASKEDPUSH
opcode.

* It's probably better to sign the amounts of all inputs, as suggested
by Johnson Lau. As that would cause default sighashes to sign all
input and output amounts, is there still a need to sign the tx fee
explicitly? Or in other words, are there situations where changing the
set of inputs or outputs after signing is desired, but the net
difference between them cannot change? If not, that would remove the
need for NOFEE.

* Do we need to keep the rule that sequence values of other inputs are
only signed with default sighash? It feels cleaner to always sign the
sequence values of all inputs that are included in the sighash anyway
(so all of them, unless ANYONECANPAY or NOINPUT, which would make it
sign only the current input's sequence value). If NOINPUT also blanks
the sequence values (as currently specified by BIP118), and all input
amounts are signed, that would make amounts/sequence values always be
treated identically.

* If MASK implies NOINPUT, and NOINPUT implies ANYONECANPAY, the 3 of
them can be encoded in just 2 bits using the
PARTIALSCRIPT/KNOWNSCRIPT/KNOWNTX/ALL_INPUTS encoding Anthony Towns
suggested.

* Regarding the discussion about preventing signatures from being
rebound to a different script(path)/checksig:
  * With MAST there is indeed less need for this, but at least
single-tree MAST constructions cannot replace all script branches (a
script with 40 IF/THEN/ELSE constructions may have 2^40 different
execution paths, for which computing a Merkle tree is intractable).
  * Just signing the opcode position of the CHECKSIG operator isn't
enough for all cases either. For example, you could have a complex
nested set of branches that puts a number of pubkeys on the stack, and
then a CHECKMULTISIG after the last ENDIF to verify all of them. In
such a situation, if the same key can occur in multiple combinations,
you still may want to prevent a signature generated for one
combination from being rebindable to the same key in another
combination. I believe that signing the opcode position plus the
true/false condition of all previous(?) IF statements is probably
sufficient to achieve that, but it would also introduce unnecessary
complexity for signers in most cases (see next point).
  * Thinking about signing code, adding these sort of execution trace
commitments to the sighash means they need to know which checksig
operator etc. they are signing for. I believe that in practice for
example HW devices will just whatever position the wallet indicated,
rather than verifying it corresponds with a particular intended code
path. Preventing rebinding isn't very useful if an attacker can make
you bind to the wrong thing regardless, so I'm not convinced this is
even worth having by default.
  * An alternative (not sure who suggested it) is to simply make every
CHECKSIG sign the opcode position of the last executed CODESEPARATOR
(and remove the earlier cut-of-scriptCode effect of CODESEPARATOR).
This gives a simple (but somewhat limited) way for scripts that need
to prevent certain kinds of cross-execution-trace rebinding.

A few misc ideas:
* (Taken from https://github.com/jl2012/bips/blob/sighash2/bip-sighash2.mediawiki)
For a default sign-everything sighash, the sighash byte can be
dropped.
* For the commitments to the scriptPubKey and scriptCode, an
intermediary hash should be used (so the data included in the sighash
includes a hash of those, rather than the script directly). This
prevents a blow up in hashing time for large scripts with many
different sighash types in its signatures.
* When masking the scriptCode, the push opcode immediately following
OP_MASKEDPUSH can be replaced by OP_VERIF (which will never collide
with any real script, as OP_VERIF makes a script invalid even when
occurring in an unexecuted branch).
* Sighashes (and really all new hashes that are introduced) should be
prefixed with a fixed 64-byte array as "tag", chosen to not collide
with any existing use of SHA256 in Bitcoin, to prevent signatures from
being re-interpretable as something else. Picking 64 bytes as tag size
means it can be efficiently implemented as just a modified SHA256 IV.

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.
* 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)
    * The hash of all txouts (or just the corresponding txout if
SINGLE; nothing if NONE)
    * 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)
  * Data about the script being executed:
    * The hash of the scriptCode (after masking out, if MASK is set)
    * The opcode number of the last executed OP_CODESEPARATOR (or
0xFFFFFFFF if none)
  * The sighash mode

Cheers,

-- 
Pieter