-
Notifications
You must be signed in to change notification settings - Fork 5k
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
EIP-712: Sign typed data #4803
EIP-712: Sign typed data #4803
Conversation
@@ -221,7 +238,7 @@ module.exports = class TypedMessageManager extends EventEmitter { | |||
msg.status = status | |||
this._updateMsg(msg) | |||
this.emit(`${msgId}:${status}`, msg) | |||
if (status === 'rejected' || status === 'signed') { | |||
if (status === 'rejected' || status === 'signed' || status === 'errored') { |
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.
unclear when status gets set to 'errored' due to errors thrown in validateParams
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'm not sure I follow; what's unclear? The conditions that cause a message to be considered invalid? Error descriptions should be fine; are you suggesting to improve the documentation for the validateParams
method to explicitly state what conditions are validated?
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 sorry I was being dense, I didn't see the call to set the message status in metamask-controller
Does this PR enforce the validity of the |
@danfinlay The spec doesn't mention a domain.url field. See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md#definition-of-domainseparator. |
Thanks for the links (was posting from phone earlier, doing bad research). I don't think we're enforcing that chainId parameter yet, would be a good improvement to make. |
Thanks @danfinlay and @leroldary, great catch with the |
Hey, where can I find the tests associated with this functionality? Do they also include the smart contract verification of typed signatures? |
@MrChico Check out Example.js and Example.sol in the EIP712 repo |
@ipatka is correct, the EIP itself has example resources, and our implementation based on these resources lives in eth-sig-util. Also note that the EIP's example code intentionally (and temporarily) omitted array encoding, so we submitted an upstream PR with this functionality at ethereum/EIPs#1242 @MrChico. |
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.
Ideally we render the domain
info as more of a table, but that's no blocker. Let's get this out there!
Oh, also: Needs a changelog entry!!!
test failing but we want to merge! |
Is it possible to detect which Metamask version is installed and if this feature is available? |
@ipatka this PR hasn't been merged into the application just yet |
@whymarrh right, is there a way to detect the version once it is merged? |
Also, will this break apps that use the previous implementation of EIP712 or will it support both? |
Hi @ipatka. We plan to add a deprecation warning to the current implementation of @danfinlay @cjeria CI all green again, but I think we should only land this after #4905 lands and the next release is cut. As soon as that's done, this can hit |
This comment has been minimized.
This comment has been minimized.
Hi @sullof: thanks for reaching out. We plan to do exactly what you suggested: we will release support for the new method under the correct RPC method name, but we will also concurrently support the old method under a modified RPC method name. This means that any app that was using the old version of the method will continue to work as long as they update to use the deprecated method name. This is what @danfinlay was referring to when he mentioned breaking APIs responsibly. We also plan to release a blog post that details this information, including exact release dates, in the coming weeks. Apologies for the lack of clarity around this rollout process. Please let us know if you have any additional questions or concerns. |
@bitpshr That is very helpful. Thanks so much. |
This pull request has been rebased and updated to concurrently support both the old and new versions of EIP-712. To provide dapps with the smoothest transition possible, each version of this proposal is and will be uniquely name-spaced. For example, the original version will be available at Note: For now, the canonical RPC method |
assert.doesNotThrow(() => { | ||
sigUtil.typedSignatureHash(params.data) | ||
}, 'Expected EIP712 typed data') | ||
switch (params.version) { |
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.
For now, since there are only two versions of the proposal, we include both validation logic paths in the same TypedMessageManager class. If there ends up being even more iterations of the proposal with different validation schemes (unlikely, but possible), we can break this class down into a base Manager class and multiple implementations that extend it with a custom validateParams
method.
return this.getState() | ||
}) | ||
const version = msgParams.version | ||
try { |
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.
Previously, we called down into the KeyringController, which in turn called into a specific keyring, which then called called signTypedData
. This dependency depth made changes very difficult and it seemed like potentially-unnecessary indirection. To get around this, the MetaMaskController just does the signing directly without traversing down to a specific keyring. This also lends itself well to a future of signature-specific controllers at the extension level.
app/scripts/metamask-controller.js
Outdated
@@ -1253,6 +1263,9 @@ module.exports = class MetamaskController extends EventEmitter { | |||
engine.push(createLoggerMiddleware({ origin })) | |||
engine.push(filterMiddleware) | |||
engine.push(this.preferencesController.requestWatchAsset.bind(this.preferencesController)) | |||
engine.push(this.createTypedDataMiddleware('eth_signTypedData', 'V1').bind(this)) | |||
engine.push(this.createTypedDataMiddleware('eth_signTypedData_v1', 'V1').bind(this)) | |||
engine.push(this.createTypedDataMiddleware('eth_signTypedData_v2', 'V2').bind(this)) |
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.
Instead of using processTypedMessage
when initializing the web3-provider-engine, we use custom middleware to intercept eth_signTypedData
methods. This allows us to have fine-grained control over custom and non-custom RPC methods without touching the provider engine itself.
Note that for now, eth_signTypedData
is still pointing to V1
of the EIP-712 proposal.
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 told Pete Kim of Cipher that his implementation could be v2, and so the final one (this one) would be v3
. Mind if we change to that? I think that will be a nice gesture to them, and leaves us open to backwards-support any apps using their version.
app/scripts/metamask-controller.js
Outdated
@@ -1253,6 +1263,9 @@ module.exports = class MetamaskController extends EventEmitter { | |||
engine.push(createLoggerMiddleware({ origin })) | |||
engine.push(filterMiddleware) | |||
engine.push(this.preferencesController.requestWatchAsset.bind(this.preferencesController)) | |||
engine.push(this.createTypedDataMiddleware('eth_signTypedData', 'V1').bind(this)) | |||
engine.push(this.createTypedDataMiddleware('eth_signTypedData_v1', 'V1').bind(this)) | |||
engine.push(this.createTypedDataMiddleware('eth_signTypedData_v2', 'V2').bind(this)) |
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 told Pete Kim of Cipher that his implementation could be v2, and so the final one (this one) would be v3
. Mind if we change to that? I think that will be a nice gesture to them, and leaves us open to backwards-support any apps using their version.
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 looks great, and non breaking! Can't wait to get this in the hands of developers!
What's the status of this feature with the recent rollbacks? Release v4.14.0 does not seem to support it. We're currently using release v4.10.0 with success but would like to get our application in the hands others. It's hard to get people to manually setup an older version of MetaMask for a variety of reasons. Thanks. |
^ Resolved. Support added back in v4.14.0 however the parameters where swapped. It is now [signer, typedData]. |
This pull request implements necessary changes to fully support the current version of EIP-712 in both the old and new user interfaces. Note that most of the heavy-lifting of this implementation is handled by the updated
signTypedData
function in eth-sig-util.Note: For now, we're displaying domain data as an inspectable object just like actual message data. Eventually, we should probably render this domain data differently (notice the mocked up "Domain / URL / Contract" section here, cc @cjeria.)
Resolves #4752
References ethereum/EIPs/pull/1222
Todo:
signTypedData
andrecoverTypedSignature
eth-sig-util
ineth-simple-keyring
eth-sig-util
ineth-hd-keyring
eth-keyring-controller
eth-keyring-controller
in the extensionsignTypedData
method.