-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
189 additions
and
35 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
export * as lvstlv from "./tlv"; | ||
export * from "./translate"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
import { type Component, Name } from "@ndn/packet"; | ||
import { pattern as P, TrustSchemaPolicy } from "@ndn/trust-schema"; | ||
import { assert } from "@ndn/util"; | ||
|
||
import { type ConsOption, type Constraint, type LvsModel, type Node, type PatternEdge, ValueEdge } from "./tlv"; | ||
|
||
export function toPolicy(model: LvsModel): TrustSchemaPolicy { | ||
return new Translator(model).translate(); | ||
} | ||
|
||
class Translator { | ||
constructor(private readonly model: LvsModel) {} | ||
|
||
private readonly policy = new TrustSchemaPolicy(); | ||
private readonly tagSymbols = new Map<number, string>(); | ||
private readonly wantedNodes = new Set<number>(); | ||
private lastAutoId = 0; | ||
|
||
public translate(): TrustSchemaPolicy { | ||
this.gatherTagSymbols(); | ||
this.gatherNodes(); | ||
this.processPatterns(); | ||
this.processRules(); | ||
return this.policy; | ||
} | ||
|
||
private gatherTagSymbols(): void { | ||
this.tagSymbols.clear(); | ||
for (const { tag, identifier } of this.model.tagSymbols) { | ||
this.tagSymbols.set(tag, identifier); | ||
} | ||
} | ||
|
||
private nameTag(tag: number): string { | ||
// TODO | ||
const prefix = this.tagSymbols.get(tag) ?? `_TAG_${tag}`; | ||
const suffix = tag > this.model.namedPatternCnt ? `_${++this.lastAutoId}` : ""; | ||
return `${prefix}${suffix}`; | ||
} | ||
|
||
private gatherNodes(): void { | ||
this.wantedNodes.clear(); | ||
for (const node of this.model.nodes) { | ||
if (node.ruleNames.length > 0 || node.signConstraints.length > 0) { | ||
this.wantedNodes.add(node.id); | ||
} | ||
for (const sc of node.signConstraints) { | ||
this.wantedNodes.add(sc); | ||
} | ||
} | ||
} | ||
|
||
private processPatterns(): void { | ||
for (const id of this.wantedNodes) { | ||
const node = this.model.nodes[id]!; | ||
const pattern = this.trPattern(node).simplify(); | ||
for (const name of this.namePattern(node)) { | ||
this.policy.addPattern(name, pattern); | ||
} | ||
} | ||
} | ||
|
||
private namePattern(node: Node): string[] { | ||
if (node.ruleNames.length === 0) { | ||
return [`_NODE_${node.id}`]; | ||
} | ||
return node.ruleNames; | ||
} | ||
|
||
private trPattern(node: Node): P.Pattern { | ||
const parts: P.Pattern[] = []; | ||
while (node.parent !== undefined) { | ||
const parent = this.model.nodes[node.parent]!; | ||
const edge = parent.findEdgeTo(node.id)!; | ||
parts.unshift(this.trEdge(edge)); | ||
node = parent; | ||
} | ||
return new P.ConcatPattern(parts); | ||
} | ||
|
||
private trEdge(edge: ValueEdge | PatternEdge): P.Pattern { | ||
if (edge instanceof ValueEdge) { | ||
return this.trValue(edge.value); | ||
} | ||
|
||
// TODO | ||
assert(edge.constraints.length <= 1, "PatternEdge with multiple Constraints is unimplemented"); | ||
const inner = edge.constraints[0] && this.trConstraint(edge.constraints[0]); | ||
return new P.VariablePattern(this.nameTag(edge.tag), { inner }); | ||
} | ||
|
||
private trConstraint(cons: Constraint): P.Pattern { | ||
return new P.AlternatePattern( | ||
Array.from(cons.options, (co) => this.trConsOption(co)), | ||
); | ||
} | ||
|
||
private trConsOption(co: ConsOption): P.Pattern { | ||
if (co.value) { | ||
return this.trValue(co.value); | ||
} | ||
if (co.tag) { | ||
return new P.VariablePattern(this.nameTag(co.tag)); | ||
} | ||
assert(co.call); | ||
// TODO | ||
assert(false, "UserFnCall is unimplemented"); | ||
} | ||
|
||
private trValue(value: Component): P.Pattern { | ||
return new P.ConstPattern(new Name([value])); | ||
} | ||
|
||
private processRules(): void { | ||
for (const node of this.model.nodes) { | ||
const packetIds = this.namePattern(node); | ||
for (const sc of node.signConstraints) { | ||
const signerIds = this.namePattern(this.model.nodes[sc]!); | ||
|
||
for (const packetId of packetIds) { | ||
for (const signerId of signerIds) { | ||
this.policy.addRule(packetId, signerId); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,22 +1,22 @@ | ||
import fs from "node:fs/promises"; | ||
import fs from "node:fs"; | ||
import path from "node:path"; | ||
|
||
import { Decoder } from "@ndn/tlv"; | ||
|
||
import { lvstlv } from ".."; | ||
|
||
async function loadLVSTLV(filename: string): Promise<lvstlv.LvsModel> { | ||
return Decoder.decode( | ||
await fs.readFile(path.join(import.meta.dirname, filename)), | ||
function loadLVSTLV(filename: string): () => lvstlv.LvsModel { | ||
return () => Decoder.decode( | ||
fs.readFileSync(path.join(import.meta.dirname, filename)), | ||
lvstlv.LvsModel, | ||
); | ||
} | ||
|
||
/** python-ndn LVS model sample "quick example". */ | ||
export const pyndn0 = await loadLVSTLV("pyndn0.tlv"); | ||
export const pyndn0 = loadLVSTLV("pyndn0.tlv"); | ||
|
||
/** python-ndn LVS model sample "signing key suggesting". */ | ||
export const pyndn1 = await loadLVSTLV("pyndn1.tlv"); | ||
export const pyndn1 = loadLVSTLV("pyndn1.tlv"); | ||
|
||
/** python-ndn LVS model sample "compiler and checker demonstration". */ | ||
export const pyndn2 = await loadLVSTLV("pyndn2.tlv"); | ||
export const pyndn2 = loadLVSTLV("pyndn2.tlv"); |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import { Name } from "@ndn/packet"; | ||
// import { printESM, versec } from "@ndn/trust-schema"; | ||
import { console } from "@ndn/util"; | ||
import { expect, test } from "vitest"; | ||
|
||
import { toPolicy } from ".."; | ||
import { pyndn0, pyndn1, pyndn2 } from "../test-fixture/lvstlv"; | ||
|
||
test("pyndn0", () => { | ||
const model = pyndn0(); | ||
// console.log(model.toString()); | ||
|
||
const policy = toPolicy(model); | ||
// console.log(printESM(policy)); | ||
// console.log(versec.print(policy)); | ||
expect(policy.canSign( | ||
new Name("/a/blog/article/math/2022/03"), | ||
new Name("/a/blog/author/xinyu/KEY/1/admin/1"), | ||
)).toBeTruthy(); | ||
expect(policy.canSign( | ||
new Name("/a/blog/author/xinyu/KEY/1/admin/1"), | ||
new Name("/a/blog/admin/admin/KEY/1/root/1"), | ||
)).toBeTruthy(); | ||
expect(policy.canSign( | ||
new Name("/a/blog/author/xinyu/KEY/1/admin/1"), | ||
new Name("/a/blog/KEY/1/self/1"), | ||
)).toBeFalsy(); | ||
}); | ||
|
||
test("pyndn1", () => { | ||
const model = pyndn1(); | ||
console.log(model.toString()); | ||
expect(model.nodes).toHaveLength(26); | ||
}); | ||
|
||
test("pyndn2", () => { | ||
const model = pyndn2(); | ||
console.log(model.toString()); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters