Я пытался понять, что я делаю неправильно здесь, но мне пока не повезло. Насколько я могу судить, я правильно использую ecrecover, но не могу вернуть адрес подписи Ethereum.
Используя сеанс geth, я создал и подписал хэш, получая значения r, v и s в соответствии с API 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"
Затем я перевел эти значения в тест Solidity:
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));
}
}
Я ожидаю, что мой адрес подписи ( 0x803c84d8b64be30554e2edb9c61b50bc78a7231f
) будет зарегистрирован, но все, что я вижу, это:
$ dapple test
Testing...
Using local solc installation...
ECRecoverTest
test recovery
LOG: log_address
LOG: val: 0xb62f18e17054f66a817bd4295423adf9ed98873e
Passed!
Я также попытался преобразовать хэш в ASCII перед его подписанием, а также добавить к шестнадцатеричному префиксу «0x» на тот случай, если проблема была связана с тем, что eth.sign
функция не вникала в то, что данные должны обрабатываться как шестнадцатеричное значение.
Любые идеи? Я уже просмотрел тестовый пример в pyethereum, чтобы убедиться, что использую его правильно, и я видел другой вопрос на этом StackExchange . Просто, кажется, не имеет большого успеха, хотя.
Я не уверен, что это ваша единственная проблема, но, по крайней мере, v, который вы получаете, неверен - он должен быть 27 или 28. К сожалению, многие функции подписи не дадут вам его, но вы можете просто попробуйте оба и посмотрите, какой из них дает вам правильный адрес. Не нужно использовать шестнадцатеричный код для «v» — просто введите 27 или 28 как целое число.
Еще одна хитрость, которая некоторое время меня смущала, заключается в том, что если вы собираетесь хэшировать байты, когда вы делаете хэш для передачи в ecrecover, вы должны убедиться, что вы хэшировали байты, когда подписывали. Я не уверен, правильно ли вы это понимаете или нет.
Здесь есть пример, если это поможет: https://github.com/edmundedgar/realitykeys-examples-ethereum/tree/master/sponsor
Этот смысл является хорошим примером того, как использовать ecrecover
. Он использует ассемблер, чтобы отфильтровать r, s, v части подписи и заполнить их ecrecover
функцией.
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)
}
Обратите также внимание на часть v 27, 28, которую упомянул Эдмунд.
ryepdx
Эдмунд Эдгар