2

I am trying to run some tests for my ecrecover function. I saw a bunch of tutorials and I always have the same problem, my contract always reverts before anything is being logged.

Contract function

event Test(bytes32 _msgHash, uint8 _v, bytes32 _r, bytes32 _s);
    function registerAddress(address _addr, bytes32 _msgHash, uint8 _v, bytes32 _r, bytes32 _s) public returns (bool) {        
        emit Test(_msgHash, _v, _r, _s);   
        if (_v < 27) _v += 27;
        emit Test(_msgHash, _v, _r, _s);        
        if (_v != 27 && _v != 28) revert();
        emit Test(_msgHash, _v, _r, _s);
        if(ecrecover(_msgHash, _v, _r, _s) != _addr)
        {
            emit Test(_msgHash, _v, _r, _s);
            revert();
        }

        registeredAddresses[_addr] = true;

        emit LogRegisterAddress(_addr);

        return true;
    }

Test Code

it('ecrecover result matches address', async function () {
    var address = owner;
    const message = 'Lorem ipsum mark mark dolor sit amet, consectetur adipiscing elit. Tubulum fuisse, qua illum, cuius is condemnatus est rogatione, P. Eaedem res maneant alio modo.';

    var sig = await generateSignature(address, message);
    var ret = await verifySignature(address, message, sig);

    var result = await coinx.registerAddress.sendTransaction(address, ret.encoded, ret.v, ret.r, ret.s, {from: address});
    assert.equal(result, true);
  });

Functions and some variables

const web3 = new Web3(new Web3.providers.HttpProvider(WEB3_PROVIDER_URL));

var node = web3.version.node.split('/')[0];
console.log('Using node=' + node);
var testrpc = false;
var geth = false;
var parity = false;
if (node === 'Geth') geth = true;
if (node === 'EthereumJS TestRPC') testrpc = true;
if (node === 'Parity') parity = true;



function generateSignature (address, message) {
  console.log('Generating signature');
  console.log('  address=' + address);
  if (testrpc) {
    var encoded = web3.sha3(message);
  }
  if (geth || parity) {
    encoded = '0x' + Buffer.from(message).toString('hex');
  }
  console.log('  encoded message=' + encoded);
  return web3.eth.sign(address, encoded);
}

async function verifySignature (address, message, sig) {
  console.log('Verifying signature');
  console.log('  address=' + address);
  let encoded;

  if (testrpc) {
    encoded = web3.sha3(message);
  } else if (geth || parity) {
    encoded = web3.sha3('\x19Ethereum Signed Message:\n' + message.length + message);
  }
  console.log('  encoded message=' + encoded);
  if (sig.slice(0, 2) === '0x') sig = sig.substr(2);
  if (testrpc || geth) {
    var r = '0x' + sig.substr(0, 64);
    var s = '0x' + sig.substr(64, 64);
    var v = '0x' + sig.substr(128, 2);
  }
  if (parity) {
    v = '0x' + sig.substr(0, 2);
    r = '0x' + sig.substr(2, 64);
    s = '0x' + sig.substr(66, 64);
  }
  console.log('  r: ' + r);
  console.log('  s: ' + s);
  console.log('  v: ' + v);

  var ret = {};
  ret.r = r;
  ret.s = s;
  ret.v = v;
  ret.encoded = encoded;
  return ret;
}

Version:

Truffle v4.1.13 (core: 4.1.13)
Solidity v0.4.24 (solc-js) 
npm v5.4.2 
node v8.7.0

1 Answer 1

2

There is a couple of things wrongs.

1- Your encoded message must be

encoded = web3.sha3('\x19Ethereum Signed Message:\n32' + web3.sha3(message))

32 is the length of the hash (sha3(message))

Instead of dealing with complex machine readable string, use other's people library that works ...

const util = require('ethereumjs-util')
encoded = util.hashPersonalMessage(util.toBuffer( web3.sha3(message)))

2- v must be an integer

var v =  web3.toDecimal(sig.substr(128, 2)) + 27

*Full Code *

var SignatureRecover = artifacts.require("SignatureRecover.sol");

const       util            = require('ethereumjs-util'),
            Wallet          = require('ethereumjs-wallet');

contract('SignatureRecover', function(accounts) {

    it('ecrecover result matches address', async function () {
        var address = accounts[0];
        console.log("owner="+address);
        const message = 'Lorem ipsum mark mark dolor sit amet, consectetur adipiscing elit. Tubulum fuisse, qua illum, cuius is condemnatus est rogatione, P. Eaedem res maneant alio modo.';

        var sig = await generateSignature(address, message);
        var ret = await verifySignature(address, message, sig);
        SignatureRecover.deployed().then(function (instance) {
            instance.registerAddress(address, ret.encoded, ret.v, ret.r, ret.s, {from: address}).then(function(tx) {
                console.log(tx.logs);
            });

        });
    });
})

var node = web3.version.node.split('/')[0];
console.log('Using node=' + node);
var testrpc = false;
var geth = false;
var parity = false;
if (node === 'Geth') geth = true;
if (node === 'EthereumJS TestRPC') testrpc = true;
if (node === 'Parity') parity = true;

console.log("testrpc="+testrpc)

function generateSignature (address, message) {
  console.log('Generating signature');
  console.log('  address=' + address);
  if (testrpc) {
    var encoded = web3.sha3(message);
  }
  if (geth || parity) {
    encoded = '0x' + Buffer.from(message).toString('hex');
  }
  console.log('  encoded message=' + encoded);
  return web3.eth.sign(address, encoded);
}

async function verifySignature (address, message, sig) {
  console.log('Verifying signature');
  console.log('  address=' + address);
  let encoded;

  if (testrpc) {
    //encoded = web3.sha3(message);
    encoded = util.hashPersonalMessage(util.toBuffer( web3.sha3(message)))
  } else if (geth || parity) {

    //encoded = web3.sha3('\x19Ethereum Signed Message:\n32' + web3.sha3(message).substr(2));
    encoded = util.hashPersonalMessage(util.toBuffer( web3.sha3(message)))

  }
  console.log('  encoded message=' + encoded.toString('hex'));
  if (sig.slice(0, 2) === '0x') sig = sig.substr(2);
  if (testrpc || geth) {
    var r = '0x' + sig.substr(0, 64);
    var s = '0x' + sig.substr(64, 64);
    var v =  web3.toDecimal(sig.substr(128, 2)) + 27
  }
  if (parity) {
    v = '0x' + sig.substr(0, 2);
    r = '0x' + sig.substr(2, 64);
    s = '0x' + sig.substr(66, 64);
  }
  console.log('  r: ' + r);
  console.log('  s: ' + s);
  console.log('  v: ' + v);

  var ret = {};
  ret.r = r;
  ret.s = s;
  ret.v = v;
  ret.encoded = '0x' + encoded.toString('hex');
  return ret;
}

You can also find all the project on GitHub

i. Run Ganache-cli

$ ganache-cli

ii. Execute Truffle tests

$ truffle test

Compiling ./contracts/Migrations.sol...
Compiling ./contracts/SignatureRecover.sol...
Using node=EthereumJS TestRPC
testrpc=true


  Contract: SignatureRecover
owner=0x7f8b3b04bf34618f4a1723fba96b5db211279a2b
Generating signature
  address=0x7f8b3b04bf34618f4a1723fba96b5db211279a2b
  encoded message=0x067f5bca343172b01203e79581e024f62046b4a935afc81bd1006704a22fbb33
Verifying signature
  address=0x7f8b3b04bf34618f4a1723fba96b5db211279a2b
  encoded message=14431339128bd25f2c7f93baa611e367472048757f4ad67f6d71a5ca0da550f5
  r: 0x51e4dbbbcebade695a3f0fdf10beb8b5f83fda161e1a3105a14c41168bf3dce0
  s: 0x46eabf35680328e26ef4579caf8aeb2cf9ece05dbf67a4f3d1f28c7b1d0e3546
  v: 28
    ✓ ecrecover result matches address (364ms)


  1 passing (440ms)

[ { logIndex: 0,
    transactionIndex: 0,
    transactionHash: '0xe17dcc501eba7efecfd5b0221e5a1f4413648511c69a15d4c296339e02025a4e',
    blockHash: '0x230e806cdecf4a66b84234546261a0675b7c1994ebb64447637ea93c49b49bf6',
    blockNumber: 157,
    address: '0x1f185823be77acab8c093df9190a14293452ae99',
    type: 'mined',
    event: 'Test',
    args: 
     { _msgHash: '0x14431339128bd25f2c7f93baa611e367472048757f4ad67f6d71a5ca0da550f5',
       _v: [Object],
       _r: '0x51e4dbbbcebade695a3f0fdf10beb8b5f83fda161e1a3105a14c41168bf3dce0',
       _s: '0x46eabf35680328e26ef4579caf8aeb2cf9ece05dbf67a4f3d1f28c7b1d0e3546' } },
  { logIndex: 1,
    transactionIndex: 0,
    transactionHash: '0xe17dcc501eba7efecfd5b0221e5a1f4413648511c69a15d4c296339e02025a4e',
    blockHash: '0x230e806cdecf4a66b84234546261a0675b7c1994ebb64447637ea93c49b49bf6',
    blockNumber: 157,
    address: '0x1f185823be77acab8c093df9190a14293452ae99',
    type: 'mined',
    event: 'Test',
    args: 
     { _msgHash: '0x14431339128bd25f2c7f93baa611e367472048757f4ad67f6d71a5ca0da550f5',
       _v: [Object],
       _r: '0x51e4dbbbcebade695a3f0fdf10beb8b5f83fda161e1a3105a14c41168bf3dce0',
       _s: '0x46eabf35680328e26ef4579caf8aeb2cf9ece05dbf67a4f3d1f28c7b1d0e3546' } },
  { logIndex: 2,
    transactionIndex: 0,
    transactionHash: '0xe17dcc501eba7efecfd5b0221e5a1f4413648511c69a15d4c296339e02025a4e',
    blockHash: '0x230e806cdecf4a66b84234546261a0675b7c1994ebb64447637ea93c49b49bf6',
    blockNumber: 157,
    address: '0x1f185823be77acab8c093df9190a14293452ae99',
    type: 'mined',
    event: 'Test',
    args: 
     { _msgHash: '0x14431339128bd25f2c7f93baa611e367472048757f4ad67f6d71a5ca0da550f5',
       _v: [Object],
       _r: '0x51e4dbbbcebade695a3f0fdf10beb8b5f83fda161e1a3105a14c41168bf3dce0',
       _s: '0x46eabf35680328e26ef4579caf8aeb2cf9ece05dbf67a4f3d1f28c7b1d0e3546' } },
  { logIndex: 3,
    transactionIndex: 0,
    transactionHash: '0xe17dcc501eba7efecfd5b0221e5a1f4413648511c69a15d4c296339e02025a4e',
    blockHash: '0x230e806cdecf4a66b84234546261a0675b7c1994ebb64447637ea93c49b49bf6',
    blockNumber: 157,
    address: '0x1f185823be77acab8c093df9190a14293452ae99',
    type: 'mined',
    event: 'LogRegisterAddress',
    args: { _addr: '0x7f8b3b04bf34618f4a1723fba96b5db211279a2b' } } ]

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.