How recreate a hash digest of a multihash in IPFS

The hash you're looking for is the hash of the output of ipfs block get QmWATWQ7fVPP2EFGu71UkfnqhYXDYH566qy47CnJDgvs8u. IPFS hashes the encoded value.

Instead of running:

protoc --decode_raw < /tmp/block.raw | shasum -a 256

Just run:

shasum -a 256 < /tmp/block.raw

but it turns out it returns some other data hash that I don't know how to inspect

That's because we currently use a protobuf inside of a protobuf. The outer protobuf has the structure {Data: DATA, Links: [{Name: ..., Size: ..., Hash: ...}]}.

In:

1 {
  1: 2
  2: "Hello World\n"
  3: 12
}

The 1 { ... } part is the Data field of the outer protobuf. However, protoc --decode_raw *recursively* decodes this object so it decodes theData` field to:

  • Field 1 (DataType): 2 (File)
  • Field 2 (Data): "Hello World\n"
  • Field 3 (Filesize): 12 (bytes)

For context, the relevant protobuf definitions are:

Outer:

// An IPFS MerkleDAG Link
message PBLink {

  // multihash of the target object
  optional bytes Hash = 1;

  // utf string name. should be unique per object
  optional string Name = 2;

  // cumulative size of target object
  optional uint64 Tsize = 3;
}

// An IPFS MerkleDAG Node
message PBNode {

  // refs to other objects
  repeated PBLink Links = 2;

  // opaque user data
  optional bytes Data = 1;
}

Inner:

message Data {
    enum DataType {
        Raw = 0;
        Directory = 1;
        File = 2;
        Metadata = 3;
        Symlink = 4;
        HAMTShard = 5;
    }

    required DataType Type = 1;
    optional bytes Data = 2;
    optional uint64 filesize = 3;
    repeated uint64 blocksizes = 4;

    optional uint64 hashType = 5;
    optional uint64 fanout = 6;
}

message Metadata {
    optional string MimeType = 1;
}

I'm not sure what that encoding is but you can unmarshal the dag data field like this in js-ipfs:

const IPFS = require('ipfs')
const Unixfs = require('ipfs-unixfs')

const ipfs = new IPFS

ipfs.dag.get('QmWATWQ7fVPP2EFGu71UkfnqhYXDYH566qy47CnJDgvs8u', (err, d) => {
  console.log(Unixfs.unmarshal(d.value.data).data.toString()))
  // prints Hello World
})

Tags:

Ipfs