Response certification tree

I’ve read the documentation few times but, I am still unsure if the tree that needs to be returned for certification purpose should contains all the resources or only the one that matches the requested url?

e.g. if the canister contains two files, a.html and b.html, and canister-id.ic0.app/a.html is requested, should the tree only contains the requested resource

# labeled ("http_assets",
   #labeled ("/a.html",
      #leaf (hash(a.html_content))
   )
);

or the all tree?

 #labeled ("http_assets",
   #fork(
       #labeled ("/a.html",
          #leaf (hash(a.html_content))
       ),
       #labeled ("/b.html",
          #leaf (hash(b.html_content))
       ),
   );
);

(above pseudo data, tree of the single resource is probably not accurate)

1 Like

I found this video by @nomeata very helpful in understanding how this is supposed to work. I think this part is probably the most relevant to your question (starting at 24:36)

I believe you’re supposed to “prune” the tree to only include data relevant to the query in order to provide a “witness” which proves that the response you’re providing is contained in the tree (or whatever data structure you used)

The video uses the analogy of a redacted document.

4 Likes

Thanks a lot! I tend to thought this was the expectation, then I can assume I got it right. Being said, I still got a bug then, I’m chasing three bytes difference since midday :rofl:.

I have stole Joachim demo code for the motoko certified asset (repo) and merkle tree (repo) and try to apply it to my sample (repo). The certified http works just fine when I got just one resource (index.html) but I did not find yet how to apply it when more resources - more assets need to be certified.

  1. on post upgrade, I generate the tree (source)

  2. I save it to a variable of the actor (for later use) and set the certified data with the root hash (source)

  3. Then when an url is requested, I use the same tree to get the witness of the specific resource only (source) and then generate the certificate and tree (source)

Everything is build and is deployed on mainnet (https://okoji-rqaaa-aaaap-qasma-cai.ic0.app/) but I get a “Body does not pass verification” when I request it.

Debugging the service worker I indeed find that the reconstructed value, built from the certificate, does not equals the certified data.

const hashTree = Cbor.decode(tree);
    const reconstructed = await reconstruct(hashTree);
    const witness = cert.lookup([
        'canister',
        canisterId.toUint8Array(),
        'certified_data',
    ]);
    if (!witness) {
        throw new Error('Could not find certified data for this canister in the certificate.');
    }
    // First validate that the Tree is as good as the certification.
    if (!equal(witness, reconstructed)) {
my error ->  console.error('Witness != Tree passed in ic-certification'); 
        return false;
    }

So it means that somewhere I am encoding something incorrectly, why I was asking if the all tree or just the witness of one resource should be returned. Now at least, I know it’s just one. Thanks again!

Perhaps watch the video in case I’m misremembering or something else stands out that seems different to your approach.

Will do. Listened to the part you mention already, really interesting.