[Ethereum] Sign and Verify transaction offchain

contract-developmentgo-ethereumraw-transactionsoliditystate-channels

I want to sign and verify a transaction offchain, but I can't really find a proper example/documentation online from start to finish that explains the whole process. Can somebody point to some reference?

If not, and if you do know how to do this, Can you illustrate it with a simple example that would sign a transaction to call the following function of a contract? and take into account that the verifier should be a different account than the signer.

contract simpleContract {

 function simpleContract() public {
 creator = msg.sender;
 }

 uint public value;

 function testingStateChannel(uint simpleValue){
 value=simpleValue;//function to be called in offline signed transaction
 }

 function getSimpleValue() view public returns (uint){
  return value;
 }  
}  

I would appreciate some solution that signs using Web3j (nodejs) or alternatively geth solidity.

Best Answer

For those of you who are also looking for this. Actually it is not exactly what I wanted in the question but it works perfectly for my requirements.

What I do is essentially signing some data, not the transaction, and then retrieving the data from the smart contract, so it is basically the same.

For the geth verify and check signatures, this is the code:

 function sign(address, value){
  var hash = web3.sha3(value.toString());
  var sig = web3.eth.sign(address, hash)
  //var result = personal.ecRecover(h, "0x"+sig)
  // send to user => value, address, result
  return [hash,sig];
}

function rsv_generate(signature){
  signature = signature.slice(2);
  var r = '0x' + signature.slice(0, 64);
  var s = '0x' + signature.slice(64, 128);
  var v = web3.toDecimal(parseInt("0x"+signature.slice(128,130))); // must be +27 of not 28 or 27
  return [r,s,v]
}

function verify(message, hash, signature, address) {
  var hashed_message = web3.sha3(message.toString());
  var signer_address = personal.ecRecover(hash,signature);
  return (hashed_message == hash) && (signer_address == address);
}

function verify(message, result, address) {
  var hash = result[0];
  var signature = result[1]
  var hashed_message = web3.sha3(message.toString());
  var signer_address = personal.ecRecover(hash,signature);
  return (hashed_message == hash) && (signer_address == address);
}

Then, in the solidity code, the same check as offline can be done in the following way:

pragma solidity ^0.4.19;
contract chargingContract {      

function verify(string message, address p, bytes32 hash, uint8 v, bytes32 r, bytes32 s) pure public returns(bool) {
  bytes memory prefix = "\x19Ethereum Signed Message:\n32"; //necessary in   Solidity as of 0.4.19
  bytes32 prefixedHash = keccak256(prefix, hash);
  bytes32 hashedMessage = sha3(message);
  return ecrecover(prefixedHash, v, r, s) == p && hashedMessage == hash;
 }
}