Skip to content
This repository has been archived by the owner on Oct 3, 2020. It is now read-only.

Possible conflict of pay-to-contract schemes with Taproot #61

Closed
ZmnSCPxj opened this issue Sep 3, 2018 · 18 comments
Closed

Possible conflict of pay-to-contract schemes with Taproot #61

ZmnSCPxj opened this issue Sep 3, 2018 · 18 comments

Comments

@ZmnSCPxj
Copy link

ZmnSCPxj commented Sep 3, 2018

As the subject says, pay-to-contract schemes may conflict with Taproot in the future, if extended naively to a future Bitcoin version with Taproot support.

Proofs may themselves be marshalled into a form which can also be read as Bitcoin SCRIPT. This would allow a scammer to induce a victim to construct a proof that can be reinterpreted as a Bitcoin SCRIPT which the scammer may know how to solve, allowing the scammer to burn the colored asset and steal the backing Bitcoin UTXO via the always-enabled Taproot branch. I have not seen spec about proof marshalling (perhaps, not yet created?), but this is care point.

An idea, is to make an OP_RETURN byte (0x6A) be the first byte in every marshalling of a proof. Thus when reinterpreted as Bitcoin SCRIPT, the first instruction, is an OP_RETURN, which prevents the proof from being reinterpreted as a Bitcoin SCRIPT that can be solved, as OP_RETURN scripts are unsolveable.

(Another mitigation is to make the backing Bitcoin funds so small as to be not worth the effort of stealing, but this may conflict with your intended plan, for using also a UTXO to back LN channels with both Bitcoin and asset)

(also this may be an argument against an always-enabled Taproot; possibly we could add a flag or marker, in the contract space, which selects "domain", and Bitcoin Taproot is simply an additional domain)

Care must still be taken in future. Other schemes that use pay-to-contract may also conflict with RGB usage in the same manner: a proof marshalling under RGB may be reinterpreted as a contract in another scheme, which may lead to victims assuming they have proofs under one system and then inadvertently signing off on a proof/contract for another system.

@afilini
Copy link
Collaborator

afilini commented Sep 3, 2018

I really have to catch up on Taproot since I don't know much about it, but my initial impression is that doing this would require to break an hash function: in our pay-to-contract scheme we would only commit to the hash of a proof, and many of its fields are controlled by the "sender" (which, if I understood correctly, should be the victim in the model you described).

So, the attacker would have to craft and "address" such that, once embedded into a proof (possibly with some data he doesn't know yet) will make the hash of the proof an executable, malicious, Bitcoin SCRIPT.

Now I'll go study and come back later when I fully understand how Taproot works ;)

PS: if you have any good references/articles please let me know here or via DM at twitter.com/afilini

@afilini
Copy link
Collaborator

afilini commented Sep 3, 2018

Oh, and about your suggestion of making small Bitcoin amounts: I was thinking about it while writing the slides for the Berlin Lightning hackday a couple of days ago.. Speaking for the Lightning part, my idea was to force the payment of fees on the underlying Bitcoin layer, to reduce the amount of data we have to gossip around (we already have Bitcoin fees and asset/Bitcoin exchange rate).

In this model, in order to have proportional fees, you would need to use the exchange rate to estimate the value of the asset being moved in Bitcoin, and then apply the Bitcoin proportional fee to it.

If this is really what we end up doing (I honestly don't really like it but I don't have any other solution yet) you would need pretty "big" Bitcoin channels to transport "big" RGB proofs, otherwise you wouldn't have enough liquidity to move the tokens.


Link to the talk if you are interested: https://youtu.be/QrX1SpD6l9g?t=5h9m47s

@ZmnSCPxj
Copy link
Author

ZmnSCPxj commented Sep 3, 2018

but my initial impression is that doing this would require to break an hash function: in our pay-to-contract scheme we would only commit to the hash of a proof

It may be possible to do so opportunistically. For instance, if the first two bytes of the hash are 0x4C 0x1E (OP_PUSHDATA1 30: push the next 30 bytes in the script as a single word on the stack), this results with high probability to a SCRIPT that pushes a truthy (nonzero) value on the stack, and is therefore anyone-can-spend with an empty witness stack. About 1 out of 65536 contracts will hash to a value that starts with those two bytes. Other reinterpretations to OP_PUSHDATA* opcodes may also be possible

Of course, it is possible that Taproot will also use a hash to further protect the Bitcoin SCRIPT and make such reinterpretation much harder with high probability. I have not seen enough details on the low-level of Taproot myself, perhaps it may also use a hash around the script before concatenating with the pubkey and hashing again. It may be useful to ask gmax or similar if this concern is unfounded.

@ZmnSCPxj
Copy link
Author

ZmnSCPxj commented Sep 3, 2018

it is possible that Taproot will also use a hash to further protect the Bitcoin SCRIPT and make such reinterpretation much harder with high probability

No, I apologize, I am being daft here. If Taproot does use a hash and you also use a hash, and it is the same hash function, then the direct serialization of your proof might be reinterpreted as a direct serialization of a Bitcoin SCRIPT, and various values and codes you use in your proofs may correspond to particular Bitcoin SCRIPT opcodes that could lead to an easily-spendable Bitcoin SCRIPT.

In short: you may need to look very well into any concrete Taproot proposal that comes up in the future (there are none yet other than basic sketches).

@afilini
Copy link
Collaborator

afilini commented Sep 3, 2018

Yes, if the hash function is the same (and I think it would be likely), then it could become an issue.

As I said before, I think it would be hard to force the victim into unknowingly pay to a precise SCRIPT, but as you pointed out in many cases a big "family" of SCRIPTs can make you loose funds.

I guess I will keep this open as a reminder and to see if someone else has an idea to propose. Once Taproot will be finalized we will make sure there are no conflicts.

@ZmnSCPxj
Copy link
Author

ZmnSCPxj commented Sep 3, 2018

Taproot is the most obvious, but, if other schemes also use pay-to-contract similarly, again a UTXO committing to an RGB proof may itself be reinterpreted as committing to a different pay-to-contract scheme contract. I have a thread on bitcoin-dev awaiting moderation about the reinterpretation problem. I believe the general solution is to adjust the tweak to:

Q = P + H(P || S || C) * G

Where S is a scheme ID (32 bytes/256 bits) that is unique to the scheme. The contract C is to be interpreted according to the scheme S.

In short, pay-to-contract must commit, not only to the contract itself, but to how the contract is to be interpreted.

@ZmnSCPxj
Copy link
Author

ZmnSCPxj commented Sep 4, 2018

Thread on bitcoin-dev: https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-September/016354.html

@ajtowns
Copy link

ajtowns commented Mar 29, 2019

I think it might make more sense to have the taproot-based p2c scheme be:

base pubkey: P
p2c: Q = P + H("rgb" || P || contract)*G
taproot scriptPubKey: R = Q + H(Q || "OP_RETURN")*G

So R = P + H("rgb"||P||contract)*G + H(Q||"OP_RETURN")*G

@ZmnSCPxj
Copy link
Author

ZmnSCPxj commented Apr 5, 2019

That certainly seems a plausible solution aj.

@ZmnSCPxj
Copy link
Author

A possibility when using Taproot is to merge the OP_RETURN and pay-to-contract commitments, by having one script branch in the Taprooted MAST be an OP_RETURN script with the contract in the OP_RETURN. "Real" script alternatives can be placed in other leaves of the MAST; we simply add an additional one to contain the RGB contract.

Still, we must be careful that a RGB contract serialization may be interpretable as the serialization of another pay-to-contract system using the same technique. So we should use tagged sha just as in bip-taproot.

@dr-orlovsky
Copy link
Contributor

dr-orlovsky commented Jun 15, 2019

Thread on bitcoin-dev: https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018-September/016354.html

I do like this proposal, it looks workable @ZmnSCPxj, have you had any further thoughts on the topic since then?

@ZmnSCPxj
Copy link
Author

Comment by ajtowns seems better. Alternatively, given current taproot proposal it would be possible to embed a hash of the RGB contract in a taproot branch that is OP_RETURN, with a RGB-specific tagged hash function as per bip-taproot. The bip-taprrot tagged hash is effectively what I propose, i.e. making a prefix that is specific to each use case, except the bip-taproot tagged hash fleshes it out and considers efficient implementations.

@dr-orlovsky
Copy link
Contributor

Alternatively, given current taproot proposal it would be possible to embed a hash of the RGB contract in a taproot branch that is OP_RETURN, with a RGB-specific tagged hash function as per bip-taproot.

Looks cool and sounds like a new commitment scheme for RGB. @giacomozucco, @afilini what do you think?

Comment by @ajtowns seems better.

Emm... I don't get why P + H("rgb" || P || contract)*G is anyhow better than P + H(P || contract)*G...

@inaltoasinistra
Copy link
Collaborator

Alternatively, given current taproot proposal it would be possible to embed a hash of the RGB contract in a taproot branch that is OP_RETURN, with a RGB-specific tagged hash function as per bip-taproot.

I see a problem here: double spend. It is possible to commit more then one RGB proofs into the taproot scripts tree. I don't see trivial solutions without affect privacy (i.e. include all the taproot scripts into the RGB proof)

@ZmnSCPxj
Copy link
Author

Emm... I don't get why P + H("rgb" || P || contract)*G is anyhow better than P + H(P || contract)*G...

The original problem pointed out that multiple pay-to-contract schemes may exist, not just RGB.

The extra H("rgb" | is intended to disambiguate, so that even if RGB contracts can written whose serialization is equivalent to the serialization of a contract in a different pay-to-contract scheme, if the other scheme uses a different prefix, it cannot be used to commit to multiple pay-to-contract schemes.

I see a problem here: double spend. It is possible to commit more then one RGB proofs into the taproot scripts tree.

You are correct and indeed the @ajtowns solution is strictly superior, as it avoids this issue.

@dr-orlovsky
Copy link
Contributor

Got it and agree. Since I'm doing implementation of the complete RGB spec from scratch (here https://github.com/dr-orlovsky/rgb-rust) I'll add this to the code and also will do a PR to the spec itself.

dr-orlovsky added a commit to rgb-archive/rust-rgb-2019 that referenced this issue Jun 18, 2019
dr-orlovsky added a commit to dr-orlovsky/spec that referenced this issue Jun 22, 2019
Adding "RGB" string to the public/private key tweaking procedure in pay-to-contract commitment scheme in order to prevent attacks around re-interpreting RGB contracts as some non-RGB contracts.
@dr-orlovsky
Copy link
Contributor

Seems like we need to add "RGB" prefix into the contract serialization as well (additionally to the actual PK tweak), in order to make the serialized contract code unambiguous. This prefix has to be included into the hash of the contract. I've already made this in code (see commit
rgb-archive/rust-rgb-2019@7a1e1ce above). I will add this to the spec as well.

dr-orlovsky added a commit to rgb-archive/rust-rgb-2019 that referenced this issue Jun 22, 2019
dr-orlovsky added a commit to dr-orlovsky/spec that referenced this issue Jun 22, 2019
Adds "RGB" prefix into the contract serialization as well (additionally to the actual PK tweak), in order to make the serialized contract code unambiguous.
@dr-orlovsky dr-orlovsky self-assigned this Jun 25, 2019
@dr-orlovsky dr-orlovsky added this to the v1.0.0 milestone Jun 25, 2019
@dr-orlovsky dr-orlovsky added this to Initial discussion / brainstorming in RGB Jul 18, 2019
@dr-orlovsky dr-orlovsky moved this from Initial discussion / brainstorming to PR under review in RGB Jul 25, 2019
dr-orlovsky added a commit to dr-orlovsky/spec that referenced this issue Jul 26, 2019
with more standard-compliance (alike in Taproot and other OP_RETURN schemes), enhancing security according to rgb-archive#61
@dr-orlovsky
Copy link
Contributor

Closing, discussion shall continue in the new PR #73

RGB automation moved this from PR under review to Done Jul 26, 2019
dr-orlovsky added a commit that referenced this issue Jul 26, 2019
Implementing issue #61: disambiguing P2C RGB tweak
dr-orlovsky added a commit to RGB-WG/rgb-node that referenced this issue May 6, 2020
dr-orlovsky added a commit to RGB-WG/rgb-node that referenced this issue May 6, 2020
@dr-orlovsky dr-orlovsky removed this from Done in RGB Apr 13, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

5 participants