Recuperar mensaje firmado JavaScript en Python Web3

Tiene problemas para tomar un mensaje firmado de Web3.js y recuperar la dirección de firma en Web3.py.

Aquí está mi código en JavaScript para crear un mensaje firmado:

async function sign_message() {
    var message = "hi"
    var message_hash = web3.eth.accounts.hashMessage(message)
    //message_hash == 0x0d52783c4cbad7ebaf7eb943fc648f5282a52070442fc18d8dd16ddb2fcbaf66

    var accounts = await web3.eth.getAccounts()
    var signature = await web3.eth.personal.sign(message, accounts[0])
    //accounts[0] ~ 0x6d31165d5d932d571f3b44695653b46dcc327e84
    console.log(signature)
    //signature == 0x29887fe718fcc6e64b97d681f80e6fd485883a45ec0dbc0e35a3752acf1065655d73c9034cac3df0dc82da015abe42367f5e90fd499d872b19610a3ea9c176921b
}

Entonces aquí está tratando de recuperar la dirección en Python:

>>> message = "hi"
>>> message_hash = defunct_hash_message(text=message)
>>> message_hash
HexBytes('0x0d52783c4cbad7ebaf7eb943fc648f5282a52070442fc18d8dd16ddb2fcbaf66')
>>> signature = '0x29887fe718fcc6e64b97d681f80e6fd485883a45ec0dbc0e35a3752acf1065655d73c9034cac3df0dc82da015abe42367f5e90fd499d872b19610a3ea9c176921b'
>>> w3.eth.account.recoverHash(message_hash, signature=signature)
'0x6F4630e882c48151D9e4E386F95009b6312717f4'

Tenga en cuenta que message_hashen ambos ejemplos son iguales, sin embargo, recoverHashno da como resultado la dirección de Ethereum correcta.

He usado estas dos fuentes para tratar de ayudarme a depurar el problema sin éxito:

¿Cómo firmar correctamente una transacción para ser utilizada por ecrecover?

Verificación de la firma personal.sign con pyethereum

¿Cuál es el proveedor en web3.js? Diferentes proveedores (pueden) implementar el método de firma personal de manera diferente.
Estaba usando Metamask (que en la parte de atrás usa Infura, creo) como mi proveedor de Ethereum. Supuse que estas llamadas no dependían de Ethereum, simplemente de la clave privada.
@carver, ¿hay algún código JavaScript que pueda agregar que me garantice poder recuperarme en Python? ¿O viceversa?

Respuestas (1)

Esto es lo que terminó funcionando:

async function create_signature(message, accounts) {
    var hex = ''
    for(var i=0;i<message.length;i++) {
        hex += ''+message.charCodeAt(i).toString(16)
    }
    var hexMessage = "0x" + hex
    var signature = web3.eth.personal.sign(hexMessage, accounts[0])
    return signature
}

Y en el lado de Python, recuperamos la dirección así:

def recover_address(message, signature):
    message_hash = defunct_hash_message(text=message)
    address = w3.eth.account.recoverHash(message_hash, signature=signature)
    return address

Si alguien conoce una mejor manera de calcular el hexMessagecódigo JavaScript, ¡responda con un comentario!