-
Notifications
You must be signed in to change notification settings - Fork 350
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
Add signedTransaction
to SignerResult
for injected Signers in signAndSend
#5914
Conversation
signerPayloadJSON
to SignerResult
for injected Signers
signerPayloadJSON
to SignerResult
for injected SignerssignerPayloadJSON
to SignerResult
for injected Signers in signAndSend
Using this incredibly leaky interface as an output only makes the problem worse for other library authors. The solution should not be to make these interfaces leakier, but rather: to start using a non-leaky interface. For instance, a solution could be to add a new method like the This would also be a "non breaking change" that wallets could adhere to if they want to. However, with the approach that I'm suggesting we could provide a deadline for deprecating these leaky methods that only make sense to PJS. It is incredibly frustrating and unfair for other library authors to have to witness how PJS keeps making the situation worse. |
signerPayloadJSON
to SignerResult
for injected Signers in signAndSend
signedTransaction
to SignerResult
for injected Signers in signAndSend
@josepot I have changed the whole structure to outline the decisions we have discussed and agreed upon. |
Thank you very much, @TarikGul, for making this change more library-agnostic. However, there's an important point to note: the new API allows the signer/extension to modify the original call-data and/or the values of other signed extensions. I believe this is actually beneficial. To clarify, the DApp should merely suggest what it wants the user to sign, but the final decision lies with the user. Additionally, the extension must handle certain aspects no matter what, such as the nonce and the value of the new signed extension. From the perspective of PJS DApp developers, there used to be a "guarantee" that if the extension signed data different from what was instructed (altered call-data, tip, nonce, mortality, etc.), PJS would ensure the transaction wasn't broadcasted from their DApp. The extension could still broadcast the transaction on its own, so the old API wasn't inherently more secure. Some might argue that this PR alters the A practical approach could be to encode the extra-data from the We could consider releasing this change as a new major version of PJS, ensuring backward compatibility. This version could introduce a new API like |
You're very welcome, and thank you for the write up!
I like all the options outlined, but I would align with this current one the most. As mentioned all have their trade offs and while I do think decoupling the stricter ("old") signAndSend from the new unrestricted one would be nice, internally it would feel like a nightmare IMO. Being that our main goal for the future is to create a more standardized
Agreed, technically speaking yes some might argue that technically this is a "breaking change" since the signer can bypass the original payload being signed so it would be wise for us to do a major increase of the version. |
This is also obviously up for discussion, but I added validation to the
Edit: As mentioned and discussed validating the call data doesn't really improve security as the Signer can just broadcast the transaction without the need of the current API. I just added it in to start discussion with others: cc @IkerAlus |
* specific fields within the signed extrinsic against the original payload that was passed | ||
* to the signer. | ||
*/ | ||
#validateSignedTransaction = (signerPayload: SignerPayload, signedExt: Extrinsic): void => { |
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.
Note that this validation logic only covers the current case of Polkadot / Kusama relay chains. Other chains (and future relay chain upgrades) may have other signed extensions which would be skipped if we go for this function (for example, the asset ID for fee payment in the Asset Hubs).
Other potential approaches I see would be to:
- Do no validation at all before submission, and clearly document the behaviour of the
signedTransaction
mode, - Only validate the payload method, also documenting the implications, or
- do a byte-level comparison of the
included_in_extrinsic
kind of signed extensions given by the relevant chain, this is, the "extra-data" present in thesignedTransaction
.
My suggestion is to go for 1 or 2 as discussed beforehand.
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 agree with what @IkerAlus proposes, however as discussed, I'm more of a proponent of option (2): I would validate that payload.method
remains the same.
Even though adding this check does not inherently improves the security of the system as the signer can broadcast any transaction it wants, I believe it does help to take a more conservative approach until the ecosystem can move to a bigger, different structure.
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.
Sounds good, I'll just ensure that the method is the same and that's it!
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.
Amazing work
This pull request has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
Summary
Disclaimer: (NO BREAKING CHANGES) The following additions do not change any existing logic unless a wallet opts in to using
signedTransaction
. More information below.The following allows signers to modify fields in the payload passed into
signPayload
. This results in the return type ofSignerResult
to now be:signedTransaction
field. (Optional)If no
signedTransaction
is present inSignerResult
everything will continue as it always has. WhensignedTransaction
is present it will broadcast the transaction that is inputted.Additional Changes
mode
- I added the ability to decodemode
from the output of anExtrinsicBase
TODO:
Edit: I have edited out the last summary and iteration which has been agreed upon as a bad iteration. It used
SignerPayloadJSON
as the response in theSignerResult
which makes it hard for other library implementations. Moving forward there will be a standardization for the external facing API to make it better for wallets and lib maintainers.