Skip to content
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

Signing with Web3 for callGasRelayed in IdentityGasRelayed.sol #22

Open
gawnieg opened this issue Sep 28, 2018 · 3 comments
Open

Signing with Web3 for callGasRelayed in IdentityGasRelayed.sol #22

gawnieg opened this issue Sep 28, 2018 · 3 comments

Comments

@gawnieg
Copy link

gawnieg commented Sep 28, 2018

I am trying to work out what is the appropriate way to sign offline for the _messageSignatures, in callGasRelayed(...), in IdentityGasRelay.sol.
The params dev instruction states "rsv concatenated ethereum signed message". Which web3 "signing" method is used to arrive at these r,s and v values? As I understand, these change with the encodings and

We have:
bytes32 signHash = getSignHash( callGasRelayHash( _to, _value, keccak256(_data), _nonce, _gasPrice, _gasLimit, _gasToken ) );

Where callGasRelayHash is:
_callGasRelayHash = keccak256( address(this), CALL_PREFIX, _to, _value, _dataHash, _nonce, _gasPrice, _gasLimit, _gasToken );

and getSignHash is:
signHash = keccak256("\x19Ethereum Signed Message:\n32", _hash);

so inline, the signHash is equivalent to:
keccak256("\x19Ethereum Signed Message:\n32", keccak256( address(this), CALL_PREFIX, _to, _value, keccak256(_data), _nonce, _gasPrice, _gasLimit, _gasToken ) )

Signatures included in _messageSignatures are eventually checked against this signHash using ecrecover, which takes the r,s and v values after extraction from _messageSignatures.
If the desired transaction to be relayed is of form:
var tx = { _to, _value, _data, _nonce, _gasPrice, _gasLimit, _gasToken }
How best to sign it offchain so the caller of callGasRelayed() has the correct _messageSignatures?

@3esmit
Copy link
Member

3esmit commented Sep 29, 2018

It should be

hash = web3.soliditySha3(contractAddress, CALL_PREFIX, _to, _value, web3.soliditySha3(_data), _nonce, _gasPrice, _gasLimit, _gasToken ) 
web3.sign(hash)

All key holders should sign the same thing, then the result (r,s,v) should be concatenated, and then concatenated with other signatures.

Note that this contract needs to be updated to latest solidity (which might make things easier), and was not formally audited.

@gawnieg
Copy link
Author

gawnieg commented Sep 30, 2018

@3esmit Thanks!
Some dumb questions: If the _data is to be left as blank, what is used as a placeholder? I am currently getting errors from web3.utils.soliditySha3 when 0x is used.
Is it correct that CALL_PREFIX = 35f894a4, as per the function hash in remix details?
Is using web3.eth.accounts.sign acceptable here too? How is the length field handled?

@richard-ramos
Copy link
Member

richard-ramos commented Oct 1, 2018

@gawnieg,

There's an existing bug that causes soliditySha3 to not work as it should when sending an empty bytes value. (web3/web3.js#1961). For that case you can use the value: "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470" , which represents the keccak of a 0x.

Also, to build the message, what we did, in order to not build the hashed message manually, was invoking the hashing function of the contract directly

hashedMessage = await IdentityGasRelay.methods.callGasRelayHash(
    to,
    value,
    data !== "0x" ? web3.utils.soliditySha3({t: 'bytes', v: data}) : "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"
    nonce,
    gasPrice,
    gasLimit,
    gasToken
).call();

And then, sign it with web3.eth.sign(hashedMessage, account)

------- EDIT ----
Added the placeholder for empty bytes

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants