Skip to content

Commit

Permalink
Merge pull request #169 from docknetwork/cd-soundness-checker
Browse files Browse the repository at this point in the history
Create a composite claim soundness checker
  • Loading branch information
cykoder authored Oct 6, 2020
2 parents c1df500 + 5e93a05 commit 07ffb75
Show file tree
Hide file tree
Showing 13 changed files with 1,786 additions and 9 deletions.
26 changes: 24 additions & 2 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,33 @@
"sourceType": "module"
},
"rules": {
"no-use-before-define": ["error", { "functions": false, "classes": true, "variables": true }],
"no-use-before-define": [
"error",
{
"functions": false,
"classes": true,
"variables": true
}
],
"class-methods-use-this": "off",
"no-return-await": "off",
"no-plusplus": "off",
"max-len": "off",
"no-console": "off"
"no-console": "off",
"no-restricted-syntax": [
"error",
{
"selector": "ForInStatement",
"message": "for..in loops iterate over the entire prototype chain, which is virtually never what you want. Use Object.{keys,values,entries}, and iterate over the resulting array."
},
{
"selector": "LabeledStatement",
"message": "Labels are a form of GOTO; using them makes code confusing and hard to maintain and understand."
},
{
"selector": "WithStatement",
"message": "`with` is disallowed in strict mode because it makes code impossible to predict and optimize."
}
]
}
}
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
{
"name": "@docknetwork/sdk",
"version": "0.3.4",
"version": "0.3.5",
"main": "index.js",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/docknetwork/sdk"
},
"engines": {
"node": ">=13.0.0"
"node": ">=13.0.0"
},
"resolutions": {
"jsonld-signatures": "https://github.com/docknetwork/jsonld-signatures",
Expand Down Expand Up @@ -79,6 +79,7 @@
"axios": "^0.19.2",
"bs58": "^4.0.1",
"credentials-context": "^1.0.0",
"deep-equal": "^2.0.3",
"did-resolver": "^1.1.0",
"dotenv": "^8.2.0",
"elliptic": "^6.5.3",
Expand Down
99 changes: 99 additions & 0 deletions src/utils/canonicalize.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
// The js interface to rify accepts RDF nodes as strings.
// This module deals with the conversions between the js representation
// of RDF nodes ({ Iri: 'https://example.com' }) and the rify-js representation
// AKA strings.

import { assert } from '@polkadot/util';
import { assertType, assertValidNode } from './common';

// Convert a Node into a cononicalized string representation.
//
// ∀ A, B ∈ Node: canon(A) = canon(B) <-> A = B
export function canon(node) {
assertValidNode(node);
return JSON.stringify(orderKeys(node));
}

/// Canonicalize all the nodes in a ruleset.
export function canonRules(rule) {
return rule.map(({ if_all: ifAll, then }) => ({
if_all: ifAll.map((claim) => claim.map(canonAtom)),
then: then.map((claim) => claim.map(canonAtom)),
}));
}

/// Canonicalize a rule atom.
/// An atom may be either { Bound: Node } or { Unbound: 'string' }
// expect(canonAtom({ Bound: { Iri: 'https://example.com' } }))
// .toEqual({ Bound: "{\"Iri\":\"https://example.com\"}" });
// expect(canonAtom({ Unbound: "heyo" }))
// .toEqual({ Unbound: "heyo" });
function canonAtom(atom) {
assert(Object.keys(atom).length === 1, 'enum must have exactly one tag');
switch (Object.keys(atom)[0]) {
case 'Bound':
assertType(atom.Bound, 'object');
return { Bound: canon(atom.Bound) };
case 'Unbound':
assertType(atom.Unbound, 'string');
return { Unbound: atom.Unbound };
default:
throw new TypeError(`expected bound or unbound rule atom got ${atom}`);
}
}

/// Canonicalize all the nodes in a proof.
export function canonProof(proof) {
return proof.map(({ rule_index: ruleIndex, instantiations }) => ({
rule_index: ruleIndex,
instantiations: instantiations.map(canon),
}));
}

/// Parse all the nodes in a conaonicalized proof.
export function decanonProof(proof) {
return proof.map(({ rule_index: ruleIndex, instantiations }) => ({
rule_index: ruleIndex,
instantiations: instantiations.map(JSON.parse),
}));
}

/// Canonicalize all the nodes in a claimgraph.
export function canonClaimGraph(cg) {
return cg.map((claim) => claim.map(canon));
}

/// Parse all the nodes in a canonicalized claimgraph.
export function decanonClaimGraph(cg) {
return cg.map((claim) => claim.map(JSON.parse));
}

// recursively lexically sort the keys in an object
// expect(JSON.stringify(orderKeys(
// { b: '', a: '' }
// ))).toEqual(JSON.stringify(
// { a: '', b: '' }
// ));
// expect(JSON.stringify(orderKeys(
// { b: '', a: { c: '', b: '', a: '' } }
// ))).toEqual(JSON.stringify(
// { a: { a: '', b: '', c: '' }, b: '' }
// ));
function orderKeys(a) {
let keys;
let ret;
switch (typeof a) {
case 'string':
return a;
case 'object':
keys = Object.keys(a);
keys.sort();
ret = {};
for (const k of keys) {
ret[k] = orderKeys(a[k]);
}
return ret;
default:
throw new TypeError(`type error: orderKeys() does not accept type ${typeof a}`);
}
}
Loading

0 comments on commit 07ffb75

Please sign in to comment.