-
Notifications
You must be signed in to change notification settings - Fork 387
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Redesign PSET #900
Redesign PSET #900
Conversation
doc/pset.mediawiki
Outdated
** Key: A 32 Scalar Offset computed by a blinder. | ||
*** <tt>{0x00}|{offset}</tt> | ||
** Value: None. The value must have a length of zero. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Should be PSET_GLOBAL_SCALAR
- 32 byte
- The scalar value should be stored in the value (not the key) since that makes the key unique and prevents duplicates even in general PSBT utilities that pass this field through. It also then matches every other Elements type in the doc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There can be multiple scalars. Putting it in the value then requires a unique key per scalar.
The original suggestion was to attach a scalar to an output, however they aren't really related to a particular output, so I opted to go with a global field.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah. This wasn't clear from the docs. given multiple scalars in a psbt, how do i know in which context to use one versus another? It seems like more data than just the scalar value will be needed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The scalars are only used by the last blinder and they are used all together at that time. They're just used in the last blinding step to make sure that everything balances.
doc/pset.mediawiki
Outdated
@@ -21,6 +20,9 @@ signatures for an input while the input does not have a complete set of signatur | |||
The signer can be offline as all necessary information will be provided in the | |||
transaction. | |||
|
|||
This is a modification of BIP 174 for the Elements sidechain. It includes changes necessary | |||
for Confidential Transactions, Confidential Assets, and Peg-in transactions. | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please consider making this doc a diff/addendum to the BIP rather than repeating the PSBT fields etc. Its hard to read, easy to miss the Elements specific stuff and it will only get out of date w.r.t. BIP 174 as its updated.
If you cant do this at least highlight the Elements changes in the markup somehow.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Commit 0b3b9ed is just the PSET changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The people who will be implementing support for PSET in their code have to use the full document, they cannot use commit as the reference. I concur with @jgriffiths that the doc should be an addendum rather than edit. I think that the described problems (need to read diff PSET/PSBT instead of the document, need to sync with PSBT as it is updated) are significant. It is the additions to the standard that are proprietary, not the standard itself. Therefore only the additions should be described in the spec.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
*proprietary in a sense that they use the PSBT_PROPRIETARY
type designed for proprietary extensions, not that the changes are somehow not open.
doc/pset.mediawiki
Outdated
The amount is added to the PSET input as <tt>PSET_IN_ISSUANCE_VALUE</tt>. | ||
|
||
The Creator decides whether and which inputs are Peg-in inputs. | ||
Peg-in inputs must have the Peg-in flag set in their outpoints. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issuance and pegin are mutually exclusive, no? if so this should be documented above with their input fields.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am under the impression that they are not mutually exclusive. I don't really see why they would be.
doc/pset.mediawiki
Outdated
The blinder will then subtract the sum of their inputs' blinding factors from the sum of their output's blinding factors. | ||
The result must be added as a <tt>PSET_GLOBAL_SCALAR</tt> field. | ||
|
||
For the Blinder who blinds the last output to be blinded, it will subtract all of the scalar offsets from the value blinding factor for the last output. |
This comment was marked as outdated.
This comment was marked as outdated.
Sorry, something went wrong.
doc/pset.mediawiki
Outdated
|
||
For the Blinder who blinds the last output to be blinded, it will subtract all of the scalar offsets from the value blinding factor for the last output. | ||
The result will be the amount blinding factor for that last output. The creation of the asset commitment, proofs, and other fields proceeds as usual. | ||
Once all outputs are blinded, all <tt>PSET_GLOBAL_SCALAR</tt> fields must be removed from the PSET. |
This comment was marked as outdated.
This comment was marked as outdated.
Sorry, something went wrong.
src/psbt.cpp
Outdated
if (!input.IsSane()) return false; | ||
// Check issuance is empty in CTxOut but set in input |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment is confusing. The "Check issuance is empty in CTxOut" happens later, but it is referred to as it it happens just here. I think better wording would be along the lines of "Check that issuance is empty in the input, because later we check that issuance is empty in CTxOut"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reworded
src/psbt.cpp
Outdated
if (!tx->vin[i].assetIssuance.nAmount.IsNull()) return false; | ||
if (!input.issuance_value && input.issuance_value_commitment.IsNull()) return false; | ||
} | ||
// Check whether any input is blinded |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment is at the end of the loop. Usually the comment describes the code that is below (or left of) the comment. Does this comment refer to the code that is supposed to be here, but removed ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed
src/psbt.cpp
Outdated
|
||
bool PSBTOutput::IsBlinded() const | ||
{ | ||
return blinding_pubkey.IsValid(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nor IsPartiallyBlinded
neither IsFullyBlinded
check blinding_pubkey.IsValid()
. That means that there is a logical contradiction that an output can be 'FullyBlinded', but not 'Blinded'. This can create confusion that can result in mistakes. Maybe better wording can help, like 'Blindable' instead of 'Blinded' ? Or IsPartiallyBlinded
/IsFullyBlinded
should imply IsBlinded
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Enforced it.
src/psbt.cpp
Outdated
@@ -329,6 +402,7 @@ bool FinalizeAndExtractPSBT(PartiallySignedTransaction& psbtx, CMutableTransacti | |||
result.witness.vtxinwit[i].scriptWitness = psbtx.inputs[i].final_script_witness; | |||
PSBTInput& input = psbtx.inputs[i]; | |||
|
|||
/* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Commented-out (and not removed) code without any further comment with justification of not removing it can be confusing and distracting. Is this commented out just temporary ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it is just temporary. The comment is to just make the code compile so that the action that this code does can be reimplemented later in this PR.
src/psbt.h
Outdated
@@ -174,49 +159,83 @@ struct PSBTInput | |||
SerializeToVector(s, final_script_witness.stack); | |||
} | |||
|
|||
// Issuance value | |||
// We shouldn't have both the value and value commitment, but maybe we do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comments should make the code more clear, rather than introduce doubt.
"but maybe we do" is not connected to the action in the code, and should either be dropped, or expanded, "but maybe we do, and in this case we ignore the value"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clarified
src/psbt.h
Outdated
SerializeToVector(s, asset_commitment); | ||
} | ||
// Asset | ||
// We shouldn't have both asset and asset commitment, but if we do, wrte only the asset commitment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mistype: "wrte" instead of "write"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
doc/pset.mediawiki
Outdated
* Type: Value Commitment <tt>PSET_OUT_VALUE_COMMITMENT = 0x01</tt> | ||
** Key: None. The key must only contain the 1 byte type. | ||
*** <tt>{0x01}</tt> | ||
** Value: The 33 byte Value Commitment for this output. Adding this field requires the removal of <tt>PSET_OUT_VALUE</tt>. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding PSET_OUT_VALUE requires remove of commitment, too. I think better say that the fields are mutually exclusive, as said for issuance value/commitment fields. (the same can be said for asset and asset commitment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
doc/pset.mediawiki
Outdated
will still need to handle events where keys are duplicated when combining transactions with duplicated fields. In this event, with the exception of duplicate output commitments and proofs, the software may choose | ||
whichever value it wishes.<ref>'''Why can the values be arbitrarily chosen?''' When there are duplicated keys, the values that can be chosen will either be | ||
valid or invalid. If the values are invalid, a signer would simply produce an invalid signature and the final transaction itself would be invalid. If the | ||
values are valid, then it does not matter which is chosen as either way the transaction is still valid.</ref>. For <tt>PSBT_OUT_VALUE_COMMITMENT</tt>, <tt>PSBT_OUT_ASSET_COMMITMENT</tt>, <tt>PSBT_OUT_VALUE_RANGEPROOF</tt>, <tt>PSBT_OUT_ASSET_SURJ_PROOF</tt>, and <tt>PSBT_OUT_ECDH_PUBKEY</tt>, the PSET should be considered invalid if these are duplicated. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think what is meant here is that 'the combined PSET should be considered invalid'. Wouldn't it be more clear to say that PSETs cannot be combined if these fields are present in both instances ?
Also I believe that if values of these fields are equal for the outputs of two PSETs, they can be combined. For example, two PSETs that was modified from one common ancestor could have these fields in outputs that are equal.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've tried to clarify and generalize this.
doc/pset.mediawiki
Outdated
For any output which is going to be blinded, the Creator must add the blinding pubkey in the <tt>PSET_OUT_BLINDING_PUBKEY</tt> field. | ||
|
||
If any input is blinded, at least one of the outputs must also be blinded, i.e. it must have a <tt>PSET_OUT_BLINDING_PUBKEY</tt>. | ||
Such an output can be a 0 value OP_RETURN output. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Creator can be unaware that Updater will add a blinded input afterwards. Then the updater have to enforce this rule, too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That would violate the constraint that the unsigned tx cannot change. Maybe we should assume (or stipulate) that creators know which/whether inputs are blinded?
doc/pset.mediawiki
Outdated
|
||
The Creator decides whether and which inputs are issuance inputs. | ||
For those inputs, the issuance data must be added to the input in the global unsigned transaction, except for the issuance amount. | ||
Such inputs must also have the issuance flag set in the outpoint. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would add "in the outpoint of the prevout". Just "outpoint" can be mistakenly read as "output" and confuse the reader (I myself misread and was confused, like "how an output can be related here at all ?")
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
doc/pset.mediawiki
Outdated
** Key: None. The key must only contain the 1 byte type. | ||
*** <tt>{0x09}</tt> | ||
** Value: The Peg-in witness for the Peg-in Transaction. | ||
*** <tt>{script}</tt> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There should be PSET_IN_ASSET_COMMITMENT
to supply asset commitment of the prevout, so Creator/Updater can provide blinding information for the inputs when they will not be the Blinder
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(this info is supplied in auxiliary_generators
argument to BlindTransaction()
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be in the UTXO already.
doc/pset.mediawiki
Outdated
Once all outputs are blinded, all <tt>PSET_GLOBAL_SCALAR</tt> fields must be removed from the PSET. | ||
|
||
A single entity is likely to be a Creator, Updater, and Blinder. | ||
In that case, the PSET should never be output with <tt>PSET_IN_ISSUANCE_VALUE</tt>, <tt>PSET_OUT_VALUE</tt>, or <tt>PSET_OUT_ASSET</tt>. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Creator must set output values to 0 and assets to NULL. So for unblinded outputs, PSET_OUT_VALUE
and PSET_OUT_ASSET
need to remain after blinding. Or there should be a rule that unblinded output values should have their value/asset specified in embedded transaction, and these PSET_*
fields used only for blindable outputs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I clarified this to say that unblinded outputs should have these fields.
doc/pset.mediawiki
Outdated
The resulting PSBT must contain all of the key-value pairs from each of the PSBTs. | ||
The Combiner must remove any duplicate key-value pairs, in accordance with the specification. It can pick arbitrarily when conflicts occur. | ||
For all PSET output fields, the combiner must fail to combine if these fields are not identical. | ||
If the PSETs to be combined have incomplete blinded outputs but the combined result would only complete blinded outputs, then the Combiner must fail unless it is also a Blinder and can reblind its outputs. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This wording is unclear. Does it says that if the two outputs that are combined are both incomplete-blinded, but the resulting output will have all the fields to consider it complete, there is a big chance that these fields are incompatible because different randomness was used to produce them ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes.
doc/pset.mediawiki
Outdated
** Value: The rangeproof for the value of this output. | ||
*** <tt>{rangeproof}</tt> | ||
|
||
* Type: Asset Surjection Proof <tt>PSET_OUT_ASSET_SURJ_PROOF = 0x05</tt> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if RANGEPROOF
is spelled without underscore, it would be more consistent to spell SURJPROOF
or SURJECTIONPROOF
also without underscore. Or use RANGE_PROOF
instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I personally prefer PSET_OUT_VALUE_RANGE_PROOF
and PSET_OUT_ASSET_SURJECTION_PROOF
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Although in the Elements code they are referred to as rangeproof
and surjectionproof
, without underscores.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also 'value' and 'asset' prefixes can be implicit in these names
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the various papers on CT and CA, rangeproof
as one word is the typical usage while surjection proof
is 2 words. So following that convention, it would be RANGEPROOF
and SURJECTION_PROOF
.
I've updated pset.mediawiki to just be PSET and not contain PSBT. |
I'd like to note that I find PSET prefix confusing if used in implementation (not so much in the specification) that will most likely be based on PSBT. Unless BIP174 is used in prefix for the names rather than PSBT, I would say that it is better to use |
Especially when used along with |
Implementors are more likely to look into reference code than the papers, and more likely to get the conventions from there. Elements code mainly uses no-underscore convention.
|
walletfillpsbtdata These are all done by walletprocesspsbt
This test is for a condition that no longer matters. Prior to CA, there was only the single value blinder for a transaction that sent unconf to conf. This would necessitate setting that single blinding factor to 0, which would make the single output not actually blinded. But with CA, because each output has an additional blinding factor for the asset, this issue no longer exists.
Helper function for getting a CTxOut for a PSBTOutput
It doesn't work, disable for now.
ack f8553c5 |
CI failure due to #1012 |
…suances.py Should describe the outputs as an array rather than as an object. (The old behavior has long been deprecated but was eliminated entirely in ElementsProject#900.)
…ash_pegins_issuances.py 1c883db test: update `createrawtransaction` call in feature_taphash_pegins_issuances.py (Andrew Poelstra) Pull request description: Should describe the outputs as an array rather than as an object. (The old behavior has long been deprecated but was eliminated entirely in #900.) Fixes functional tests which were broken in master by simultaneous merge of #1002 and #900. ACKs for top commit: stevenroose: utACK 1c883db Tree-SHA512: f7963c34e7006a25ac5515e30966ef46777fa22d6125d219345731aef603e5f3179fc316134d59694af8e753f7cb48c825ad3434f2bceda0a10b8d5a52c32cd3
This fixes an undetected merge conflict between ElementsProject#1014 and ElementsProject#900.
…ew RPC changes c0936ba test: fix surjectionproof overflow functional test for new RPC changes (Andrew Poelstra) Pull request description: This fixes an undetected merge conflict between #1014 and #900. ACKs for top commit: gwillen: utACK c0936ba psgreco: UTACK c0936ba Tree-SHA512: a39d98db91d92f7e0e739e06d7a1bb13814d2bc7751cb6105a759af04ed0d61d206d1650f5e4e087feaeafcf1c482587b05b66d9cc497bc594a45df6bf23c07a
I hacked up rpc_fundrawtransaction.py a little bit because our `get_address` method here depends on nobody having called `createwallet` on a particular node ... the "correct" fix for this would be to redo the Elements changes to this functional test for the 0.20+ createwallet changes, but because there will be big future changes to this test (in Elements #900 (PSET)) I did the quick/hacky thing, and will defer cleanups to a separate post-rebase PR.
Surprisingly easy to do. Almost all of the diff resolution was mechanically * replacing boost::variant with std::variant * replacing Optional with std::optional * then replacing `nullopt` with `std::nullopt` * updating the RPC functions for the new RPCArg::Default type * update the tests/ directory to make new (since 22) tests use arrays for createrawtransaction outputs * other ad-hoc changes to function parameters etc (not too many of these) I had to "really" change the code in PrecomputePSBTData, which was introduced in 22.0 and affected by PSET, but this function was like 8 lines long so it was easy. Reviewing the diff may be a bit difficult because of the mix of mechanical changes and ad-hoc things. Probably the most straightforward thing to do is to redo the merge, `sed -i` to fix the boost::variant and Optional stuff, then diff the remaining conflicts against this commit. TODO: grep for `blindpsbt` and you will see that this RPC is still referenced in documentation and help text even though it was deleted. Need to fix this in 0.21 in a separate PR.
The original PSET had some issues with leaking private information and there were issues with the design of the various roles. This PR replaces it with a new PSET design that should be able to provide all of the things that people expect PSETs to do while preserving privacy.
Additionally, an actual specification for this new design has been written up. It describes all of the new fields, their serialization, and how roles should handle the PSET data.
This is still a work in progress as not everything with the blinder role has been worked out yet.