An IPFS hash can be expressed in hexadecimal which is 34 bytes long. Afaik it is most efficient to store fixed length values in a Ethereum contract, thus a maximum of 32 bytes (bytes32). Because the first two bytes of the IPFS hex hash describe the hash function and the hash size it could be split and stored with something like this:
bytes32 hash
uint8 hash_function
uint8 size
I tried to do the splitting of the hash in solidity:
function splitHash(bytes source) internal returns(uint8, uint8, bytes32 hash) {
uint8 tag = uint8(source[0]);
uint8 len = uint8(source[1]);
assembly {
hash := mload(add(source,34))
}
return (tag, len, hash);
}
and combining it again using:
function combineHash(uint8 _tag, uint8 _len, bytes32 _hash) internal returns(bytes) {
bytes memory out = new bytes(34);
out[0] = byte(_tag);
out[1] = byte(_len);
uint8 i;
for (i = 0; i < 32; i++) {
out[i+2] = _hash[i];
}
return out;
}
This seems to work well but I fail to use it from web3.js and I fail to retrieve the hashes.
Is this approach useful? Does anybody has an example or some best practices on how to store and load IPFS hashes?