La dirección son los últimos 20 bytes desha3(publicKey)
En Solidity, usando ensamblaje si es necesario, ¿cómo podría empalmar los primeros 12 bytes sha3(publicKey)
y obtener la dirección? Lo que se me ocurrió se queda sin gasolina:
bytes32 b = sha3(publicKey)
address signer;
assembly {
signer := mload(add(b, 0x0c) // skip the first 12 bytes, 0c in hex = 12
}
MLOAD(0XAB) carga la palabra (32 bytes) ubicada en la dirección de memoria 0XAB. ¿Mi función falla porque está tratando de cargar solo 20 bytes? ¿MLOAD puede cargar solo 20 bytes?
Esto funciona:
return address(keccak256(publicKey) & (2**(8*21)-1));
2**(8*21)-1
es solo un truco para obtener 0xFFFFFF... (40 Fs) sin escribirlo. :-)
EDITAR
Como señaló @schnorr, no hay necesidad de la máscara:
return address(keccak256(publicKey));
address
tiene un tamaño de 20 bytes, por lo que no puede almacenar más bytes que eso. Mantiene los bytes menos significativos, como todas las conversiones a números de menor tamaño.keccak256
siempre devuelve 32 bytes.)De una respuesta a ¿Cómo convertir un byte a una dirección en Solidity? así como una respuesta a ¿Cómo concatenar una matriz de bytes32 [] en una cadena? , se me ocurrió esto para convertir una bytes32 keyHash
en una dirección.
function getAddressFromPublicKey(bytes _publicKey) returns (address signer) {
// Get address from public key
bytes32 keyHash = keccak256(_publicKey);
uint result = 0;
for (uint i = keyHash.length-1; i+1 > 12; i--) {
uint c = uint(keyHash[i]);
uint to_inc = c * ( 16 ** ((keyHash.length - i-1) * 2));
result += to_inc;
}
return address(result);
}
En solidez 0.5:
function calculateAddress(bytes memory pub) public pure returns (address addr) {
bytes32 hash = keccak256(pub);
assembly {
mstore(0, hash)
addr := mload(0)
}
}
Esto debería funcionar para Solidity 0.5.x:
bytes32 hash = keccak256(publicKey);
address wallet = address(uint160(bytes20(hash)));
noel maersk
sha3(pk)+12
, que es (muy probablemente) un número de 256 bits. Te estás quedando sin gasolina porque la expansión de la memoria a una ubicación tan alta se la come toda.noel maersk
usuario19510
add(b, 0x0c)
es análoga a la aritmética de punteros. (Le da la ubicación en la memoria 12 bytes después del comienzo deb
).