3

So, for my studies, I am supposed to interact with a contract function that has the following built in condition:

if (ecrecover(_h, _v, _r, _s) == msg.sender && _h == sha3(this))

I am supposed to provide _h, _v, _r and _s via contract transaction so that the statement equals true.

Our uni has a test server node which we can connect to via mist --rpc and we can also open a web3 provider via http to that node.

I know how to sign messages in web3 and how to extract r, s and v so that ecrecover returns my address. But I can only get the right signature if I use the ethereum signature prefix and thus the condition _h == sha3(this) will always fail. I don't know what to do. I've been trying to somehow access my private key so I can use ethereumjs-util to sign the message but I can't get it.

How can I get a signature with my testnet address that doesn't automatically add the prefix??!

1 Answer 1

3

From Web3 JavaScript-API docs:

After the hex prefix, characters correspond to ECDSA values like this:

r = signature[0:64]
s = signature[64:128]
v = signature[128:130]

Note that if you are using ecrecover, v will be either "00" or "01". As a result, in order to use this value, you will have to parse it to an integer and then add 27. This will result in either a 27 or a 28.

Here's a working example I tested out using truffle:

Example.sol

pragma solidity ^0.4.0;

contract Example {
    function testRecovery(bytes32 h, uint8 v, bytes32 r, bytes32 s) returns (address) { 
        /* prefix might be needed for geth only
         * https://github.com/ethereum/go-ethereum/issues/3731
         */
        // bytes memory prefix = "\x19Ethereum Signed Message:\n32";
        // h = sha3(prefix, h);

        address addr = ecrecover(h, v, r, s);

        return addr;
    }
}

example.js (test)

var Example = artifacts.require('./Example.sol')

var Web3 = require('web3')
var web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545'))

contract('Example', (accounts) => {
  var address = accounts[0]

  it('ecrecover result matches address', async function() {
    var instance = await Example.deployed()
    var contractAddress = instance.address

    var h = web3.sha3(contractAddress)
    var sig = web3.eth.sign(address, h).slice(2)
    var r = `0x${sig.slice(0, 64)}`
    var s = `0x${sig.slice(64, 128)}`
    var v = web3.toDecimal(sig.slice(128, 130)) + 27

    var result = await instance.testRecovery.call(h, v, r, s)
    assert.equal(result, address)
  })
})

Running test:

$ truffle test

Using network 'development'.

Compiling ./contracts/Example.sol...


  Contract: Example
    ✓ ecrecover result matches address (132ms)


  1 passing (147ms)

Related

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.