Skip to content

Conversation

@achow101
Copy link
Contributor

Adds the document specifying the new PSET format that #900 implements.

Pulled out of #900

@apoelstra
Copy link
Member

Thanks!

I think we are going to change this to make it based off of PSBT2, which should simplify a lot of the transaction-hacking (and perhaps PSBT2 will have a "psbt ID" that we can make stay constant even after reblinding...maybe).

Useful to have this PR so that we can iterate on that independently of the code review.


The currently defined elements per-input proprietary types are as folows:

* Type: Issuance Value <tt>PSBT_ELEMENTS_IN_ISSUANCE_VALUE = 0x00</tt>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Am I wrong, but this maybe should be called PSET_ and not PSBT_ ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wrote in a comment to the previous PR (#900 (comment)) why I think that PSBT_ELEMENTS_... is better than PSET_... and it seems that my arguments were accepted


The Blinder can identify which outputs it should blind by checking the <tt>PSBT_ELEMENTS_OUT_BLINDER_INDEX</tt>.
Using that index, the Blinder should inspect the input at that same index.
If that input belongs to the Blinder, then the output is to be blinded by it.
Copy link

@tiero tiero Feb 2, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The language here is not entirely clear here IMHO. Unless I don't understand what it mean: the output is to be blinded by it

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An output O has an int I_i which is the index of an input. If a blinder owns the input at I_i, it must also blind the output O.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand that this makes it possible to define a specific blinder for each output. But why is this necessary? Is it a problem if the blinder has no input in the transaction?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, reading it I thought "it" was about the input, but it means the Blinder. So all good

@tiero
Copy link

tiero commented Feb 2, 2021

Let's say we want to support use-cases where multiple parties adds inputs and interactively sign (coinjoin, swaps) and is acceptable that the last party adding inputs/outputs (ie. SIGHASH_ALL) will cover the Blinder role knowing therefore the blinding keys of others (or asset/amount blinders):

We want to have a dedicated field for sharing these secrets in the PSET or this is out of scope and we will leave to be a construction coinjoin/swap protocols will build on top?

@apoelstra
Copy link
Member

The recipients can learn the blinding factors of their outputs in the usual way (using the rangeproof sidechannel), so PSET doesn't need to worry about this.

@tiero
Copy link

tiero commented Feb 2, 2021

The recipients can learn the blinding factors of their outputs in the usual way (using the rangeproof sidechannel), so PSET doesn't need to worry about this.

Pardon, what's a rangeproof "sidechannel" ?

Also here it's the blinder (which may or not may be one of the recipients) that needs to get blinders somehow from other parties.
I agree that this should be out of scope of PSET and will be done eventually by specific procotols (eg. for atomic swaps in tdex each party incude his own blinding keys/blinders so the the Responder could blind all the outputs one-shot)

@apoelstra
Copy link
Member

@tiero the "rangeproof sidechannel" is a mechanism in Elements that lets you encrypt data into a rangeproof with no additional space, such that the recepient can decrypt. This is currently used in Liquid so that senders can create blinded outputs and then communicate the blinding factors to the recipients.

@apoelstra
Copy link
Member

Doc needs update to be based on PSBT2 BIP-0370 https://github.com/achow101/bips/blob/psbt2/bip-0370.mediawiki ... should be fairly minor stuff but will let us clean up the "replace explicit outputs with blinded ones" workflow.g

@apoelstra
Copy link
Member

apoelstra commented Feb 22, 2021

Opened a PR to this branch over here achow101#2

Will start working on implementing this on rust-elements and elements-miniscript, and in parallel @achow101 will work on building something on top of #935, with the goal of getting some test vectors so that everyone else can start moving forward again (and we can do a libwally implementation). Sorry for the delays on this, I keep promising to go over this and coordinate things and then getting pulled into other stuff.

@achow101 achow101 force-pushed the pset-spec branch 2 times, most recently from 3b0435a to 3c3487c Compare February 24, 2021 22:22
@achow101
Copy link
Contributor Author

achow101 commented Feb 24, 2021

I have updated this to use the formatting used in BIPs 174 and 370. Additionally this has been updated to be dependent on BIP 370 and PSET will only work with PSBTv2.

One notable change is that PSBT_ELEMENTS_OUT_VALUE has been dropped as PSBTv2 has a PSBT_OUT_AMOUNT that is the same thing.

@achow101 achow101 force-pushed the pset-spec branch 2 times, most recently from 2445805 to 81beac4 Compare February 24, 2021 22:35
Copy link
Contributor

@sanket1729 sanket1729 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the elements Taproot sighash, we also a global blockchain_genesis_hash in order to avoid reuse of signatures across blockchains. I think we should add a pset global proprietary field for it as it would needed to construct the Sighash Message

| 2
|-
| Peg-in Witness
| <tt>PSBT_ELEMENTS_IN_PEG_IN_WITNESS = 0x09</tt>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The name makes it seem that the type of the value should Witness, but it is shown as a script. How does this work for segwit transactions?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this question does not make sense, and pegin transactions input only have witness in ScriptSig.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

! Versions Allowing Inclusion
|-
| Value Commitment
| <tt>PSBT_ELEMENTS_OUT_VALUE_COMMITMENT = 0x01</tt>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Proprietary fields for Input, Global start from 0x00. Is there any special reason why this starts from 0x01?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Originally, the output's value was in field 0x00. However with the move to PSBTv2, this was no longer necessary and I removed that field. I just didn't change the rest of the field numbers. I don't feel strongly about keeping these, but it does make implementation easier to not change them.

@sanket1729
Copy link
Contributor

sanket1729 commented Apr 16, 2021

@achow101 How is the serialization for range proof and surjection proofs witness_utxo supposed to be done? In the current elements, there are not serialized as a part of TxOut, but as additional witness data at the end of the transaction.

Should we add separate fields for those? I only see proprietary fields for issuances/pegins in inputs. In a common workflow, the user would need to rewind the rangeproof in order to get the value/asset.

@sanket1729
Copy link
Contributor

Or is the type of witness_utxo a Psbt/Pset output and not an elements TxOut?

@achow101
Copy link
Contributor Author

achow101 commented Apr 19, 2021

@achow101 How is the serialization for range proof and surjection proofs witness_utxo supposed to be done? In the current elements, there are not serialized as a part of TxOut, but as additional witness data at the end of the transaction.

Should we add separate fields for those? I only see proprietary fields for issuances/pegins in inputs. In a common workflow, the user would need to rewind the rangeproof in order to get the value/asset.

Currently neither the range proof nor the surjection proof is provided in the input UTXOs. I don't see why the surjection proof would be required, but for the rangeproof, the only reason to have it is to be able to get the encrypted blinding factor from it. However since the range proof is really large, I am hesitant to put it there in its entirety. Instead, we could have a field for the encrypted blinding factor. The ecdh pubkey is already stored in CTxOut.nNonce. So updaters can extract the encrypted blinding factor from the rangeproof and put that in the PSET.

@tiero
Copy link

tiero commented Apr 19, 2021

However since the range proof is really large, I am hesitant to put it there in its entirety.

Owning the blinding private key and a a call to any explorer/node, anyone can get the proofs and unblind it. Especially if wallets implements slip77, just the script is enough to derive the blinding from the seed/master blind key

@achow101
Copy link
Contributor Author

achow101 commented Apr 19, 2021

a call to any explorer/node

I think the scenario is for offline blinders which don't have access to any nodes. After all, the point of a PSET is to have everything for signing and blinding, no need to call a node.

@tiero
Copy link

tiero commented Apr 19, 2021

a call to any explorer/node

I think the scenario is for offline blinders which don't have access to any nodes. After all, the point of a PSET is to have everything for signing and blinding, no need to call a node.

That's true, I am more in favor to put asset/value blinders then. This could unlock indeed more advanced cooperative multi-party blinding/unblinding

@achow101
Copy link
Contributor Author

That's true, I am more in favor to put asset/value blinders then. This could unlock indeed more advanced cooperative multi-party blinding/unblinding

The purpose of this rework of PSET is to avoid having to put asset and value blinders into the PSET. The blinding factors are supposed to be secret, while PSETs can be passed around to untrusted entities. Having the blinding factors in the PSET destroys the privacy preserving aspects of elements, so I don't think it makes a lot of sense to have them in. What workflows does having the blinding factors in the PSET enable?

@tiero
Copy link

tiero commented Apr 19, 2021

@achow101 Sorry, I meant encrypted of course, ref: your comment before

Instead, we could have a field for the encrypted blinding factor

The main advantage would be cooperative blinding for swaps/coin join (ie. I don't trust the input you giving to contain what you claim), but yeah there could be other means to do it, on top of PSET without including in it

@sanket1729
Copy link
Contributor

sanket1729 commented Apr 19, 2021

@achow101, This would be an optional field, and only the users who really care about applications that require rewinding the proofs would use it.

Here is one simple scenario where this might be useful. The user has an SW watch-only software that wants to confirm a receiving confidential transaction. The SW provides the 1) Rangeproof, 2) the TxOut.nNonce from the receiving transaction and 3) the receiver address(or the ecdh_pubkey) to the HW wallet that does the unblinding tells the SW about the asset and value it is receiving.
In my opinion, we should add two per input optional fields for 1) rangeproof and 2) the receiver pubkey in the CT address. Since txout.nNonce already contains the ephermal_pk, the unblinder can use these three together to unblind the txout.

  1. Since the field is completely optional, applications that don't care about this don't have to use it. It is already possible to inflate psbts/psets by filling in unnecessary optional things in global maps/key maps etc. So, adding this is not creating any new DoS vector that does not already exist
  2. We already have range proofs for outputs, issuance/re-issuance inputs.

w.r.t to surjection proofs, you are right that these are not needed.

So updaters can extract the encrypted blinding factor from the rangeproof and put that in the PSET.

The current libsecp_zkp API does not provide any such support for extracting encrypted blinding factors from range proofs. It only offers a rewind method that needs the secret key after the ecdh computation.

@apoelstra
Copy link
Member

I think we should add the extra field. As Sanket observes,

  1. Encoding the value/blinder directly would be a serious privacy leak, but we don't have any standard way to encrypt this data to the Blinder, other than the entire rangeproof.
  2. We already encode entire rangeproofs for the outputs of the transaction; so encoding them for the inputs as well isn't that big a loss.

Both of these problems are "temporary" in that they'll be eliminated by Bulletproofs.

@achow101
Copy link
Contributor Author

I've added an additional field where the UTXO's rangeproof can be specified.

@sanket1729
Copy link
Contributor

sanket1729 commented Apr 20, 2021

Thanks, @achow101. For the full utility of the use-case that I described above, we need three things.

  1. Rangeproof: available by PSBT_ELEMENTS_IN_UTXO_RANGEPROOF.
  2. Sender Ecdh pubkey: available inside PSBT_ELEMENTS_IN_UTXO in txout.nNonce
  3. (un)Blinding pk: Typically stored in the CT address that the receiver uses.

we also need the public key from the receiver address. Is it also possible to add optional pubkey PSBT_ELEMENTS_IN_UTXO_BLINDING_PUBKEY ?

@achow101
Copy link
Contributor Author

  1. (un)Blinding pk: Typically stored in the CT address that the receiver uses.

we also need the public key from the receiver address. Is it also possible to add optional pubkey PSBT_ELEMENTS_IN_UTXO_BLINDING_PUBKEY ?

I'm not sure that updaters will necessarily know this. The blinding pubkey is not stored publicly anywhere and I'm not sure that updaters would necessarily be able to derive the blinding pubkey for an output. AFAIU, blinders should know how their blinding pubkeys are derived so a blinder can try to unwind every rangeproof. The ones where the unwinding is successful are the inputs that the blinder owns.

@apoelstra
Copy link
Member

@sanket1729 @achow101 think we should merge this since both PSET implementations are nearing completion?

@achow101
Copy link
Contributor Author

achow101 commented May 5, 2021

Fine by me

Copy link
Contributor

@sanket1729 sanket1729 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACk 8e19dfa

@stevenroose stevenroose merged commit 4db1799 into ElementsProject:master May 6, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants