5

I am storing addresses on the blockchain for IPFS objects, and the addresses are more than 32 bytes. I was using bytes32 for testing but I have truncation. I am seeking a method to read data from the blockchain (array of strings) and then return that into the reactjs to process.

For example I have -

Zipfs.deployed().then(instance=>instance.getIpfsData());
 [ '0x516d586465315a5552556442524c68706f4178587a324b7a585371646f6e446d',
'0x516d6538414d69774d434d446478415936675a3338714a6b6570566b516b5964' ]

I was using bytes32[] but that is not working as a return as follows -

pragma solidity ^0.4.8;
contract Zipfs {

IpfsData[] public ipfsrecs;

struct IpfsData {
    bytes32 reviewData;
}

function addIpfs (bytes32 _reviewData) payable returns (bool success) {
    IpfsData memory newIpfsData;
    newIpfsData.reviewData = _reviewData;

    ipfsrecs.push(newIpfsData);
    return true;
}

function getIpfsData() constant returns (bytes32[]) {

    uint length = ipfsrecs.length;
    bytes32[] memory reviews = new bytes32[](length);

    for (uint i=0; i<ipfsrecs.length; i++) {
        IpfsData memory currentIpfsRec;
        currentIpfsRec = ipfsrecs[i];

        reviews[i]=currentIpfsRec.reviewData;


    }
    return (reviews);
}


}

What can I do as it appears arrays of strings are not supported?

  • I think the solution is to store multiple fields in ethereum and then concatenate the strings after reading them. I will check into this and post an answer when I have one. – Trevor Lee Oakley May 1 '17 at 18:12
2

Life is easier if you can assume 32 bytes. If you are able to restrict the multihash formats you accept or assume sha2-256, which is common now, you could just drop some meta-data so that they fit in 32 bytes. To convert to a bytes32, base-58-decode the data, then strip what should be 0x1220 off the front. The 12 indicates the format (sha2-256), and the 20 is the length of the data, ie 32 bytes.

If you want to handle all the legal multihash formats properly, you could concatenate them together as a single byte array, then manage a separate array holding the start offset of each entry.

  • I am just using the addresses from the IPFS system, can they be pushed into 32 bytes? – Trevor Lee Oakley May 1 '17 at 19:41
  • As base-58-encoded strings they'll take quite a bit more than 32 bytes, but if you decode them as I suggest then normally, yes, you can fit them in exactly 32 bytes. The problem is that there are other legal IPFS address formats that wouldn't fit in 32 bytes. However, nobody seems to be using them in practice. – Edmund Edgar May 1 '17 at 20:11
0

I had the same problematic as you have. By making some assumptions as Edmund suggested, you can easily fit the IPFS hashes in a bytes32. If you have control over the files before sending their hash on-chain that should be future proof enough. Here is the coding and decoding code I'm using on my own d-app. Though I process it in javascript using b58 :

const bs58 = require('bs58');

exports.getBytes32FromIpfsHash = (ipfsHash) => {
  return [].slice.call(new Uint8Array(bs58.decode(ipfsHash).slice(2)));
}


exports.getIpfsHashFromBytes32 = (bytes32) => {
  const hashHex = "1220" + bytes32.slice(2)
  const hashBytes = Buffer.from(hashHex, 'hex');
  const hashStr = bs58.encode(hashBytes)
  return hashStr;
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.