¿Cómo concatenar una matriz de bytes32 [] a una cadena?

Estoy pasando una matriz de bytes32 a mi función. Esta matriz puede contener números o hashes, etc. para identificar un objeto. En un nuevo caso de uso, quiero pasar una URL a esta función dividiendo la URL en partes convertidas en bytes32. ¿Cómo puedo concatenar los bytes32 individuales para restaurar la URL?

Sé que puedo crear una matriz de bytes y establecer bytes en los índices. Pero no sé cómo puedo acceder a una posición específica en bytes32.

function bytes2string(bytes32[] data) returns (string) {
    bytes memory r = new bytes(1);
    r[0] = bytes1(data[0]);
    return string(r);
}

Respuestas (2)

Gracias a Piper y Chris, encontré una solución funcional para Solidity <= 0.2.1. La razón por la que las dos primeras declaraciones de registro devuelven resultados diferentes es porque uintN está alineado a la derecha y bytesN está alineado a la izquierda. La conversión entre uintN y bytesN primero se acorta y luego cambia la alineación. Es por eso que debe volver a bytes32convertirse antes de convertirse en byte:

LogBytes1(byte(data)); // prints "s"
LogBytes1(byte(uint(data))); prints "\x00"
LogBytes1(byte(bytes32(uint(data)))); prints "s"

Una solución probada a mi pregunta es:

function bytes32ArrayToString (bytes32[] data) returns (string) {
    bytes memory bytesString = new bytes(data.length * 32);
    uint urlLength;
    for (uint i=0; i<data.length; i++) {
        for (uint j=0; j<32; j++) {
            byte char = byte(bytes32(uint(data[i]) * 2 ** (8 * j)));
            if (char != 0) {
                bytesString[urlLength] = char;
                urlLength += 1;
            }
        }
    }
    bytes memory bytesStringTrimmed = new bytes(urlLength);
    for (i=0; i<urlLength; i++) {
        bytesStringTrimmed[i] = bytesString[i];
    }
    return string(bytesStringTrimmed);
}
I meet some problem when call this function outside the contract, I specify the bytes32[] string like this [7bb8b6ec123302e43ad88384158e2347efcfef19600b821431e8e09504046595,1f57c6ad7358ac73b73730eabb54b1bea7b785df2e4502291ed99b08af625def] but the compiler tell me it's wrong, why?

Solidez <= 0.2.1

Puede recuperar el enésimo byte de cualquier bytesXXtipo con el siguiente código.

bytes32 v = ...;
byte b = byte(bytes32(uint(v) * 2 ** (8 * n)));

Solidez > 0.2.1

A partir de la próxima versión de Solidity, podrá acceder a ellos mediante índices .

bytes32 v = ...;
byte b = v[n];
Gracias por tu comentario Piper. La solución Solidity <= 0.2.1 no funciona para mí, debido a un comportamiento extraño de Solidity. Suponiendo que tengo un bytes32 que contiene una representación de bytes de la cadena "string", después de una conversión de uint y byte, los datos cambiaron: `event LogBytes1(bytes1); LogBytes1(byte(datos)); // imprime "s" LogBytes1(byte(uint(datos))); // imprime "\x00" `
Actualicé mi código para incluir la refundición a bytes32. No estoy seguro si desea mantener esta respuesta o la de abajo.