ecrecover в солидности, возвращающий нулевой адрес [дубликат]

Мне нужна помощь с проверкой адреса Ethereum. Я следую руководству по подписанию и проверке адреса Ethereum. Код на гитхабе . Меня смущает мой фактический результат адреса после запуска, loginContractInstance.recoverAddr.call(addr, fixed_msg_sha, v_decimal, r,s, function(err, actual) {потому что он возвращает ноль.

Вот мой внутренний код ниже,

// Unlock account before the login attempt
web3.personal.unlockAccount(req.body.address, req.body.password, 100, function(error, unlocked) {
    console.log(`>>>>> Login - User is unlocked: ${unlocked}`);
    if (unlocked) {

        // Signing/ Encryption
        const addr = req.body.address;
        const msg = req.body.password;
        const hex_msg = '0x' + toHex(msg);
        let signature = web3.eth.sign(addr, hex_msg);

        console.log(`address -----> ${addr}`);
        console.log(`msg ---------> ${msg}`);
        console.log(`hex(msg) ----> ${hex_msg}`);
        console.log(`sig ---------> ${signature}`);

        const r = signature.slice(0, 66)
        const s = '0x' + signature.slice(66, 130)
        const v = '0x' + signature.slice(130, 132)
        const v_decimal = web3.toDecimal(v);

        console.log(`r -----------> ${r}`);
        console.log(`s -----------> ${s}`);
        console.log(`v -----------> ${v}`);
        console.log(`vd ----------> ${v_decimal}`);

        // Validation/Decryption
        const fixed_msg = `\x19Ethereum Signed Message:\n${msg.length}${msg}`
        const fixed_msg_sha = '0x' + web3.sha3(fixed_msg)

        loginContractInstance.isSigned.call(addr, fixed_msg_sha, v_decimal, r, s, function (err, signed) {
            console.log(`>>>>> Login - Signature: ${signed}`);

            if (signed) {
                // Saving login attempt
                loginContractInstance.successfulLogin.sendTransaction(req.body.address, req.body.password,
                    {from:'6ded1c5b448819a6cde4293e33fbe54583ef5c52', gas:200000},
                    function(err, transactionHash) {
                        if (!err) {
                            console.log(`>>>>> Login - login details (${addr}, ${msg}) successfully saved @ ${transactionHash}`);
                            console.log(`>>>>> Login - Successfully login`);

                        } else {
                            console.log(`>>>>> Login - login transaction failed: ${err}`);
                        }

                        // set primary account to mine
                        web3.eth.coinbase = req.body.address;

                        console.log(`>>>>> Login - Current User: ${web3.eth.coinbase} is logged in`);

                        var balanceWei = web3.eth.getBalance(req.body.address).toNumber();
                        var balance = web3.fromWei(balanceWei, 'ether');
                        res.json({
                            allowedLogin: true,
                            address: req.body.address,
                            balance: balance,
                            token: generateToken(addr)
                        });

                    });
            } else {
                loginContractInstance.recoverAddr.call(fixed_msg_sha, v_decimal, r,s, function(err, actual) {
                    console.log(`>>>>> Login - Failed login: Signature not matched:${addr} = ${actual}`);
                    saveFailedLoginAttempts(loginContractInstance, req, res);
                });
            }
        });
    } else {
        console.log(`>>>>> Login - Failed login: User is locked`);
        saveFailedLoginAttempts(loginContractInstance, req, res);
    }

});

И мой смарт-контракт,

contract Login {

event LoginAttempt(address sender, string password);

address private sender;
string private password;

function successfulLogin (address _sender, string _password) public {
    LoginAttempt(_sender, _password);
    sender = _sender;
    password = _password;
}

function failedLogin (address _sender, string _password) public {
    LoginAttempt(_sender, _password);
}

function recoverAddr(bytes32 msgHash, uint8 v, bytes32 r, bytes32 s) public pure returns (address) {
    return ecrecover(msgHash, v, r, s);
}

function isSigned(address _addr, bytes32 msgHash, uint8 v, bytes32 r, bytes32 s) public pure returns (bool) {
    return ecrecover(msgHash, v, r, s) == _addr;
}

Вот результат вызова этой функции в моей консоли,

введите описание изображения здесь

Может ли кто-нибудь помочь, что мне не хватает?

РЕДАКТИРОВАТЬ

Я исправил функцию recoveryAddr.call, чтобы она использовала правильный ввод. Я также узнал, что моя fixed_msg_shaпроблема, потому что я добавил 0xв const fixed_msg_sha = '0x' + web3.sha3(fixed_msg). Это было напечатано так0x0xf348f6a3d221a5e7e851292474330ca6e6cf6ad54572ee114233ab9b9225ab4f

Теперь проблема изменилась на возврат адреса 0x,введите описание изображения здесь

Ответы (2)

ваша функция смарт-контракта:

function recoverAddr(bytes32 msgHash, uint8 v, bytes32 r, bytes32 s)

ваш внутренний код:

loginContractInstance.recoverAddr.call(addr, fixed_msg_sha, v_decimal, r,s, function(err, actual) {

Не думаю, что вы намеревались передать addrв качестве первого параметра?

Не уверен, почему он не жалуется на «недопустимое количество аргументов для функции прочности», хотя

Спасибо за исправление моей невнимательности. Но проблема все еще остается после того, как я ее исправил. Он по-прежнему возвращает ноль.

Я знаю, что вы используете это для восстановления прообразов: \x19Ethereum Signed Message:\n30`это то, что дано в сообщении среды. Это неверно, правильная строка байтов:

\x19Ethereum Signed Message:\n32

Я посмотрел на тот же пример, что и вы, и очень застрял, когда впервые экспериментировал с проверкой подписи, так как она неверна (может быть, это было правильно, когда писался средний пост, но не сейчас).

У меня есть написанный контракт, который использует ecrecover и сообщения, подписанные geth, вы можете взглянуть на объявление префикса подписи здесь: https://github.com/postables/Postables-Payment-Channel/blob/7d2f91bb060f80b139cab72b5fdff79d116f6210/solidity/ChannelsV4. sol#L12 и обратите внимание, что он не совпадает с тем, что дал автор поста на Medium.

Фактическая проверка подписи происходит здесь:

https://github.com/postables/Postables-Payment-Channel/blob/7d2f91bb060f80b139cab72b5fdff79d116f6210/solidity/ChannelsV4.sol#L257

Лично я предпочитаю подписывать сообщения с помощью python web3 + локальный узел geth, как показано в этом скрипте python:

https://github.com/postables/Postables-Payment-Channel/blob/develop/python/signer.py

В моем случае я не следовал тому, что сказал учебник, потому что я использую его, const fixed_msg = \x19Ethereum Signed Message:\n${msg.length}${msg}поскольку он более настраиваемый.
Это ошибка, вы подписываете хэш сообщения, а не сообщение. Хэш всегда 32 байта.