He estado buscando para descubrir qué estoy haciendo mal aquí, pero aún no he tenido suerte. Por lo que puedo decir, estoy usando ecrecover correctamente, pero parece que no puedo recuperar la dirección de firma de Ethereum.
Usando una sesión geth, creé y firmé un hash, recuperando los valores r, v y s según la API de Javascript :
> var foobar = web3.sha3('foobar')
undefined
> foobar
"38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e"
> var foo = eth.sign('0x803c84d8b64be30554e2edb9c61b50bc78a7231f', foobar).slice(2)
undefined
> var r = foo.slice(0, 64); var s = foo.slice(64, 128); var v = foo.slice(128);
> v
"00"
> r
"723841761d213b60ac1cbf063207cbeba6c2725bcaf7c189e63f13d93fc1dc07"
> s
"789d1dd423d25f0772d2748d60f7e4b81bb14d086eba8e8e8efb6dcff8a4ae02"
Luego traduje esos valores en una prueba de solidez:
import 'dapple/test.sol';
contract ECRecoverTest is Test {
function testRecovery() {
bytes32 foobar = 0x38d18acb67d25c8bb9942764b62f18e17054f66a817bd4295423adf9ed98873e;
uint8 v = 0x00;
bytes32 r = 0x723841761d213b60ac1cbf063207cbeba6c2725bcaf7c189e63f13d93fc1dc07;
bytes32 s = 0x789d1dd423d25f0772d2748d60f7e4b81bb14d086eba8e8e8efb6dcff8a4ae02;
log_address(ecrecover(foobar, v, r, s));
}
}
Espero ver mi dirección de firma ( 0x803c84d8b64be30554e2edb9c61b50bc78a7231f
) registrada, pero todo lo que veo es:
$ dapple test
Testing...
Using local solc installation...
ECRecoverTest
test recovery
LOG: log_address
LOG: val: 0xb62f18e17054f66a817bd4295423adf9ed98873e
Passed!
También intenté convertir el hash a ASCII antes de firmarlo y también prefijar el hexadecimal con "0x" en caso de que el problema se deba a que la eth.sign
función no entendió que los datos debían tratarse como un valor hexadecimal.
¿Algunas ideas? Ya miré el caso de prueba en pyethereum para asegurarme de que lo estoy usando correctamente, y vi la otra pregunta en este StackExchange . Sin embargo, no parece estar teniendo mucho éxito.
No estoy seguro de si este es su único problema, pero al menos, la v que está obteniendo es incorrecta: debería ser 27 o 28. Desafortunadamente, muchas funciones de firma no le darán, pero puede simplemente pruebe ambos y vea cuál le da la dirección correcta. No es necesario usar hexadecimal para "v", simplemente aliméntelo literalmente 27 o 28 como un int.
El otro truco que me confundió por un tiempo es que si vas a codificar bytes cuando haces que el hash pase a ecrecover, debes asegurarte de que también estabas codificando bytes cuando firmaste. No estoy seguro de si lo estás haciendo bien o no.
Hay un ejemplo aquí si eso ayuda: https://github.com/edmundedgar/realitykeys-examples-ethereum/tree/master/sponsor
Esta esencia es un buen ejemplo de cómo usar ecrecover
. Utiliza ensamblador para filtrar las partes r, s, v de una firma y lo completa en la ecrecover
función.
assembly {
r := mload(add(sig, 32))
s := mload(add(sig, 64))
// Here we are loading the last 32 bytes, including 31 bytes
// of 's'. There is no 'mload8' to do this.
//
// 'byte' is not working due to the Solidity parser, so lets
// use the second best option, 'and'
v := and(mload(add(sig, 65)), 255)
}
Note también la parte v 27, 28 que Edmund mencionó
ryepdx
Edmundo Edgar