-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
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
Personal API methods #98
Comments
Personal signing is fully supported in ethers.js, but you do not need a provider, it works client-side, I haven't seen that EIP, I will check it out. It is certainly something I have wanted. :) |
@ricmoo awesome. I knew you'd have it figured out :) thanks. it makes sense that its client-side, but in the case of MetaMask which holds the private key, it requires the user to "sign" with a button click, I assume the MetaMask wallet provides a provider over some transport (postMessage?) at which point we get the signed data back. My purposes is of course to use MetaMask, so I'll read the ethers-web3.js in the iOS client and hopefully it has the personal method there too. I'm excited for when this is pushed to ethers.js repo. |
does this look correct? // if web3.currentProvider is ethers.. then..
const ethersBridge = web3.currentProvider
ethersBridge.sendAsync({ params: [utils.hexlify(utils.toUtf8Bytes('mymessage')), '0xADDY'], callback} looks like from source, I need to hexlify the message string by hand like so. it would be nice eventually in the bridge to have functions/methods that look more like: |
The Web3BridgeProvider may not work out-of-the box, I'll be adding it (hopefully) soon, in a way that will work without any mangling. But the idea is to use it like a Web3 provider, which allows existing Web3 apps to work instantly, by swapping out the provider with an ethers provider:
By using the official Web3 object, it remains bug-for-bug compatible, as well as some of the weirder choices Web3 made. :) That said, I'm hoping more people will instead use the These are mostly done, but require testing. This week I'm focusing more on the Firefly firmware, which should hopefully be done soon, for the v0 version, at least. |
@ricmoo personally I don't want to have any of the web3 or ethereumjs dependencies anywhere in my project. Dapps should build with the lib they choose, and most likely that will be the case. Ie. I don't see a lot of benefit to use the ethers Web3BridgeProvider for a 100% compat API which still requires the web3 dependency, the only advantage would be some kind of migration I suppose, but still I'm not sure that'd speed up much migration. web3 and ethereumjs pkgs are quite a mess, and dont follow conventions at times, and further their filesize is quite large (>500kb minified and 1.8mb unminified). I plan to use Ethers directly and just use the small web3.currentProvider surface api with ethers directly. Looking at the source of ethers-web3.js, I believe |
I think the right API is similar to as shown here: https://github.com/MetaMask/faq/blob/master/detecting_metamask.md#using-a-convenience-library for example.. (without any need for a web3 dependency aside from the injected .currentProvider): var ethers = require('ethers');
var provider = new ethers.providers.Web3BridgeProvider(web3.currentProvider);
provider.getBalance(address).then(function(balance) { ... });
provider.personalSign(msg, address).then(...); // which doesn't exist yet in ethers provider
provider.signTypedData(msgParams, address).then(...); // new as per EIP above but supported by MM also FYI, see https://github.com/danfinlay/js-eth-personal-sign-examples relating to examples of ethSign, personalSign and ethSignTypedData written by a MetaMask dev |
Right. What you want is what will be the I expect the The Web3Provider will also have a I'm thinking of doing the conversion internally of signed messages too, so if you call parity or get you get the same result (a signature ending in 0x1b or 0x1c)... I don't want things to change in the front-end because the backend changes. Feedback? |
@ricmoo that sounds great. Nice and lean, and makes ethers.js quickly useable with the injected web3.currentProvider, as a simple integration. Question, web3.currentProvider offers send() and sendAsync() - which is obvious as synchronous (wait for response) and asynchronous (pass a callback or promise). I noticed the send() method in ethers returns a promise, so I believe you'll want it to call web3.currentProvider.sendAsync(). I am not sure when you'd use a sync operation ever ..? I do like the convenience of the signer too, that will be helpful but I don't believe the currentProvider does anything with signing, it just relays the rpc request/response straight up, but you probably know that so maybe I'm not understanding the difference other than you mean, the methods on the Web3Provider such as I was not aware that parity or geth generate different signatures, is this related to the -27 last byte thing? which I've yet to fully dive in to understand why this has occurred/remains. I do agree all request/response from an app perspective, regardless of backend should be consistent. However, hopefully this doesnt have to be too hackey either or it'll make a mess of your lib code. |
Correct, my send is async (as ethers does not support sync in any way and never will), so I will override the I don't want to conflate what a Provider vs a Signer is. A Signer encapsulates private methods (like sign, sendTransaction, and signMessage) and can be passed into other libraries (such as ethers-meow, ethers-ens and will have the necessary properties to sign. A Provider only exposes public methods (like getLogs, getTransaction). The Signer returned by the Web3Provider will simple proxy the commands through to the RPC. But keeps the two concepts completely separated, so that anything that takes in a provider will continue to work with any other provider and anything that takes in a Signer will continue to work with any other Signer (e.g. in the future, there will likely be a LedgerSigner and a FireflySigner). The only reason is for encapsulation. The Yes, it's the -27 thing... The best way I can describe Parity is that it does what the right thing is, that should have been the standard, instead of the standard thing. Somewhat annoying, but maybe not wrong? |
+1 for encapsulation & separation of concerns, that makes lots of sense. Signer is for methods using a wallet's private key, and Provider is for the network - do I have that right? I'm really enjoying working with ethers btw, thanks for this dope project. I look forward to one day seeing this thing in TypeScript and having type safety + hinting, ahhh dreams |
Yupp, absolutely correct. I have finished the Web3Provider and am just running test cases now... Maybe I can get some quick feedback? :) See: 67bb0b7 |
@ricmoo nice work dude! here's some questions/feedback:
I'll give this a shot in our dapp tomm morning and replace the web3 provider with the new ethers Web3Provider - thanks very much! |
the only other feedback I have in general is to perhaps name the functions on the provider similarly to the names of the RPC methods where the |
I've noticed that too, do you have any information why Metamask has that notice? It seems to me the eth_sign and personal_sign perform the same operation. The problem is that personal_sign doesn't exist in Parity. I can try The id is completely arbitrary. It doesn't matter what it is, it just has to be something unique per connection, but each request only lives for one connection. It's only really useful in a long-lived connection to a JSON-RPC connection (e.g. WebSockets), as it allows the sender to multiplex and send multiple requests and know which request each response corresponds to. I usually choose 42 since it is a number that is somewhat obvious and uncommon, so if I see it show up in logs/debugging info somewhere, it rings a bell in my head saying "Hmmm... I am probably responsible for this"... :) |
Re: Basically Parity should have |
yea, it seems since the @ricmoo you could leave it up to the dapp dev to make their choice between eth_sign or personal_sign by offering both without any fallback. For example, ethereumjs-testrpc aka ganache does not implement personal_sign, but it does implement the latest behaviour of eth_sign (which is the same), so in my dapp tests, I make a json-rpc call to you could do something similar if you wanted to, and have |
@shazow For now though, many people (e.g. me :) ) don't have it, and it still isn't added to their list: https://paritytech.github.io/wiki/JSONRPC-personal-module.html What is the difference though? If they both behave identically, how is one secure and the other not? For now, I will do what I can to make sure it just works. A person should not care what they are connected to, Parity JSON-RPC, Geth JSON-RPC, Metamask, etc. I think I will use the |
@pkieltyka Well, that is my annoyance with the Web3 API. It conflates provider and key. And you shouldn't need to call Which is also why I don't think the API should be bogged down with all the various endpoints that various implementations implement, a person who wrote an app against a Web3Provider and Web3Signer should be able to trivially switch to an InfuraProvider and a Wallet. If you use There is a way to do it if they want, but the 99% use case is covered.
Anyhoo... Did you get a chance to try it out? I'm going to upload the new version with Web3Provider to the CDN tonight. |
Before |
Oh, so The |
@shazow Yes, I see now. Thanks. :) But the current behaviour isn't insecure. And the old behaviour is no longer possible. So, why would they deprecate it? And move it? |
@ricmoo Yea, I don't fully understand the deprecation/migration strategy. I think the idea is that they wanted to keep |
I believe MetaMask did the wrong thing by suggesting the warning even after fixing the eth_sign vulnerability after the change to protocol change of eth_sign with the message prefix. I am sure MetaMask will fix this in future versions, but given that many users running older versions of MM will have that waiting, its best to test for isMetaMask and call personal_sign instead specifically for MM. |
I feel like it makes sense to use personal_sign when it's available and issue a warning if you need to fallback to something else that is deprecated (eth_sign). IIRC they're adding more stuff into the personal_* namespace too. |
@ricmoo I'm receiving the following error when trying to instantiate the signer,
in this.provider = new ethers.providers.Web3Provider(web3CurrentProvider)
this.signer = this.provider.getSigner() // error start here my test case stack trace references https://github.com/ethers-io/ethers.js/blob/master/providers/web3-provider.js#L19 |
Sorry, yes, I've fixed that in my working copy. For now you need to specify an address to signer. The fix will be up within an hour.
|
I'm trying to find a definitive source whether |
Found some sources. It is running through Travis CI right now. :) |
@ricmoo In the spirit of "parity probably does the right thing", looks like [ message, address, password ]. |
@ricmoo btw, i've moved my dapp to ethers and its working well! I made the fixes locally to move forward and I see you just committed the fixes as well. The only other thing I ran up against is when running tests against ethereumjs-testrpc (aka ganache-core/cli), the test first grabbed |
@pkieltyka Ugh... Yes, good point, I should lowercase addresses in some of the calls. I had a similar issue when adding Web3 emulation to EthersWallet; CryptoKitties doesn't allow checksum addresses either. |
Ok... One more round of Travis CI. :) |
@ricmoo congrats on the support for MetaMask and other web3.currentProvider-based wallets. Can you push the dist files to npm release? |
Ack! I published to my CDN but forgot npm. Ok, published. [email protected]. Thanks! I hope this helps expand out the user base. :) |
Woo! Going to try this again on my next project, thanks @ricmoo! :D |
@ricmoo the last recommendation if you want to expand the user base:
|
Hey @ricmoo just wondering if you've considered adding the personal api methods such as
personal_sign
among others (https://github.com/ethereum/go-ethereum/wiki/Management-APIs#list-of-management-apis) for the purposes of signing arbitrary data from a wallet.This is something well supported by web3, ethjs and MetaMask.
FYI as well, I've uncovered an EIP that's a standard for machine-verifiable and human-readable typed data signing with Ethereum keys. MetaMask and Cipher have added support for the new method already called
eth_signTypedData
see: ethereum/EIPs#712so two questions,
eth_signTypedData
?The text was updated successfully, but these errors were encountered: