@ceramicnetwork/core
Version:
Typescript implementation of the Ceramic protocol
49 lines • 2.23 kB
JavaScript
import { EventType } from '@ceramicnetwork/common';
export class AnchorTimestampExtractor {
constructor(logger, ipfsLoader, anchorValidator) {
this.logger = logger;
this.ipfsLoader = ipfsLoader;
this.anchorValidator = anchorValidator;
}
async verifyAnchorCommit(commitData) {
const proof = commitData.proof;
const commitPath = commitData.commit.path;
let prevCIDViaMerkleTree;
try {
if (commitPath.length === 0) {
prevCIDViaMerkleTree = proof.root;
}
else {
const merkleTreeParentCommitPath = '/root/' + commitPath.substr(0, commitPath.lastIndexOf('/'));
const last = commitPath.substr(commitPath.lastIndexOf('/') + 1);
const merkleTreeParentCommit = await this.ipfsLoader.retrieveFromIPFS(commitData.commit.proof, merkleTreeParentCommitPath);
prevCIDViaMerkleTree = merkleTreeParentCommit[last];
}
}
catch (e) {
throw new Error(`The anchor commit couldn't be verified. Reason ${e.message}`);
}
if (commitData.commit.prev.toString() !== prevCIDViaMerkleTree.toString()) {
throw new Error(`The anchor commit proof ${proof.toString()} with path ${commitPath} points to invalid 'prev' commit`);
}
return this.anchorValidator.validateChainInclusion(proof);
}
async verifyAnchorAndApplyTimestamps(streamId, log) {
let timestamp = null;
for (let i = log.commits.length - 1; i >= 0; i--) {
const commitData = log.commits[i];
if (commitData.type == EventType.TIME) {
try {
timestamp = await this.verifyAnchorCommit(commitData);
}
catch (err) {
this.logger.warn(`Error when validating anchor commit ${commitData.cid} of stream ${streamId}: ${err}`);
commitData.anchorValidationError = err;
}
}
commitData.timestamp = timestamp;
}
return { commits: log.commits, timestampStatus: 'validated' };
}
}
//# sourceMappingURL=anchor-timestamp-extractor.js.map