Re: [bitcoin-dev] Generalised Replay Protection for Future Hard Forks

2017-11-14 Thread Mats Jerratsch via bitcoin-dev

> But I like the 'old' idea of putting the hash of a block that MUST be on the 
> chain that this txn can eventually be added to. If the hash is not a valid 
> block on the chain, the txn can't be added.
> 
> It means you can choose exactly which forks you want to allow your txn on, 
> pre-fork for both, post-fork for only one, and gets round the issue of who 
> gets to decide the nForkid value.. since you don't need one. Also, all the 
> old outputs work fine, and LN not an issue.
> 
> I'm missing why this scheme would be better ?

I do agree that solutions like `SIGHASH_BLOCKCOMMIT` are superior in the sense 
that they are very difficult to circumvent. However, a fork could also follow 
the original chain in SPV mode and allow transactions protected with these 
mechanism. Since it's fundamentally impossible to disallow transactions in 
future projects, the goal shouldn't be to make this overly complicated.

Furthermore, this schema is not just adding replay protection. It makes 
transacting safer overall (due to a dedicated address format per fork) and 
allows light clients to differentiate between multiple forks. In the past three 
months, at least $600k has been lost by users sending BCH to a BTC address [1].

> Thanks for the clarification.  How would a tx specify a constraint like 
> "nForkId>=1"?  I was thinking of it just as a number set on the tx.

Whether the transaction is replay protected or not is specified by setting a 
bit in the `SigHashId`. If this bit is set, then the signature *preimage* MUST 
have `nForkId` appended. `nForkId` is not part of the final transaction, 
someone who wants to verify the transaction must know which `nForkId` it was 
created with.

If the bit isn't set, it means `nForkId=0`, which allows other forks to 
validate the signature.

> Also note that since forks form a partial order, but IDs (numbers) form a 
> total order, ">=" will miss some cases.  Eg, suppose BCH had forked with 
> nForkId 2, and then you set up a LN funding tx on BCH with nForkId>=2, and 
> then Segwit2x forked (from BTC!) with nForkId 3.  The BCH funding tx would be 
> valid on Segwit2x.  This is more of a fundamental problem than a bug - to 
> avoid it you'd have to get into stuff like making each fork reference its 
> parent-fork's first block or something, someone has written about this...

Sorry, I was careless with the use of `>=` there. You are correct, forks form a 
tree. For this proposal, every leaf must be assigned a unique `nForkId`. The 
relationship between `nForkId` is irrelevant (e.g. which number is bigger), as 
long as they are unique. Transactions are only valid IFF `nForkId` matches 
exactly the `nForkId` of the software validating it. As described above, the 
transaction doesn't even contain `nForkId`, and the node surely is not starting 
to guess which one it could be.

[1]
https://twitter.com/khannib/status/930223617744437253 



signature.asc
Description: Message signed with OpenPGP
___
bitcoin-dev mailing list
bitcoin-dev@lists.linuxfoundation.org
https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev


Re: [bitcoin-dev] Generalised Replay Protection for Future Hard Forks

2017-11-13 Thread Mats Jerratsch via bitcoin-dev

> OK, so nForkId 0 is exactly the "valid on all chains" specifier I was asking 
> about, cool.  And your LN example (and nLockTime txs in general) illustrate 
> why it's preferable to implement a generic replay protection scheme like 
> yours in advance, rather than before each fork: all ad hoc RP schemes I know 
> of break old txs on one of the chains, even when that's not desirable - ie, 
> they offer no wildcard like nForkId 0.

Exactly!

> One comment on your LN example: users would have to take note that nForkId 0 
> txs would be valid not only on future forks, but on past forks too.  Eg, if 
> BCH had been deployed with nForkId 2, then a user setting up BTC LN txs now 
> with nForkId 0 would have to be aware that those txs would be valid for BCH 
> too.  Of course the user could avoid this by funding from a BTC-only address, 
> but it is a potential minor pitfall of nForkId 0.  (Which I don't see any 
> clean way around.)

This is actually incorrect. There are two transactions involved in LN. The 
funding transaction, which opens a payment channel, and a commitment 
transaction, which closes the channel when broadcasted to the network (the 
cooperative closing transaction can be considered a commitment transaction in a 
loose sense).

Now you want to protect the funding transaction, as otherwise you would be 
subject to a replay-attack on all *past* forks. So you will set `nForkId>=1` 
for the funding transaction, making this payment channel non-existent on any 
*past* forks. However, if during the lifetime of the payment channel another 
fork happens, the payment channel exists for both tokens. So for the commitment 
transaction, you will have `nForkId=0`, making it valid on both of these 
chains. While this `nForkId` is valid on all chains, the parent transaction it 
tries to spend (the funding transaction) does only exist on two chains, the 
original one you created the channel for and the one that forked away.


signature.asc
Description: Message signed with OpenPGP
___
bitcoin-dev mailing list
bitcoin-dev@lists.linuxfoundation.org
https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev


Re: [bitcoin-dev] Generalised Replay Protection for Future Hard Forks

2017-11-10 Thread Mats Jerratsch via bitcoin-dev
I guess I wasn't clear on the wildcard, `nForkId=0`

This proposal puts Bitcoin at `nForkId=1`, with the purpose of having 
`nForkId=0` valid on *all* future forks. This means you can create a 
`nLockTime` transaction, delete the private key and still be assured to not 
lose potential future tokens.

In theory `nForkId=0` could be used for an address too, the sending wallet 
should display a warning message about unknown side effects though. This 
address would be future-safe, and you can put it into a safe-deposit box (even 
though I see little reason to back up an _address_. You would always back up a 
_private key_, which translates into funds on any fork.)

Furthermore, `nForkId=0` can be used for L2 applications. Let's say Alice and 
Bob open a payment channel. One week later, project X decides to fork the 
network into a new token, implementing a custom way of providing strong two-way 
replay protection. The protocol Alice and Bob use for the payment channel has 
not implemented this new form of replay protection. Alice and Bob now have to 
make a choice:

(1) Ignore this new token. This comes with an evaluation of how much this new 
token could be worth in the future. They will continue normal channel 
operation, knowing that their funds on the other branch will be locked up until 
eternity. When they close their payment channel, the closing transaction will 
get rejected from the other network, because it's not following the format for 
replay protected transactions.

(2) Close the payment channel before the fork. The transaction, which closes 
the payment channel has to be mined before the fork, potentially paying a 
higher-than-normal fee.

With this proposal implemented, there are two additional choices

(3) Create the commitment transactions with `nForkId=0`. This ensures that when 
the channel gets closed, funds on other chains are released accordingly. This 
also means that after the fork, payments on the channel move both, the original 
token and the new token. Potentially, Alice and Bob want to wait before further 
transacting on the channel, to see if the token has substantial value. If it 
has, they can *then* close the channel and open a new channel again. (Note: The 
funding transaction can use a specific `nForkId`, preventing you from locking 
up multiple coins when funding the channel, but you can choose to settle with 
`nForkId=0` to not lock up future coins)

(4) Make the protocol aware of different `nForkId`. After the fork, the 
participants can chose to *only* close the payment channel on the new token, 
making the payment channel Bitcoin-only again. This is the preferred option, as 
it means no disruption to the original network.

> I like the idea of specifying the fork in bech32 [0]. On the other hand, the 
> standard already has a human readable part. Perhaps the human readable part 
> can be used as the fork id?

I was considering this too. On the other hand, it's only _human readable_ 
because thy bytes used currently encode 'bc'. For future forks, this would just 
be two random letters than, but potentially acceptable.



signature.asc
Description: Message signed with OpenPGP
___
bitcoin-dev mailing list
bitcoin-dev@lists.linuxfoundation.org
https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev


Re: [bitcoin-dev] Generalised Replay Protection for Future Hard Forks

2017-11-08 Thread Mats Jerratsch via bitcoin-dev
Hey Jacob!

> 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.

With this proposal implemented, a 'mis-send' is fundamentally impossible. The 
address contains the identifier of the token that should be sent.

If anything, it's possible to 'mis-receive'.
That is, the receiving wallet was not aware of a newer chain, and the receiver 
actually wanted to receive the newer token, but instead his wallet created an 
address for the old token. It is the responsibility of the receiver to write a 
correct invoice. This is the case everywhere else in the world too, so this 
seems like a reasonable trade-off.

I would even argue that this should hold in a legal case, where the receiver 
cannot claim that he was expecting a payment in another token (contrary to how 
it is today, like when users send BTC to a BCH address, losing their funds with 
potentially no legal right for reimbursement). If I sent someone an invoice 
over 100€, I cannot later proclaim that I actually expected $100.

With this proposal, wallets are finally able to distinguish between different 
tokens. With this ability, I expect to see different implementations, some 
wallets which advertise staying conservative, following a strict ruleset, and 
other wallets being more experimental, following hashing rate or other metrics.



signature.asc
Description: Message signed with OpenPGP
___
bitcoin-dev mailing list
bitcoin-dev@lists.linuxfoundation.org
https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev


[bitcoin-dev] Generalised Replay Protection for Future Hard Forks

2017-11-06 Thread Mats Jerratsch via bitcoin-dev

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
 



signature.asc
Description: Message signed with OpenPGP
___
bitcoin-dev mailing list
bitcoin-dev@lists.linuxfoundation.org
https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev


Re: [bitcoin-dev] BIP CPRKV: Check private key verify

2016-02-29 Thread Mats Jerratsch via bitcoin-dev
This is actually very useful for LN too, see relevant discussion here

http://lists.linuxfoundation.org/pipermail/bitcoin-dev/2015-November/011827.html

2016-02-12 11:05 GMT+01:00 Tier Nolan via bitcoin-dev
:
> On Fri, Feb 12, 2016 at 5:02 AM,  wrote:
>>
>> Seems it could be done without any new opcode:
>
>
> The assumption was that the altcoin would only accept standard output
> scripts.  Alice's payment in step 2 pays to a non-standard script.
>
> This is an improvement over the cut and choose, but it will only work for
> coins which allow non-standard scripts (type 2 in the BIP).
>
> I guess I was to focused on maintaining standard scripts on the altcoin.
>
> ___
> bitcoin-dev mailing list
> bitcoin-dev@lists.linuxfoundation.org
> https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev
>
___
bitcoin-dev mailing list
bitcoin-dev@lists.linuxfoundation.org
https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev


[bitcoin-dev] [BIP] OP_CHECKPRIVPUBPAIR

2015-11-27 Thread Mats Jerratsch via bitcoin-dev
Prior discussion:
http://lists.linuxfoundation.org/pipermail/lightning-dev/2015-November/000309.html

Goal:
Greatly improve security for payment networks like the 'Lightning
Network' (LN) [1]

---

Introduction:
To improve privacy while using a payment network, it is possible to
use onion-routing to make a payment to someone. In this context,
onion-routing means encrypting the data about subsequent hops in a way
that each node only knows where it received a payment from and the
direct next node it should send the payment to. This way we can route
a payment over N nodes, and none of these will know

(1) at which position it is within the route (first, middle, last?)

(2) which node initially issued the payment (payer)

(3) which node consumes the payment (payee).

However, given the way payments in LN work, each payment is uniquely
identifiable by a preimage-hash pair R-H. H is included in the output
script of the commit transaction, such that the payment is enforceable
if you ever get to know the preimage R.

In a payment network each node makes a promise to pay the next node,
if they can produce R. They can pass on the payment, as they know that
they can enforce the payment from a previous node using the same
preimage R. This severely damages privacy, as it lowers the amount of
nodes an attacker has to control to gain information about payer and
payee.

---

Problem:
The problem was inherited by using RIPEMD-160 for preimage-hash
construction. For any cryptographic hash-function it is fundamentally
unfeasible to correlate preimage and hash in such a way, that

F1(R1) = R2 and
F2(H1) = H2, while
SHA(R1) = H1 and SHA(R2) = H2.

In other words, I cannot give a node H1 and H2 and ask it to receive
my payment using H1, but pass it on using H2, as the node has no way
of verifying it can produce R1 out of the R2 it will receive. If it
cannot produce R1, it is unable to enforce my part of the contract.

---

Solution:
While above functions are merely impossible to construct for a
cryptographic hash functions, they are trivial when R and H is a EC
private/public key pair. The original sender can make a payment using
H1 and pass on a random number M1, such that the node can calculate a
new public key

H2 = H1 + M1.

When he later receives the private key R2, he can construct

R1 = R2 - M1

to be able to enforce the other payment. M1 can be passed on in the
onion object, such that each node can only see M for that hop.
Furthermore, it is unfeasible to brute-force, given a sufficiently
large number M.

---

Example:

Given that E wants to receive a payment from A, payable to H. (if A
can produce R, it can be used as a prove he made the payment and E
received it)

A decides to route the payment over the nodes B, C and D. A uses four
numbers M1...M4 to calculate H1...H4. The following payments then take
place

A->B using H4
B->C using H3
C->D using H2
D->E using H1.

When E receives H1, he can use attached M1 to calculate R1 from it.
The chain will resolve itself, and A is able to calculate R using
M1...M4. It also means that all privacy is at the sole discretion of
the sender, and that not even the original pair R/H is known to any of
the nodes.

To improve privacy, E could also be a rendezvous point chosen by the
real receiver of the payment, similar constructions are similar in
that direction as well.

---

Caveats:

Currently it is difficult to enforce a payment to a private-public key
pair on the blockchain. While there exists OP_HASH160 OP_EQUAL to
enforce a payment to a hash, the same does not hold true for EC keys.
To make above possible we would therefore need some easy way to force
a private key, given a public key. This could be done by using one of
the unused OP_NOP codes, which will verify

  OP_CHECKPRIVPUBPAIR

and fails if these are not correlated or NOP otherwise. Would need
OP_2DROP afterwards. This would allow deployment using a softfork.

As there are requests for all sort of general crypto operations in
script, we can also introduce a new general OP_CRYPTO and prepend one
byte for the operation, so

0x01 OP_CRYPTO = OP_CHECKPRIVPUBPAIR
0x02-0xff OP_CRYPTO = OP_NOP

to allow for extension at some later point.

---

Alternatives:

In the attached discussion there are some constructions that would
allow breaking the signature scheme, but they are either very large in
script language or expensive to calculate. Given that the blocksize is
a difficult topic already, it would not be beneficial to have a 400B+
for each open payment in case one party breaches the contract. (or
just disappears for a couple of days)

It is also possible to use a NIZKP - more specifically SNARK - to
prove to one node that it is able to recover a preimage R1 = R2 XOR
M1, given only H1, H2 and M1. However, these are expensive to
calculate and experimental in it's current state.

---

Acknowledgements:
Gregory Maxwell for pointing out addition of M1 for EC points is much
less expensive
Pieter Wuille for helping with general