ecrecover en solidez devolviendo dirección nula [duplicado]

Necesito ayuda con la verificación de la dirección de Ethereum. Estoy siguiendo el tutorial sobre cómo firmar y validar la dirección de Ethereum. Código GitHub . Estoy confundido por mi resultado real de la dirección después de ejecutar loginContractInstance.recoverAddr.call(addr, fixed_msg_sha, v_decimal, r,s, function(err, actual) {porque devuelve nulo.

Aquí está mi código backend a continuación,

// 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);
    }

});

Y mi contrato inteligente,

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;
}

Aquí está el resultado de esa llamada de función en mi consola,

ingrese la descripción de la imagen aquí

¿Alguien puede ayudar en lo que me estoy perdiendo?

EDITAR

He corregido la función recoveryAddr.call para usar la entrada correcta. También descubrí que fixed_msg_shael problema es mío porque 0xagregué const fixed_msg_sha = '0x' + web3.sha3(fixed_msg). se imprimió así0x0xf348f6a3d221a5e7e851292474330ca6e6cf6ad54572ee114233ab9b9225ab4f

Ahora el problema ha cambiado para devolver una dirección 0x,ingrese la descripción de la imagen aquí

Respuestas (2)

su función de contrato inteligente:

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

su código de fondo:

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

¿ No crees que tenías la intención de pasar addrcomo primer parámetro?

Sin embargo, no estoy seguro de por qué no se queja de "número no válido de argumentos para la función de solidez".

Gracias por corregir mi descuido. Pero el problema aún persiste después de que lo corregí. Todavía devuelve nulo.

Si está usando esto para reconstruir las preimágenes: \x19Ethereum Signed Message:\n30`que es lo que se proporciona en la publicación mediana, es incorrecto, la cadena de bytes adecuada es:

\x19Ethereum Signed Message:\n32

Observé el mismo ejemplo que usted y me quedé extremadamente atascado cuando experimenté por primera vez con la verificación de la firma, ya que es incorrecto (tal vez era correcto cuando se escribió la publicación mediana, pero ya no).

Tengo un contrato escrito que usa ecrecover y mensajes firmados por geth, puede consultar la declaración del prefijo de la firma aquí: https://github.com/postables/Postables-Payment-Channel/blob/7d2f91bb060f80b139cab72b5fdff79d116f6210/solidity/ChannelsV4. sol#L12 y observe que no coincide con lo que dio el autor de la publicación mediana.

La verificación de la firma real tiene lugar aquí:

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

Mi preferencia personal para firmar mensajes es usar python web3 + un nodo geth local, como lo demuestra este script de python:

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

En mi caso no seguí lo que decía el tutorial, porque lo estoy usando const fixed_msg = \x19Ethereum Signed Message:\n${msg.length}${msg}ya que es más ajustable.
Ese es el error que firma el hash del mensaje, no el mensaje. El hash es siempre de 32 bytes.