Inconsistent behavior of web3.eth.sign between ganache-cli and hdwallet-provider
See original GitHub issue- Question about this asked on gitter: [x]
- Link to the question on gitter: https://gitter.im/ConsenSys/truffle?at=5ecd5c0f778fad0b1329b1c0
Expected Behavior
The output of web3.eth.sign
should be consistent when using different Ethereum clients, including Ganache.
Current Behavior
The output of web3.eth.sign
when using Ganache is different from that of other Ethereum client implementations in that the last byte of the signature (v
) is either 00
or 01
, while in other implementations it’s 1b
or 1c
. Notably, the behavior of web3.eth.sign
when only using Ganache is inconsistent with that of @truffle/hdwallet-provider
.
Note that this inconsistency is not limited to Truffle projects.
- The current example in the Ethereum Wiki however shows that the last output byte resulting from an RPC call to
eth_sign
is1b
(Ganache would return00
instead). The behavior was apparently different in previous versions of this documentation (source). - The current examples in the documentation of Web3.js show that the last output byte of a call to
web3.eth.sign
is00
/01
. - Calling
eth_sign
in Parity/OpenEthereum returns1b
/1c
, as well as callingweb3.eth.sign
with Truffle using Parity/OpenEthereum as its client. - Calling
eth_sign
in Geth returns1b
/1c
.
Possible Solution
Ganache and @truffle/hdwallet-provider
should settle on a single standard output of web3.eth.sign
.
I would recommend changing Ganache’s behavior so that the final byte of an RPC call to eth_sign
is 1b
or 1c
for consistency with Geth and Parity/OpenEthereum. This change would modify the last byte returned by web3.eth.sign
accordingly, since it’s just a wrapper around eth_sign
.
Steps to Reproduce
Install truffle
, ganache-cli
, @truffle/hdwallet-provider
.
Run ganache-cli --mnemonic="shove shoulder neutral steak day correct neither girl alcohol modify bacon fee"
Create a new Truffle project with the following network configuration:
var HDWalletProvider = require("@truffle/hdwallet-provider");
var mnemonic = "shove shoulder neutral steak day correct neither girl alcohol modify bacon fee";
var provider = new HDWalletProvider(mnemonic, "http://localhost:8545");
module.exports = {
networks: {
ganache: {
host: "127.0.0.1",
port: 8545,
network_id: "*"
},
hdwalletprovider: {
provider,
network_id: "*"
}
}
};
Create Truffle script script.js
with the following content:
module.exports = async (callback, b) => {
const accounts = await web3.eth.getAccounts();
console.log(await web3.eth.sign("test string", accounts[0]));
callback();
};
Test the script on both networks:
$ npx truffle exec script.js --network=ganache
Using network 'ganache'.
0x0bef479e20b9186de969a6b1054892d007b870e8086cc162e0b72508a08742ba3830b16c42816dfb0420ae1f509086587971b0c0ada01fff6b17a91e2fddad8a00
$ npx truffle exec script.js --network=hdwalletprovider
Using network 'hdwalletprovider'.
0x0bef479e20b9186de969a6b1054892d007b870e8086cc162e0b72508a08742ba3830b16c42816dfb0420ae1f509086587971b0c0ada01fff6b17a91e2fddad8a1b
Observe that the final bytes differs (00
vs. 1b
).
Context
This issue was found out while debugging an inconsistent behavior between production and testing in a script relying on web3.eth.sign
, see this PR for details.
Your Environment
Truffle v5.1.27 (core: 5.1.27) Solidity v0.5.16 (solc-js) Node v12.16.3 Web3.js v1.2.1 Ganache-cli 6.9.1 @truffle/hdwallet-provider 1.0.35
If the changes I propose in this issue were greenlighted, I’d try to submit a PR implementing them.
Issue Analytics
- State:
- Created 3 years ago
- Reactions:5
- Comments:5 (3 by maintainers)
Top GitHub Comments
Oh wow, I believe your are correct. Well get this fixed asap (which will be next week)!
As far as I know message signatures do not depend on the chain id like it is the case for Ganache. To test this I run the signing code on a Rinkeby Geth node (version 1.10.12-stable, chainId 4) and the returned signature is still ending in
1b
(and1c
). If the implementation depended on the chain id I’d expect thev
value to somehow include the chain id4
.In particular,
eth_sign
signatures can easily be replayed across networks, this is why other signing implementations like EIP-712 recommend to include the chain id in the signed data. Changing just thev
value in any case wouldn’t help as we can just replace it with the correspondingv
value for mainnet and get a valid mainnet signature.Note that here we are talking about message signing and not transaction signing, so even if likely related the issue that was just linked to this is different.