Return-Path: Received: from smtp1.linuxfoundation.org (smtp1.linux-foundation.org [172.17.192.35]) by mail.linuxfoundation.org (Postfix) with ESMTPS id CE35394F for ; Mon, 6 Nov 2017 19:21:32 +0000 (UTC) X-Greylist: whitelisted by SQLgrey-1.7.6 Received: from mail-lf0-f54.google.com (mail-lf0-f54.google.com [209.85.215.54]) by smtp1.linuxfoundation.org (Postfix) with ESMTPS id 69D0920D for ; Mon, 6 Nov 2017 19:21:31 +0000 (UTC) Received: by mail-lf0-f54.google.com with SMTP id a2so11714436lfh.11 for ; Mon, 06 Nov 2017 11:21:31 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:in-reply-to:references:from:date:message-id:subject:to; bh=Y3YaQ38eajBByNb0U0hoQWoN7kj1HkVTKqh/901HRfY=; b=qZrqZ4QmPytAspAJDcI6Q/tGYgshx4tQtkcwOoE2SlIG8/F+EJ/+VV6GFDEwbSoaJx Q25D14LVRmxqV5moFdep4berXFaICigZA/F0eaPDRaRKGS9DKsfYS0n0kFepUsh1/U0x oyUF5lMc3GyWCrlRNlFYbIcCyWAJ/8QQ88/7KfGJ3+3dJNfFXvIt224QWrsHmlj5aMFe BpG1L/2Sf45LpO+VtZRrgvIafzu2RBX0GjO+Xf+9u4GVu3+Vryy1MIn0H4o3AOzPsbMY L/j8TDVJ96M2yHB023b4cksHFSeVSjZGoo6Ap/I1USS5dFn6S9kLvDR1uvQOIMxPKiiW EVfg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:in-reply-to:references:from:date :message-id:subject:to; bh=Y3YaQ38eajBByNb0U0hoQWoN7kj1HkVTKqh/901HRfY=; b=bZacS6GyjOeGfpjR0qss0DMN/Henl8ufbJNl3gdtb67S8H/nXmwiNLeG/JEulsAOoq UfIcXx3wxgBMsijt0vFng9eJR2tS24Z8JEfd0t8t7AF+hh+wVT0PN5i7A7MSkGD0lRFO aCJjltlELoyEIST+llgDXwOeFSyNOY+m1VFetecILkSx9Xyz0661e84vmxbyNTNajB43 W0xlwvw5uFedQXrvrZvE8uDUORcRFeogvdIeBLUbwQOdK1IZ9noAWdOG/2qA68QOc6ws Xx7KzBVdMqEn/9UTEow+rJP8sGtympJA8yLLU2Ko+PdboblFBvUGN9a9yCPAxEguzx55 Ow4w== X-Gm-Message-State: AJaThX6w+VBS7zM1G3FI10KnS/u1pRpXA+wTOdXbTHiZZJDA5c7pQODw yhAt5W9EE7i1av6M8/0FdhR0/mKp96JAxZOug0w= X-Google-Smtp-Source: ABhQp+QmbDF3EhE14R7boFf3ub6CGXXzzCo9VufJiN+SC7xV6bNcbeDXBfaNpyB8/Zcdg/wjXVngRenQntF/nQLCPeE= X-Received: by 10.25.78.10 with SMTP id c10mr6137778lfb.4.1509996089716; Mon, 06 Nov 2017 11:21:29 -0800 (PST) MIME-Version: 1.0 Received: by 10.25.168.7 with HTTP; Mon, 6 Nov 2017 11:21:28 -0800 (PST) Received: by 10.25.168.7 with HTTP; Mon, 6 Nov 2017 11:21:28 -0800 (PST) In-Reply-To: References: <7601C2CD-8544-4501-80CE-CAEB402A72D2@blockchain.com> From: Jacob Eliosoff Date: Mon, 6 Nov 2017 14:21:28 -0500 Message-ID: To: Mats Jerratsch , Bitcoin Dev Content-Type: multipart/alternative; boundary="94eb2c1cdd8c8a3368055d555cd1" X-Spam-Status: No, score=0.4 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,FREEMAIL_FROM,HTML_MESSAGE,RCVD_IN_DNSWL_NONE, RCVD_IN_SORBS_SPAM autolearn=disabled version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on smtp1.linux-foundation.org X-Mailman-Approved-At: Mon, 06 Nov 2017 23:54:24 +0000 Subject: Re: [bitcoin-dev] Generalised Replay Protection for Future Hard Forks 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: Mon, 06 Nov 2017 19:21:32 -0000 --94eb2c1cdd8c8a3368055d555cd1 Content-Type: text/plain; charset="UTF-8" Thanks Mats, this proposal makes sense to me (especially the idea of fork-specific addresses). It prevents replay across forks, and makes it easy for client software, and thus potentially users, to specify which fork a tx is for. But, like other (rougher) past proposals I've seen, it does little to prevent users from accidentally sending on the wrong fork. Take the specific and common case of non-upgraded wallet software. Suppose a HF happens, and becomes the network used by 90% of users. Will old wallets still default to the old nForkId (10% legacy chain)? If so, I'd expect a lot of accidental mis-sends on that chain. This is just a gap in your proposal, not a flaw, but it's worth thinking about less hazard-prone ways wallets could default nForkId. Perhaps they could listen to all forks, and default to the one whose last (recent) block had the highest difficulty? Or just check those blocks to see if multiple forks are (nontrivially) active, and if so warn the user and force them to confirm? Something like that. On Nov 6, 2017 7:05 AM, "Mats Jerratsch via bitcoin-dev" < bitcoin-dev@lists.linuxfoundation.org> wrote: Presented is a generalised way of providing replay protection for future hard forks. On top of replay protection, this schema also allows for fork-distinct addresses and potentially a way to opt-out of replay protection of any fork, where deemed necessary (can be beneficial for some L2 applications). ## Rationale Currently when a hard fork happens, there is ad-hoc replay protection built within days with little review at best, or no replay protection at all. Often this is either resource problem, where not enough time and developers are available to sufficiently address replay protection, or the idea that not breaking compatibility is favourable. Furthermore, this is potentially a recurring problem with no generally accepted solution yet. Services that want to deal in multiple forks are expected to closely follow all projects. Since there is no standard, the solutions differ for each project, requiring custom code for every fork. By integrating replay protection into the protocol, we advocate the notion of non-hostile forks. Users are protected against accidentally sending coins on the wrong chain through the introduction of a fork-specific incompatible address space. The coin/token type is encoded in the address itself, removing some of the importance around the question _What is Bitcoin?_. By giving someone an address, it is explicitly stated _I will only honour a payment of token X_, enforcing the idea of validating the payment under the rules chosen by the payee. ## Iterative Forks In this schema, any hard fork is given an incremented id, `nForkId`. `nForkId` starts at `1`, with `0` being reserved as a wildcard. When project X decides to make an incompatible change to the protocol, it will get assigned a new unique `nForkId` for this fork. A similar approach like for BIP43 can be taken here. Potentially `nForkId` can be reused if a project has not gained any amount of traction. When preparing the transaction for signing or validation, `nForkId` is appended to the final template as a 4B integer (similar to [1]). Amending BIP143, this would result in ``` Double SHA256 of the serialization of: 1. nVersion of the transaction (4-byte little endian) 2. hashPrevouts (32-byte hash) 3. hashSequence (32-byte hash) 4. outpoint (32-byte hash + 4-byte little endian) 5. scriptCode of the input (serialized as scripts inside CTxOuts) 6. value of the output spent by this input (8-byte little endian) 7. nSequence of the input (4-byte little endian) 8. hashOutputs (32-byte hash) 9. nLocktime of the transaction (4-byte little endian) 10. sighash type of the signature (4-byte little endian) 11. nForkId (4-byte little endian) ``` For `nForkId=0` this step is ommitted. This will immediately invalidate signatures for any other branch of the blockchain than this specific fork. To distinguish between `nForkId=0` and `nForkId` hardcoded into the software, another bit has to be set in the 1B SigHashId present at the end of signatures. To make this approach more generic, payment addresses will contain the fork id, depending on which tokens a payee expects payments in. This would require a change on bech32 addresses, maybe to use a similar format used in lightning-rfc [2]. A wallet will parse the address, it will extract `nForkId`, and it displays which token the user is about to spend. When signing the transaction, it will use `nForkId`, such that the transaction is only valid for this specific token. This can be generalised in software to the point where replay protection *and* a new address space can be introduced for forks without breaking existing clients. For light clients, this can be extended by enforcing the coinbase/block header to contain the `nForkId` of the block. Then the client can distinguish between different chains and tokens it received on each. Alternatively, a new P2P message type for sending transactions could be introduced, where prevOut and `nForkId` is transmitted, such that the lite client can check for himself, which token he received. Allowing signatures with `nForkId=1` can be achieved with a soft fork by incrementing the script version of SegWit, making this a fully backwards compatible change. [1] https://lists.linuxfoundation.org/pipermail/bitcoin-dev/ 2017-February/013542.html [2] https://github.com/lightningnetwork/lightning-rfc/blob/master/11-payment- encoding.md _______________________________________________ bitcoin-dev mailing list bitcoin-dev@lists.linuxfoundation.org https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev --94eb2c1cdd8c8a3368055d555cd1 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
Thanks Mats, this proposal makes sense to me (especially = the idea of fork-specific addresses).=C2=A0 It prevents replay across forks= , and makes it easy for client software, and thus potentially users, to spe= cify which fork a tx is for.=C2=A0 But, like other (rougher) past proposals= I've seen, it does little to prevent users from accidentally sending o= n the wrong fork.

Take the spe= cific and common case of non-upgraded wallet software.=C2=A0 Suppose a HF h= appens, and becomes the network used by 90% of users.=C2=A0 Will old wallet= s still default to the old nForkId (10% legacy chain)?=C2=A0 If so, I'd= expect a lot of accidental mis-sends on that chain.

This is just a gap in your proposal, not a fla= w, but it's worth thinking about less hazard-prone ways wallets could d= efault nForkId.=C2=A0 Perhaps they could listen to all forks, and default t= o the one whose last (recent) block had the highest difficulty?=C2=A0 Or ju= st check those blocks to see if multiple forks are (nontrivially) active, a= nd if so warn the user and force them to confirm?=C2=A0 Something like that= .


On Nov 6, 2017 7:05 AM, "Mats Jerratsch via bi= tcoin-dev" <bitcoin-dev@lists.linuxfoundation.org> wrote:

Prese= nted is a generalised way of providing replay protection for future hard fo= rks. On top of replay protection, this schema also allows for fork-distinct= addresses and potentially a way to opt-out of replay protection of any for= k, where deemed necessary (can be beneficial for some L2 applications).

## Rationale

Currently when a hard fork happens, there i= s ad-hoc replay protection built within days with little review at best, or= no replay protection at all. Often this is either resource problem, where = not enough time and developers are available to sufficiently address replay= protection, or the idea that not breaking compatibility is favourable. Fur= thermore, this is potentially a recurring problem with no generally accepte= d solution yet. Services that want to deal in multiple forks are expected t= o closely follow all projects. Since there is no standard, the solutions di= ffer for each project, requiring custom code for every fork. By integrating= replay protection into the protocol, we advocate the notion of non-hostile= forks.

Users are protected against accidentally sending coins o= n the wrong chain through the introduction of a fork-specific incompatible = address space. The coin/token type is encoded in the address itself, removi= ng some of the importance around the question _What is Bitcoin?_. By giving= someone an address, it is explicitly stated _I will only honour a payment = of token X_, enforcing the idea of validating the payment under the rules c= hosen by the payee.

## Iterative Forks

In this schem= a, any hard fork is given an incremented id, `nForkId`. `nForkId` starts at= `1`, with `0` being reserved as a wildcard. When project X decides to make= an incompatible change to the protocol, it will get assigned a new unique = `nForkId` for this fork. A similar approach like for BIP43 can be taken her= e. Potentially `nForkId` can be reused if a project has not gained any amou= nt of traction.

When preparing the transaction for signing or va= lidation, `nForkId` is appended to the final template as a 4B integer (simi= lar to [1]). Amending BIP143, this would result in

```
D= ouble SHA256 of the serialization of:
=C2=A0=C2=A0=C2=A0=C2=A01. nVersion o= f the transaction (4-byte little endian)
=C2=A0=C2=A0=C2=A0=C2=A02. hashPre= vouts (32-byte hash)
=C2=A0=C2=A0=C2=A0=C2=A03. hashSequence (32-byte hash)=
= =C2=A0=C2=A0=C2=A0=C2=A04. outpoint (32-byte hash + 4-byte little endian) =
= =C2=A0=C2=A0=C2=A0=C2=A05. scriptCode of the input (serialized as scripts = inside CTxOuts)
=C2=A0=C2=A0=C2=A0=C2=A06. value of the output spent by thi= s input (8-byte little endian)
=C2=A0=C2=A0=C2=A0=C2=A07. nSequence of the = input (4-byte little endian)
=C2=A0=C2=A0=C2=A0=C2=A08. hashOutputs (32-byt= e hash)
=C2=A0=C2=A0=C2=A0=C2=A09. nLocktime of the transaction (4-byte lit= tle endian)
<= /span> =C2=A0=C2=A0=C2=A010. sighash type of the signature (4-byte lit= tle endian)
=C2=A0=C2=A0=C2=A011. nFo= rkId (4-byte little endian)
```


For `nForkId=3D0` thi= s step is ommitted. This will immediately invalidate signatures for any oth= er branch of the blockchain than this specific fork. To distinguish between= `nForkId=3D0` and `nForkId` hardcoded into the software, another bit has t= o be set in the 1B SigHashId present at the end of signatures.
= To make this approach more generic, payment addresses will contain the fork= id, depending on which tokens a payee expects payments in. This would requ= ire a change on bech32 addresses, maybe to use a similar format used in lig= htning-rfc [2]. A wallet will parse the address, it will extract `nForkId`,= and it displays which token the user is about to spend. When signing the t= ransaction, it will use `nForkId`, such that the transaction is only valid = for this specific token. This can be generalised in software to the point w= here replay protection *and* a new address space can be introduced for fork= s without breaking existing clients.

For light clients, this ca= n be extended by enforcing the coinbase/block header to contain the `nForkI= d` of the block. Then the client can distinguish between different chains a= nd tokens it received on each. Alternatively, a new P2P message type for se= nding transactions could be introduced, where prevOut and `nForkId` is tran= smitted, such that the lite client can check for himself, which token he re= ceived.

Allowing signatures with `nForkId=3D1` can be achieved = with a soft fork by incrementing the script version of SegWit, making this = a fully backwards compatible change.

[1]

[2]

_______________________________________________
bitcoin-dev mailing list
bitcoin-dev@lists.= linuxfoundation.org
https://lists.linuxfoundation.org= /mailman/listinfo/bitcoin-dev


--94eb2c1cdd8c8a3368055d555cd1--