Update attenuations

This commit is contained in:
Tony Garnock-Jones 2023-02-06 15:16:57 +01:00
parent 93fcebc4ce
commit 5030130aef
4 changed files with 35 additions and 25 deletions

View File

@ -3,7 +3,7 @@
import { IdentitySet, Value, embeddedId, is, fromJS, stringify } from '@preserves/core'; import { IdentitySet, Value, embeddedId, is, fromJS, stringify } from '@preserves/core';
import { Cell, Field, Graph } from './dataflow.js'; import { Cell, Field, Graph } from './dataflow.js';
import { Attenuation, runRewrites } from './rewrite.js'; import { Caveat, runRewrites } from './rewrite.js';
import { queueTask } from './task.js'; import { queueTask } from './task.js';
export type AnyValue = Value<Ref>; export type AnyValue = Value<Ref>;
@ -34,15 +34,15 @@ export type Cap = Ref;
export interface Ref { export interface Ref {
readonly relay: Facet; readonly relay: Facet;
readonly target: Partial<Entity>; readonly target: Partial<Entity>;
readonly attenuation?: Attenuation; readonly attenuation?: Caveat[];
} }
export class RefImpl implements Ref { export class RefImpl implements Ref {
readonly relay: Facet; readonly relay: Facet;
readonly target: Partial<Entity>; readonly target: Partial<Entity>;
readonly attenuation?: Attenuation; readonly attenuation?: Caveat[];
constructor(relay: Facet, target: Partial<Entity>, attenuation?: Attenuation) { constructor(relay: Facet, target: Partial<Entity>, attenuation?: Caveat[]) {
this.relay = relay; this.relay = relay;
this.target = target; this.target = target;
this.attenuation = attenuation; this.attenuation = attenuation;

View File

@ -8,7 +8,6 @@ import type { SturdyValue } from "../transport/sturdy.js";
import { import {
Alts, Alts,
Attenuation,
Caveat, Caveat,
Lit, Lit,
PAnd, PAnd,
@ -155,21 +154,30 @@ export function rewrite(r: Rewrite, v: Assertion): Assertion | null {
} }
export function examineAlternatives(cav: Caveat, v: Assertion): Assertion | null { export function examineAlternatives(cav: Caveat, v: Assertion): Assertion | null {
if (cav._variant === 'Alts') { switch (cav._variant) {
for (const r of cav.value.alternatives) { case "Alts": {
const w = rewrite(r, v); for (const r of cav.value.alternatives) {
if (w !== null) return w; const w = rewrite(r, v);
if (w !== null) return w;
}
return null;
} }
return null; case "Rewrite":
} else { return rewrite(cav.value, v);
return rewrite(cav.value, v); case "Reject":
return (match(cav.value.pattern, v) !== null) ? null : v;
case "unknown":
return null;
default:
((_: never) => { throw new Error("bad caveat"); })(cav);
} }
} }
export function runRewrites(a: Attenuation | undefined, v: Assertion): Assertion | null { export function runRewrites(a: Caveat[] | undefined, v: Assertion): Assertion | null {
if (a !== void 0) { if (a !== void 0) {
for (const stage of a) { for (let i = a.length - 1; i >= 0; i--) {
const w = examineAlternatives(stage, v); const caveat = a[i];
const w = examineAlternatives(caveat, v);
if (w === null) return null; if (w === null) return null;
v = w; v = w;
} }
@ -185,9 +193,9 @@ export function rfilter(... patterns: Pattern[]): Caveat {
return ps.length === 1 ? Caveat.Rewrite(ps[0]) : Caveat.Alts(Alts(ps)); return ps.length === 1 ? Caveat.Rewrite(ps[0]) : Caveat.Alts(Alts(ps));
} }
export function attenuate(ref: Ref, ... a: Attenuation): Ref { export function attenuate(ref: Ref, ... a: Caveat[]): Ref {
if (a.length === 0) return ref; if (a.length === 0) return ref;
return { ... ref, attenuation: [... a, ... (ref.attenuation ?? [])] }; return { ... ref, attenuation: [... (ref.attenuation ?? []), ... a] };
} }
export function forwarder(ref: Ref): { proxy: Ref, revoker: Ref } { export function forwarder(ref: Ref): { proxy: Ref, revoker: Ref } {

View File

@ -7,7 +7,7 @@ import * as IO from '../gen/protocol.js';
import { wireRefEmbeddedType } from './protocol.js'; import { wireRefEmbeddedType } from './protocol.js';
import { queueTask } from '../runtime/task.js'; import { queueTask } from '../runtime/task.js';
import { attenuate } from '../runtime/rewrite.js'; import { attenuate } from '../runtime/rewrite.js';
import { fromAttenuation, WireRef } from '../gen/sturdy.js'; import { fromCaveat, WireRef } from '../gen/sturdy.js';
export class WireSymbol { export class WireSymbol {
count = 0; count = 0;
@ -264,7 +264,7 @@ export class Relay {
if (ar.__attenuations === void 0) { if (ar.__attenuations === void 0) {
ar.__attenuations = new Dictionary(); ar.__attenuations = new Dictionary();
} }
return ar.__attenuations.getOrSet(fromAttenuation(n.attenuation), () => return ar.__attenuations.getOrSet(n.attenuation.map(fromCaveat), () =>
attenuate(r, ... n.attenuation)); attenuate(r, ... n.attenuation));
} }
} }

View File

@ -45,17 +45,19 @@ export async function mint(oid: SturdyValue, secretKey: Bytes): Promise<S.Sturdy
}); });
} }
export async function attenuate(r: S.SturdyRef, ... a: S.Attenuation): Promise<S.SturdyRef> { async function chainMac(key: Bytes | Promise<Bytes>, caveats: S.Caveat[]): Promise<Bytes> {
return caveats.reduce(async (key, c) => mac(await key, sturdyEncode(S.fromCaveat(c))), key);
}
export async function attenuate(r: S.SturdyRef, ... a: S.Caveat[]): Promise<S.SturdyRef> {
return S.SturdyRef({ return S.SturdyRef({
oid: r.oid, oid: r.oid,
caveatChain: [... r.caveatChain, a], caveatChain: [... r.caveatChain, ... a],
sig: await mac(r.sig, sturdyEncode(S.fromAttenuation(a))) sig: await chainMac(r.sig, a),
}); });
} }
export async function validate(r: S.SturdyRef, secretKey: Bytes): Promise<boolean> { export async function validate(r: S.SturdyRef, secretKey: Bytes): Promise<boolean> {
const sig = await r.caveatChain.reduce( const sig = await chainMac(await mac(secretKey, sturdyEncode(r.oid)), r.caveatChain);
async (sig, a) => mac(await sig, sturdyEncode(S.fromAttenuation(a))),
mac(secretKey, sturdyEncode(r.oid)));
return is(sig, r.sig); return is(sig, r.sig);
} }