Skip to content

Instantly share code, notes, and snippets.

@zarutian
Last active September 13, 2020 21:55
Show Gist options
  • Save zarutian/2cb903d37364b9a7518c300417c23801 to your computer and use it in GitHub Desktop.
Save zarutian/2cb903d37364b9a7518c300417c23801 to your computer and use it in GitHub Desktop.
/*
This whole thing sprang forth from a comment MarkM made regarding ActiveCapCerts
and various musings of my own.
*/
const seqBlock = (block, opt = {}) => {
if (opt.NearGuard === undefined) {
// tbd; hmm
opt.NearGuard = {
coerce: (specimen, ejector) => { return specimen; }
}
}
if (opt.outer === undefined) {
opt.outer = () => { throw new Error("no outer than that"); };
}
const sb = () => {
const sb_args = arguments;
const r = SingleAssigmentMap();
const i = (item) => {
switch (item[0]) {
case "@qid": return r.get(item[1]);
case "@sba": return sb_args[item[1]];
case "@ref":
case "@dat": return item[1];
case "@arr": return item.slice(1).map(i);
case "@rec": return Object.fromEntries(Object.entries(item[1]).map((k, v) => { return [k, i(v)]; }));
case "@prx": return new Proxy(i(item[1]), i(item[2]));
case "@hpr": return new HandledPromise((res, rej, rep) => { return (i(item[1]))~.(res, rej, rep); });
case "@sqb":
// tbd: ætti þerra að vera? gerir seqBlock öflugra
// en @agoric/Justin
// tbd: a) item[1]
// b) i(item[1])
// c) ri(item[1]) reqursive i() með "@outer" kind tag
const o = {...opt, outer: i}
return seqBlock(i(item[1]), o);
case "@outer": return opt.outer(item.slice(1));
case "@record": throw "tbd";
case "@tuple": throw "tbd";
}
};
var last_qid = 0;
block.forEach((evSend) => {
switch (evSend[0]) {
case "mso":
case "applyMethodSendOnly":
(() => {
const [kind, target, verb, args] = evSend;
void HandledPromise.applyMethodSendOnly(i(target), verb, i(args));
})(); break;
case "m":
case "applyMethod":
(() => {
const [kind, qid, target, verb, args] = evSend;
r.set(qid, HandledPromise.applyMethod(i(target), verb, i(args)));
last_qid = qid;
})(); break;
case "fso":
case "applyFunctionSendOnly":
(() => {
const [kind, target, args] = evSend;
void HandledPromise.applyFunctionSendOnly(i(target), i(args));
})(); break;
case "f":
case "applyFunction":
(() => {
const [kind, qid, target, args] = evSend;
r.set(qid, HandledPromise.applyFunction(i(target), i(args)));
last_qid = qid;
})(); break;
case "gso":
case "getSendOnly":
(() => {
const [kind, target, prop] = evSend;
void HandledPromise.getSendOnly(i(target), prop);
})(); break;
case "g":
case "get":
(() => {
const [kind, qid, target, prop] = evSend;
r.set(qid, HandledPromise.get(i(target), prop));
last_qid = qid;
})(); break;
case "rv":
case "returnValue":
(() => {
const [kind, val] = evSend;
last_qid = Object.freeze(Object.create(null));
r.set(last_qid, i(val));
})(); break;
case "a":
case "assignOnce":
(() => {
const [kind, qid, val] = evSend;
r.set(qid, i(val));
last_qid = qid;
})(); break;
/*
case "imi":
case "immediateMethodInvocation":
// hmm spurning um hvort þetta ætti að vera til yfir höfuð.
// handles atomicity by running in one turn
// þarf e-ð álíka Near guard úr E
(() => {
const [kind, qid, target, verb, args] = evSend;
last_qid = qid;
try {
const t = opt.NearGuard.coerce(target);
r.set(qid, [true, t[verb](...args)]);
} catch (p) {
r.set(qid, [false, p]);
}
})(); break;
case "ifa":
case "immediateFunctionApply":
// sama
(() => {
const [kind, qid, target, args] = evSend;
last_qid = qid;
try {
const t = opt.NearGuard.coerce(target);
r.set(qid, [true, t(...args)]);
} catch (p) {
r.set(qid, [false, p]);
}
})(); break;
*/
default:
}
});
return r.get(last_qid);
};
sb._sealedDispatch = (brand) => {
if (brand === trustedSerializerBrand) {
return trustedSerializerSealer.seal(["functionCall", seqBlock, [block]]);
}
return null;
};
return sb;
};
const SingleAssigmentMap = (...args) => {
const backing = new Map();
return Object.freeze({
"has": (key) => (backing.has(key)),
"get": (key) => {
if (!backing.has(key)) {
throw new Error("a SingleAssignmentMap does not have an sought after key");
}
return backing.get(key);
},
"set": (key, value) => {
if (backing.has(key)) {
throw new Error("a SingleAssigment has already got a value assigned under given key");
}
return backing.set(key, value);
}
});
}
const doLoopy = remoteSeqBlock~.([
["applyFunctionSendOnly", ["@sba", 0], ["@sba", 1]],
["applyFunction", "p2", ["@sba", 2], ["@sba", 3]],
["applyMethod", "p3", ["@qid", "p2"], "pick",["@arr", ["@sba", 4], ["@sba", 5]]],
["applyFunction", "p4", ["@qid", "p3"], ["@arr", ["@sba", 0], ["@sba", 1], ["@sba", 2], ["@sba", 3], ["@sba", 4], ["@sba", 5]]],
["returnValue", ["@qid", "p2"]]
]);
const ignorer = () => { return undefined; };
const p53 = doLoopy~.(body, body_args, cond, cond_args, doLoopy, ignorer);
const p54 = remoteArrayInstance~.map(remoteSeqBlock~.([["mso", ["@sba", 0], "add", ["@arr", 42]]));
const remoteSlotMaker = remoteSeqBlock~.([
["assignOnce", "theSlot", ["@arr", ["@dat", undefined]],
["returnValue", ["@rec", {
"get": ["@sqb", [
["get", "ignored", ["@outer", "@qid", "theSlot"], ["@dat", 0]]
]],
"set": ["@sqb", [
["applyMethodSendOnly", ["@outer", "@qid", "theSlot"], "pop", ["@arr"]],
["applyMethodSendOnly", ["@outer", "@qid", "theSlot"], "push", ["@arr", ["@sba", 0]]],
["returnValue", ["@sba", 0]]
]] }]]
]);
//
const async_NOT = (a) => {
return a~.pick(false, true);
};
const async_OR = (a, b) => {
const c = a~.pick([true, true], [true, false]);
return b~.pick(c~.[0], c~.[1]);
};
const async_AND = (a, b) => {
const c = a~.pick([true, false], [false, false]);
return b~.pick(c~.[0], c~.[1]);
};
const async_XOR = (a, b) => {
const c = a~.pick([false, true], [true, false]);
return b~.pick(c~.[0], c~.[1]);
};
// argsAwait
const awaitOnArgsForMethodThenSend = async (target, verb, args) => {
const settledArgs = await Promise.allSettled(args);
return HandledPromise.applyMethod(target, verb, settledArgs);
}
const awaitOnArgsForFunctionThenSend = async (target, args) => {
const settledArgs = await Promise.allSettled(args);
return HandledPromise.applyFunction(target, settledArgs);
}
const awaitOnThenMethodSend = (blockerP, target, verb, args) => {
// works for same purpose as Capn Proto embargo
return blockerP.then((_) => HandledPromise.applyMethod(target, verb, args));
}
const awaitOnThenFunctionSend = (blockerP, target, args) => {
return blockerP.then((_) => HandledPromise.applyFunction(target, args));
}
/*
const async_array_filter = (remoteArray, remoteSeqBlock, filterFunc) => {
// todo: some sort of guard that checks if remoteArray and remoteSeqBlock are at the same vat. Possible?
// see the whole EQ? discussions on that
const result = [];
const pushItem = (i) => {
result.push(i);
};
const ignoreItem = remoteSeqBlock~.([]);
const sb1 = remoteSeqBlock~.([
["f", "p1", ["@ref", filterFunc], ["@arr", ["@sba", 0], ["@sba", 1]]],
["m", "p2", ["@qid", "p1"], "pick", ["@arr", ["@ref", pushItem], ["@ref", ignoreItem]]],
["fso", ["@qid", "p2"], ["@arr", ["@sba", 0]]]
]);
remoteArray~.forEach(sb1);
return result;
}
*/
const async_array_filter = (remoteArray, remoteSeqBlock, filterFunc) => {
const sb = remoteSeqBlock~.([
["f", "p1", ["@ref", filterFunc], ["@arr", ["@sba", 1]]],
["m", "p2", ["@qid", "p1"], "pick", ["@arr", ["@sba", 0], ["@arr"]]],
["mso", ["@qid", "p2"], "push", ["@arr", ["@sba", 1]]],
["rv", ["@sba", 0]]
]);
const remoteMakeArray = remoteSeqBlock~.([["rv", ["@arr"]]]);
return remoteArray~.reduce(sb, remoteMakeArray~.());
}
const async_mux = (pSel, pInps) => {
const selBits = pSel~.toBoolArray(8);
const q0 = pInps~.slice(0, 128);
const q1 = pInps~.slice(128, 256);
const q2 = selBits~.[7]~.pick(q0, q1);
const q3 = q2~.slice(0, 64);
const q4 = q2~.slice(64, 128);
const q5 = selBits~.[6]~.pick(q3, q4);
const q6 = q5~.slice(0, 32);
const q7 = q5~.slice(32, 64);
const q8 = selBits~.[5]~.pick(q6, q7);
const q9 = q8~.slice(0, 16);
const q10 = q8~.slice(16, 32);
const q11 = selBits~.[4]~.pick(q9, q10);
const q12 = q11~.slice(0, 8);
const q13 = q11~.slice(8, 16);
const q14 = selBits~.[3]~.pick(q12, q13);
const q15 = q14~.slice(0, 4);
const q16 = q14~.slice(4, 8);
const q17 = selBits~.[2]~.pick(q15, q16);
const q18 = q17~.slice(0, 2);
const q19 = q17~.slice(2, 4);
const q20 = selBits~.[1]~.pick(q18, q19);
const q21 = selBits~.[0]~.pick(q20~.[0], q20~.[1]);
return q21;
}
//
Function.prototype.toJSON = function () {
return {"$func":"".concat(this)};
}
Boolean.prototype.pick = function (conseq, altern) {
return (this.valueOf() ? conseq : altern);
}
/*
true.pick = (conseq, altern) { return conseq; };
false.pick = (conseq, altern) { return altern; };
true.not = () => { return false; };
false.not = () => { return true; };
*/
Boolean.prototype.not = function () {
return !(this.valueOf());
}
Boolean.prototype.and = function (other) {
return (this.valueOf() && Boolean(other));
}
Boolean.prototype.or = function (other) {
return (this.valueOf() || Boolean(other));
}
BigInt.prototype.add = function (other) {
return (this.valueOf()) + BigInt(other);
}
BigInt.prototype.subtract = function (other) {
return (this.valueOf()) - BigInt(other);
}
BigInt.prototype.multiply = function (other) {
return (this.valueOf()) * BigInt(other);
}
BigInt.prototype.divide = function (other) {
return (this.valueOf()) / BigInt(other); // /
}
BigInt.prototype.modulo = function (other) {
return (this.valueOf()) % BigInt(other);
}
BigInt.prototype.exponate = function (other) {
return (this.valueOf()) ** BigInt(other);
}
BigInt.prototype.negate = function () {
return -(this.valueOf());
}
BigInt.prototype.bitwiseNot = function () {
return ~(this.valueOf());
}
BigInt.prototype.bitwiseAnd = function (other) {
return (this.valueOf()) & BigInt(other);
}
BigInt.prototype.bitwiseOr = function (other) {
return (this.valueOf()) | BigInt(other);
}
BigInt.prototype.bitwiseXor = function (other) {
return (this.valueOf()) ^ BigInt(other);
}
// ...
BigInt.prototype.toBoolArray = function (nrOfBits = 32) {
var v = this.valueOf();
const r = [];
while (nrOfBits > 0) {
r.push(((v & 0x1) == 0x1));
v = v >> 1;
nrOfBits--;
}
return r;
}
Number.prototype.toBoolArray = BigInt.prototype.toBoolArray;
BigInt.fromBoolArray = (arr) => {
var n = BigInt(0);
while (arr.length > 0) {
n = n << 1;
n = n + (arr.pop() ? BigInt(1) : BigInt(0));
}
return n;
}
BigInt.prototype.isZero = function () {
return (this.valueOf() == 0n);
}
BigInt.prototype.isGreaterThan = function (other) {
return (this.valueOf() > BigInt(other));
}
BigInt.prototype.isLessThan = function (other) {
return (this.valueOf() < BigInt(other));
}
BigInt.prototype.isEqual = function (other) {
return (this.valueOf() == BigInt(other));
}
BigInt.prototype.timesDoEventually = function (block, step = 1n) {
if (this.isGreaterThan(0n)) {
/*
const next = block~.(this);
void BigInt(this.valueOf() - 1n)~.timesDoEventual(next);
*/
void block~.(this);
void this.subtract(step)~.timesDoEventually(block, step);
}
}
const async_switch = (selector, cases) => {
const [first, ...rest] = cases;
switch (first[0]) {
case "case":
return HandledPromise.applyFunction(selector~.isEqual(first[1])~.pick(first[2], () => async_switch(selector, rest)), first[3]);
case "default":
return HandledPromise.applyFunction(first[1], first[2]);
default:
}
}
const XOR = (a, b) => { return BigInt(a) ^ BigInt(b); };
const bitEqual = (a, b) => { return BigInt(a) == BigInt(b); };
const makeBigRandom = (nrOfBits) => {
var result = BigInt(0);
while (nrOfBits > 0) {
nrOfBits--;
result = BigInt((result < 1) | makeRandomBit());
}
return result;
};
const Ask_Bob_outstanding = new WeakMap();
Object.prototype._ask = function (requestHandle, myNonce) {
const self = this;
var requestedOfMe = Ask_Bob_outstanding.get(self);
if (requestedOfMe === undefined) {
requestedOfMe = new WeakMap();
Ask_Bob_outstanding.set(self, requestedOfMe);
}
const other = requestedOfMe.get(requestHandle);
var myPromise, myResolver, yourPromise, yourResolver;
if (other === undefined) {
[myPromise, myResolver] = makePromise();
[yourPromise, yourResolver] = makePromise();
requestedOfMe.set(requestHandle, [myPromise, yourResolver]);
} else {
[yourPromise, myResolver] = other;
}
myResolver.resolve(myNonce);
return yourPromise.then((yourNonce) => XOR(myNonce, yourNonce));
}
const Ask_Bob_ifSame = (Bob1, Bob2) => {
const requestHandle = harden({});
const nonce1 = makeBigRandom(128);
const nonce2 = makeBigRandom(128);
const r1 = Bob1~._ask(requestHandle, nonce1);
const r2 = Bob2~._ask(requestHandle, nonce2);
return Promise.all([r1, r2]).then(([result1, result2]) => {
return bitEqual(result1, result2);
}, () => false);
}
const Ask_Bob_ifSame2 = (Bob1, Bob2) => {
const request = makeBigRandom(128);
const nonce1 = makeBigRandom(128);
const nonce2 = makeBigRandom(128);
const r1 = Bob1~._ask(request, nonce1);
const r2 = Bob2~._ask(request, nonce2);
return Promise.all([r1, r2]).then(([res1, res2]) => {
return bitEqual(res1, res2);
}, () => false);
}
const make_async_distributed_Map = (opt={}) => {
// opt.myEntries is {Iterable.next => [key, value]}
// opt.nrOfEntriesIkeep { max: Int, min: Int }
// opt.nextPresence
// opt.random
if (opt.myEntries == undefined) {
opt.myEntries = new Array();
}
if (opt.nrOfEntriesIkeep == undefined) {
opt.nrOfEntriesIkeep = {};
}
if (opt.nrOfEntriesIkeep.min == undefined) {
opt.nrOfEntriesIkeep.min = 100;
}
if (opt.nrOfEntriesIkeep.max == undefined) {
opt.nrOfEntriesIkeep.max = 5000;
}
if (opt.nextPresence == undefined) {
opt.nextPresence = {
has: (key) => false,
get: (key) => undefined,
set: (key, value) => { throw new Error("cant set"); },
delete: (key) => true;
entries: () => (new Array()).[Symbol.iterator];
};
}
if (opt.random == undefined) {
// the purpose of opt.random is to provide some picking
// distribution. If no opt.random was given the Finbonatci
// is good as any.
var fibA = 0n; var fibB = 1n;
opt.random = (maximum = 1) => {
var fibC = fibA + fibB; fibA = fibB; fibB = fibC;
return fibC % maximum;
}
}
const backing = new Map(opt.myEntries);
var moving = false;
const housekeep = () => {
const size = backing.size;
if (size > opt.nrOfEntriesIkeep.max) {
if (moving) { return; }
moving = true;
var nrToMove = size - opt.nrOfEntriesIkeep.min;
const keysToMove = [];
const entries = new Array(backing.entries());
while (nrToMove > 0) {
const enr = opt.random(size);
const [key, _] = entries[enr];
if (!keysToMove.includes(key)) {
keysToMove.push(key);
nrToMove = nrToMove - 1;
}
}
void Promise.allSettled(keysToMove.map((key) => {
const r = opt.nextPresence~.set(key, backing.get(key));
backing.delete(key);
return r;
})).then((outcomes) => {
outcomes.forEach((outc, idx) => {
if (outc.status == "rejected") {
const [key, value] = entries[idx];
backing.set(key, value);
}
}
moving = false;
});
}
};
return harden({
has: (key) => {
housekeep();
if (backing.has(key)) {
return Promise.resolve(true);
} else {
return opt.nextPresence~.has(key);
}
},
get: (key) => {
housekeep();
if (backing.has(key)) {
return Promise.resolve(backing.get(key));
} else {
return opt.nextPresence~.get(key);
}
},
set: (key, value) => {
housekeep();
if (backing.has(key)) {
return Promise.resolve(backing.set(key, value));
} else {
return opt.nextPresence~.has(key).then((result) => {
if (result) {
return opt.nextPresence~.set(key, value);
} else {
return Promise.resolve(backing.set(key, value));
}
});
/* // alternative impl:
return opt.nextPresence~.has(key)~.pick(opt.nextPresence, backing)~.set(key, value);
*/
}
},
delete: (key) => {
housekeep();
if (backing.has(key)) {
return Promise.resolve(backing.delete(key));
} else {
return opt.nextPresence~.has(key).then((result) => {
if (result) {
return opt.nextPresence~.delete(key);
} else {
return Promise.resolve(backing.delete(key));
}
});
/* // alternative impl:
return opt.nextPresence~.has(key)~.pick(opt.nextPresence, backing)~.delete(key);
*/
},
entries: () => {
const mine = backing.entries();
const others = opt.nextPresence~.entries();
var doneHere = false;
return harden({ next: () => {
if (doneHere) {
return others~.next();
} else {
const r = mine.next();
if (r.done) {
r.done = false;
doneHere = true;
}
return Promise.resolve(r);
}
}});
}
}
});
}
// a challange: implement FCPU-16 using only the tools above plus eventual send
/*
FCPU-16 is a 16 bit dual stack machine with the following instruction set
0x0000 NOP
0x0001 UM+ ( a b -- sum carry )
0x0002 AND ( a b -- a&b )
0x0003 XOR ( a b -- a^b )
0x0004 1LBR ( u -- u )
0x0005 INCR ( u -- u+1 )
0x0006 FETCH ( addr -- cell )
0x0007 STORE ( cell addr -- )
0x0008 DUP ( a -- a a )
0x0009 DROP ( a -- )
0x000A SWAP ( a b -- b a )
0x000B SKZ ( a -- ) PC = (a == 0) ? PC+1 : PC
0x000C >R ( a -- ) R:( -- a )
0x000D R> ( -- a ) R:( a -- )
0x000E EXT ( ... ext-nr -- ... )
0x000F EXIT ( ) R:( ra -- ) PC = ra
0x____ call ( ) R:( -- PC ) PC = INSTR
ext-nr:
0x7000 is-a-cap ( cap-nr -- T | F )
0x7001 nr-of-caps ( -- nr-of-caps )
0x7002 drop-cap ( cap-nr -- )
0x7003 swap-caps ( cap-nr-A cap-nr-B -- )
0x7004 "get" ( dest-cap-nr prop-cap-nr -- promise-cap-nr )
0x7005 "functionApply" ( dest-cap-nr args-cap-nr -- promise-cap-nr )
0x7006 "methodApply" ( dest-cap-nr verb-cap-nr args-cap-nr -- promise-cap-nr )
0x7007 "getSendOnly" ( dest-cap-nr prop-cap-nr -- )
0x7008 "functionApplySendOnly" ( dest-cap-nr args-cap-nr -- )
0x7009 "methodApplySendOnly" ( dest-cap-nr verb-cap-nr args-cap-nr -- )
0x700F resolved? ( promise-cap-nr -- T | F )
0x7010 make-a-str ( str-addr str-len cap-nr -- )
0x7011 make-a-num ( u cap-nr -- )
0x7012 make-a-arr ( arr-addr arr-len cap-nr -- ) \ arr is an array of cap-nr s
0x7020 get-item-type ( cap-nr -- item-type )
0x0000 empty
0x0001 a ref
0x0002 a num
0x0003 a str
0x0004 a arr
0x7021 get-num ( cap-nr -- u )
0x7022 get-str ( cap-nr str-addr str-max-len -- )
0x7023 get-arr ( cap-nr arr-addr arr-max-len -- )
0x7024 get-len ( cap-nr -- len )
*/
const evFCPU16 = (initState) => {
const { PC, DS, RS, MEM, caps,
rseqBlock, async_switch} = initState;
const NOP_case = rseqBlock~.([
["g", "PC_t0", ["@sba", 0], "PC"],
["g", "DS_t0", ["@sba", 0], "DS"],
["g", "RS_t0", ["@sba", 0], "RS"],
["g", "MEM_t0", ["@sba", 0], "MEM"],
["g", "caps_t0", ["@sba", 0], "caps"],
["returnValue", ["@rec", {
"PC": ["@qid", "PC_t0"],
"DS": ["@qid", "DS_t0"],
"RS": ["@qid", "RS_t0"],
"MEM": ["@qid", "MEM_t0"],
"caps": ["@qid", "caps_t0"]
}]]
]);
const UMP_case = rseqBlock~.([
["g", "PC_t0", ["@sba", 0], "PC"],
["g", "DS_t0", ["@sba", 0], "DS"],
["g", "RS_t0", ["@sba", 0], "RS"],
["g", "MEM_t0", ["@sba", 0], "MEM"],
["g", "caps_t0", ["@sba", 0], "caps"],
["g", "TOS_t0", ["@qid", "DS_t0"], -1],
["g", "NOS_t0", ["@qid", "DS_t0"], -2],
["m", "TOS_t1", ["@qid", "TOS_t0"], "add", ["@arr", ["@qid", "NOS_t0"]]],
["m", "NOS_t1", ["@qid", "TOS_t1"], "modulo", ["@arr", ["@dat", "0x10000"]]],
["m", "TOS_t2", ["@qid", "TOS_t1"], "divide", ["@arr", ["@dat", "0x10000"]]],
["m", "DS_t1", ["@qid", "DS_t0"], "slice", ["@arr", ["@dat", 0], ["@dat", -2]]],
["m", "DS_t2", ["@qid", "DS_t1"], "concat", ["@arr", ["@arr", ["@qid", "NOS_t1"], ["@qid", "TOS_t2"]]]],
["returnValue", ["@rec", {
"PC": ["@qid", "PC_t0"],
"DS": ["@qid", "DS_t2"],
"RS": ["@qid", "RS_t0"],
"MEM":["@qid", "MEM_t0"],
"caps": ["@qid", "caps_t0"]
}]]
]);
const AND_case = rseqBlock~.([
["g", "PC_t0", ["@sba", 0], "PC"],
["g", "DS_t0", ["@sba", 0], "DS"],
["g", "RS_t0", ["@sba", 0], "RS"],
["g", "MEM_t0", ["@sba", 0], "MEM"],
["g", "caps_t0", ["@sba", 0], "caps"],
["g", "TOS_t0", ["@qid", "DS_t0"], -1],
["g", "NOS_t0", ["@qid", "DS_t0"], -2],
["m", "TOS_t1", ["@qid", "TOS_t0"], "bitwiseAnd", ["@arr", ["@qid", "NOS_t0"]]],
["m", "DS_t1", ["@qid", "DS_t0"], "slice", ["@arr", ["@dat", 0], ["@dat", -2]]],
["m", "DS_t2", ["@qid", "DS_t1"], "concat", ["@arr", ["@arr", ["@qid", "TOS_t1"]]]],
["returnValue", ["@rec", {
"PC": ["@qid", "PC_t0"],
"DS": ["@qid", "DS_t2"],
"RS": ["@qid", "RS_t0"],
"MEM": ["@qid", "MEM_t0"],
"caps": ["@qid", "caps_t0"]
}]]
]);
const XOR_case = rseqBlock~.([
["g", "PC_t0", ["@sba", 0], "PC"],
["g", "DS_t0", ["@sba", 0], "DS"],
["g", "RS_t0", ["@sba", 0], "RS"],
["g", "MEM_t0", ["@sba", 0], "MEM"],
["g", "caps_t0", ["@sba", 0], "caps"],
["g", "TOS_t0", ["@qid", "DS_t0"], -1],
["g", "NOS_t0", ["@qid", "DS_t0"], -2],
["m", "TOS_t1", ["@qid", "TOS_t0"], "bitwiseXor", ["@arr", ["@qid", "NOS_t0"]]],
["m", "DS_t1", ["@qid", "DS_t0"], "slice", ["@arr", ["@dat", 0], ["@dat", -2]]],
["m", "DS_t2", ["@qid", "DS_t1"], "concat", ["@arr", ["@arr", ["@qid", "TOS_t1"]]]],
["returnValue", ["@rec", {
"PC": ["@qid", "PC_t0"],
"DS": ["@qid", "DS_t2"],
"RS": ["@qid", "RS_t0"],
"MEM": ["@qid", "MEM_t0"],
"caps": ["@qid", "caps_t0"]
}]]
]);
const OLBR_case = rseqBlock~.([
["g", "PC_t0", ["@sba", 0], "PC"],
["g", "DS_t0", ["@sba", 0], "DS"],
["g", "RS_t0", ["@sba", 0], "RS"],
["g", "MEM_t0", ["@sba", 0], "MEM"],
["g", "caps_t0", ["@sba", 0], "caps"],
["g", "TOS_t0", ["@qid", "DS_t0"], -1],
["m", "TOS_t1", ["@qid", "TOS_t0"], "toBoolArray", ["@arr", ["@dat", 16]]],
["m", "TOS_t2a", ["@qid", "TOS_t1"], "slice", ["@arr", ["@dat", 0], ["@dat", 1]]],
["m", "TOS_t2b", ["@qid", "TOS_t1"], "slice", ["@arr", ["@dat", 1]]],
["m", "TOS_t3", ["@qid", "TOS_t2b"], "concat", ["@arr", ["@qid", "TOS_t2a"]]],
["f", "TOS_t4", ["@ref", awaitOnArgsForMethodThenSend], ["@arr",
["@ref", BigInt], ["@dat", "fromBoolArray"], ["@arr", ["@qid", "TOS_t3"]]]],
["m", "DS_t1", ["@qid", "DS_t0"], "slice", ["@arr", ["@dat", 0], ["@dat", -1]]],
["m", "DS_t2", ["@qid", "DS_t1"], "concat", ["@arr", ["@arr", ["@qid", "TOS_t4"]]]],
["returnValue", ["@rec", {
"PC": ["@qid", "PC_t0"],
"DS": ["@qid", "DS_t2"],
"RS": ["@qid", "RS_t0"],
"MEM": ["@qid", "MEM_t0"],
"caps": ["@qid", "caps_t0"]
}]]
]);
const INCR_case = rseqBlock~.([
["g", "PC_t0", ["@sba", 0], "PC"],
["g", "DS_t0", ["@sba", 0], "DS"],
["g", "RS_t0", ["@sba", 0], "RS"],
["g", "MEM_t0", ["@sba", 0], "MEM"],
["g", "caps_t0", ["@sba", 0], "caps"],
["g", "TOS_t0", ["@qid", "DS_t0"], -1],
["m", "TOS_t1", ["@qid", "TOS_t0"], "add", ["@arr", ["@dat", 1]]],
["m", "TOS_t2", ["@qid", "TOS_t1"], "modulo", ["@arr", ["@dat", "0x10000"]]],
["m", "DS_t1", ["@qid", "DS_t0"], "slice", ["@arr", ["@dat", 0], ["@dat", -1]]],
["m", "DS_t2", ["@qid", "DS_t1"], "concat", ["@arr", ["@arr", ["@qid", "TOS_t2"]]]],
["returnValue", ["@rec", {
"PC": ["@qid", "PC_t0"],
"DS": ["@qid", "DS_t2"],
"RS": ["@qid", "RS_t0"],
"MEM": ["@qid", "MEM_t0"],
"caps": ["@qid", "caps_t0"]
}]]
]);
const FETCH_case = rseqBlock~.([
["g", "PC_t0", ["@sba", 0], "PC"],
["g", "DS_t0", ["@sba", 0], "DS"],
["g", "RS_t0", ["@sba", 0], "RS"],
["g", "MEM_t0", ["@sba", 0], "MEM"],
["g", "caps_t0", ["@sba", 0], "caps"],
["g", "TOS_t0", ["@qid", "DS_t0"], -1],
["m", "TOS_t1", ["@qid", "TOS_t0"], "add", ["@arr", ["@dat", 1]]],
["m", "TOS_t2", ["@qid", "MEM_t0"], "slice", ["@arr", ["@qid", "TOS_t0"], ["@qid", "TOS_t1"]]],
["g", "TOS_t3", ["@qid", "TOS_t2"], 0],
["m", "DS_t1", ["@qid", "DS_t0"], "slice", ["@arr", ["@dat", 0], ["@dat", -1]]],
["m", "DS_t2", ["@qid", "DS_t1"], "concat", ["@arr", ["@arr", ["@qid", "TOS_t3"]]]],
["returnValue", ["@rec", {
"PC": ["@qid", "PC_t0"],
"DS": ["@qid", "DS_t2"],
"RS": ["@qid", "RS_t0"],
"MEM": ["@qid", "MEM_t0"],
"caps": ["@qid", "caps_t0"]
}]]
]);
const STORE_case = rseqBlock~.([
["g", "PC_t0", ["@sba", 0], "PC"],
["g", "DS_t0", ["@sba", 0], "DS"],
["g", "RS_t0", ["@sba", 0], "RS"],
["g", "MEM_t0", ["@sba", 0], "MEM"],
["g", "caps_t0", ["@sba", 0], "caps"],
["g", "TOS_t0", ["@qid", "DS_t0"], -1],
["g", "NOS_t0", ["@qid", "DS_t0"], -2],
["m", "TOS_t1", ["@qid", "TOS_t0"], "add", ["@arr", ["@dat", 1]]],
["m", "MEM_t1a", ["@qid", "MEM_t0"], "slice", ["@arr", ["@dat", 0], ["@qid", "TOS_t0"]]],
["m", "MEM_t1b", ["@qid", "MEM_t0"], "slice", ["@arr", ["@qid", "TOS_t1"]]],
["m", "MEM_t2", ["@qid", "MEM_t1a"], "concat", ["@arr", ["@arr", ["@qid", "NOS_t0"]], ["@qid", "MEM_t1b"]]],
["m", "DS_t1", ["@qid", "DS_t0"], "slice", ["@arr", ["@dat", 0], ["@dat", -2]]],
["returnValue", ["@rec", {
"PC": ["@qid", "PC_t0"],
"DS": ["@qid", "DS_t1"],
"RS": ["@qid", "RS_t0"],
"MEM": ["@qid", "MEM_t2"],
"caps": ["@qid", "caps_t0"]
}]]
]);
const DUP_case = rseqBlock~.([
["g", "PC_t0", ["@sba", 0], "PC"],
["g", "DS_t0", ["@sba", 0], "DS"],
["g", "RS_t0", ["@sba", 0], "RS"],
["g", "MEM_t0", ["@sba", 0], "MEM"],
["g", "caps_t0", ["@sba", 0], "caps"],
["g", "TOS_t0", ["@qid", "DS_t0"], -1],
["m", "DS_t1", ["@qid", "DS_t0"], "concat", ["@arr", ["@arr", ["@qid", "TOS_t0"]]]],
["returnValue", ["@rec", {
"PC": ["@qid", "PC_t0"],
"DS": ["@qid", "DS_t1"],
"RS": ["@qid", "RS_t0"],
"MEM": ["@qid", "MEM_t0"],
"caps": ["@qid", "caps_t0"]
}]]
]);
const DROP_case = rseqBlock~.([
["g", "PC_t0", ["@sba", 0], "PC"],
["g", "DS_t0", ["@sba", 0], "DS"],
["g", "RS_t0", ["@sba", 0], "RS"],
["g", "MEM_t0", ["@sba", 0], "MEM"],
["g", "caps_t0", ["@sba", 0], "caps"],
["m", "DS_t1", ["@qid", "DS_t0"], "slice", ["@arr", ["@dat", 0], ["@dat", -1]]],
["returnValue", ["@rec", {
"PC": ["@qid", "PC_t0"],
"DS": ["@qid", "DS_t1"],
"RS": ["@qid", "RS_t0"],
"MEM": ["@qid", "MEM_t0"],
"caps": ["@qid", "caps_t0"]
}]]
]);
const SWAP_case = rseqBlock~.([
["g", "PC_t0", ["@sba", 0], "PC"],
["g", "DS_t0", ["@sba", 0], "DS"],
["g", "RS_t0", ["@sba", 0], "RS"],
["g", "MEM_t0", ["@sba", 0], "MEM"],
["g", "caps_t0", ["@sba", 0], "caps"],
["g", "TOS_t0", ["@qid", "DS_t0"], -1],
["g", "NOS_t0", ["@qid", "DS_t0"], -2],
["m", "DS_t1", ["@qid", "DS_t0"], "slice", ["@arr", ["@dat", 0], ["@dat", -2]]],
["m", "DS_t2", ["@qid", "DS_t1"], "concat", ["@arr", ["@arr", ["@qid", "TOS_t0"], ["@qid", "NOS_t0"]]]],
["returnValue", ["@rec", {
"PC": ["@qid", "PC_t0"],
"DS": ["@qid", "DS_t2"],
"RS": ["@qid", "RS_t0"],
"MEM":["@qid", "MEM_t0"],
"caps": ["@qid", "caps_t0"]
}]]
]);
const SKZ_case = rseqBlock~.([
["g", "PC_t0", ["@sba", 0], "PC"],
["g", "DS_t0", ["@sba", 0], "DS"],
["g", "RS_t0", ["@sba", 0], "RS"],
["g", "MEM_t0", ["@sba", 0], "MEM"],
["g", "caps_t0", ["@sba", 0], "caps"],
["g", "TOS_t0", ["@qid", "DS_t0"], -1],
["m", "PC_t1", ["@qid", "PC_t0"], "add", ["@arr", ["@dat", 1]]],
["m", "PC_t2", ["@qid", "PC_t1"], "modulo", ["@arr", ["@dat", "0x10000"]]],
["m", "TOS_t1", ["@qid", "TOS_t0"], "isZero", ["@arr"]],
["m", "PC_t3", ["@qid", "TOS_t1"], "pick", ["@arr", ["@qid", "PC_t2"], ["@qid", "PC_t0"]]],
["m", "DS_t1", ["@qid", "DS_t0"], "slice", ["@arr", ["@dat", 0], ["@dat", -1]]],
["returnValue", ["@rec", {
"PC": ["@qid", "PC_t3"],
"DS": ["@qid", "DS_t1"],
"RS": ["@qid", "RS_t0"],
"MEM": ["@qid", "MEM_t0"],
"caps": ["@qid", "caps_t0"]
}]]
]);
const TO_R_case = rseqBlock~.([
["g", "PC_t0", ["@sba", 0], "PC"],
["g", "DS_t0", ["@sba", 0], "DS"],
["g", "RS_t0", ["@sba", 0], "RS"],
["g", "MEM_t0", ["@sba", 0], "MEM"],
["g", "caps_t0", ["@sba", 0], "caps"],
["g", "TOS_t0", ["@qid", "DS_t0"], -1],
["m", "DS_t1", ["@qid", "DS_t0"], "slice", ["@arr", ["@dat", 0], ["@dat", -1]]],
["m", "RS_t1", ["@qid", "RS_t0"], "concat", ["@arr", ["@arr", ["@qid", "TOS_t0"]]]],
["returnValue", ["@rec", {
"PC": ["@qid", "PC_t0"],
"DS": ["@qid", "DS_t1"],
"RS": ["@qid", "RS_t1"],
"MEM":["@qid", "MEM_t0"],
"caps": ["@qid", "caps_t0"]
}]]
]);
const R_FROM_case = rseqBlock~.([
["g", "PC_t0", ["@sba", 0], "PC"],
["g", "DS_t0", ["@sba", 0], "DS"],
["g", "RS_t0", ["@sba", 0], "RS"],
["g", "MEM_t0", ["@sba", 0], "MEM"],
["g", "caps_t0", ["@sba", 0], "caps"],
["g", "TOS_t0", ["@qid", "RS_t0"], -1],
["m", "RS_t1", ["@qid", "RS_t0"], "slice", ["@arr", ["@dat", 0], ["@dat", -1]]],
["m", "DS_t1", ["@qid", "DS_t0"], "concat", ["@arr", ["@arr", ["@qid", "TOS_t0"]]]],
["returnValue", ["@rec", {
"PC": ["@qid", "PC_t0"],
"DS": ["@qid", "DS_t1"],
"RS": ["@qid", "RS_t1"],
"MEM":["@qid", "MEM_t0"],
"caps": ["@qid", "caps_t0"]
}]]
]);
const EXIT_case = rseqBlock~.([
["g", "DS_t0", ["@sba", 0], "DS"],
["g", "RS_t0", ["@sba", 0], "RS"],
["g", "MEM_t0", ["@sba", 0], "MEM"],
["g", "caps_t0", ["@sba", 0], "caps"],
["g", "PC_t1", ["@qid", "RS_t0"], -1],
["m", "RS_t1", ["@qid", "RS_t0"], "slice", ["@arr", ["@dat", 0], ["@dat", -1]]],
["returnValue", ["@rec", {
"PC": ["@qid", "PC_t1"],
"DS": ["@qid", "DS_t0"],
"RS": ["@qid", "RS_t1"],
"MEM":["@qid", "MEM_t0"],
"caps": ["@qid", "caps_t0"]
}]]
]);
const call_case = rseqBlock~.([
["g", "PC_t0", ["@sba", 0], "PC"],
["g", "DS_t0", ["@sba", 0], "DS"],
["g", "RS_t0", ["@sba", 0], "RS"],
["g", "MEM_t0", ["@sba", 0], "MEM"],
["g", "caps_t0", ["@sba", 0], "caps"],
["g", "PC_t1", ["@sba", 0], "INSTR"],
["m", "RS_t1", ["@qid", "RS_t0"], "concat", ["@arr", ["@arr", ["@qid", "PC_t0"]]]],
["returnValue", ["@rec", {
"PC": ["@qid", "PC_t1"],
"DS": ["@qid", "DS_t0"],
"RS": ["@qid", "RS_t1"],
"MEM":["@qid", "MEM_t0"],
"caps": ["@qid", "caps_t0"]
}]]
]);
const EXT_case = rseqBlock~.([
["g", "PC_t0", ["@sba", 0], "PC"],
["g", "DS_t0", ["@sba", 0], "DS"],
["g", "RS_t0", ["@sba", 0], "RS"],
["g", "MEM_t0", ["@sba", 0], "MEM"],
["g", "caps_t0", ["@sba", 0], "caps"],
["g", "EXT_nr", ["@qid", "DS_t0"], -1],
["m", "DS_t1", ["@qid", "DS_t0"], "slice", ["@arr", ["@dat", 0], ["@dat", -1]]],
["a", "state", ["@rec", {
"PC": ["@qid", "PC_t0"],
"DS": ["@qid", "DS_t1"],
"RS": ["@qid", "RS_t0"],
"MEM": ["@qid", "MEM_t0"],
"caps": ["@qid", "caps_t0"]
}]],
["f", "result", ["@ref", async_switch], ["@arr", ["@qid", "EXT_nr"],
["@arr",
["@arr", "case", "0x7000", [], []],
["@arr", "case", "0x7001", [], []],
["@arr", "case", "0x7002", [], []],
["@arr", "case", "0x7003", [], []],
["@arr", "case", "0x7004", [], []],
["@arr", "case", "0x7005", [], []],
["@arr", "case", "0x7006", [], []],
["@arr", "case", "0x7007", [], []],
["@arr", "case", "0x7008", [], []],
["@arr", "case", "0x7009", [], []],
["@arr", "case", "0x700F", [], []],
["@arr", "case", "0x7010", [], []],
["@arr", "case", "0x7011", [], []],
["@arr", "case", "0x7012", [], []],
["@arr", "case", "0x7020", [], []],
["@arr", "case", "0x7021", [], []],
["@arr", "case", "0x7022", [], []],
["@arr", "case", "0x7023", [], []],
["@arr", "case", "0x7024", [], []]
]]
]]
]);
const doInstr = rseqBlock~.([
["g", "PC_t0", ["@sba", 0], "PC"],
["g", "DS_t0", ["@sba", 0], "DS"],
["g", "RS_t0", ["@sba", 0], "RS"],
["g", "MEM_t0", ["@sba", 0], "MEM"],
["g", "caps_t0", ["@sba", 0], "caps"],
["g", "INSTR", ["@qid", "MEM_t0"], ["@qid", "PC_t0"]],
["m", "PC_t1", ["@qid", "PC_t0"], "add", ["@arr", ["@dat", "1"]]],
["m", "PC_t2", ["@qid", "PC_t1"], "modulo", ["@arr", ["@dat", "0x10000"]]],
["a", "state", ["@rec", {
"PC": ["@qid", "PC_t2"],
"DS": ["@qid", "DS_t0"],
"RS": ["@qid", "RS_t0"],
"MEM": ["@qid", "MEM_t0"],
"caps": ["@qid", "caps_t0"],
"INSTR": ["@qid", "INSTR"]
}]],
["f", "resultOfStep", ["@ref", async_switch], ["@arr", ["@qid", "INSTR"],
["@arr",
["@arr", "case", "0x0000", ["@ref", NOP_case], ["@qid", "state"]],
["@arr", "case", "0x0001", ["@ref", UMP_case], ["@qid", "state"]],
["@arr", "case", "0x0002", ["@ref", AND_case], ["@qid", "state"]],
["@arr", "case", "0x0003", ["@ref", XOR_case], ["@qid", "state"]],
["@arr", "case", "0x0004", ["@ref", OLBR_case], ["@qid", "state"]],
["@arr", "case", "0x0005", ["@ref", INCR_case], ["@qid", "state"]],
["@arr", "case", "0x0006", ["@ref", FETCH_case], ["@qid", "state"]],
["@arr", "case", "0x0007", ["@ref", STORE_case], ["@qid", "state"]],
["@arr", "case", "0x0008", ["@ref", DUP_case], ["@qid", "state"]],
["@arr", "case", "0x0009", ["@ref", DROP_case], ["@qid", "state"]],
["@arr", "case", "0x000A", ["@ref", SWAP_case], ["@qid", "state"]],
["@arr", "case", "0x000B", ["@ref", SKZ_case], ["@qid", "state"]],
["@arr", "case", "0x000C", ["@ref", TO_R_case], ["@qid", "state"]],
["@arr", "case", "0x000D", ["@ref", R_FROM_case], ["@qid", "state"]],
["@arr", "case", "0x000E", ["@ref", EXT_case], ["@qid", "state"]],
["@arr", "case", "0x000F", ["@ref", EXIT_case], ["@qid", "state"]],
["@arr", "default", ["@ref", call_case], ["@qid", "state"]]
]]
]);
}
//
/*
a b | s c a b ci | s co
0 0 0 0 0 0 0 0 0
0 1 1 0 0 1 0 1 0
1 0 1 0 1 0 0 1 0
1 1 0 1 1 1 0 0 1
0 0 1 1 0
0 1 1 0 1
1 0 1 0 1
1 1 1 1 1
*/
const async_halfAdd = (a, b, remoteSeq, remoteAsyncAND, remoteAsyncXOR) => {
return (remoteSeq~.([
["f", "sum", ["@ref", remoteAsyncXOR], ["@arr", ["@sba", 0], ["@sba", 1]]],
["f", "car", ["@ref", remoteAsyncAND], ["@arr", ["@sba", 0], ["@sba", 1]]],
["returnValue", ["@arr", ["@qid", "sum"], ["@qid", "car"]]]
]))~.(a, b);
}
const async_fullAdd = (a, b, c, remoteSeq, remoteAnd, remoteXor, remoteOr) => {
}
const async_add = (a, b, remoteSeq) => {
return (remoteSeq~.([
["m", "aExpanded", ["@sba", 0], "toBoolArray", ["@arr"]],
["m", "bExpanded", ["@sba", 1], "toBoolArray", ["@arr"]],
["g", "a0", ["@qid", "aExpanded"], 0],
["g", "b0", ["@qid", "bExpanded"], 0],
])~.(a, b);
}
//
CapCert A, issued&signed by VatA, targets VatA:
const q1 = NonceLocator.acceptFrom(«VatID of VatA»,
«nonce for AliceBucksIssuer»,
null);
NonceLocator.provideFor(«VatID of VatA»,
«nonce for AliceBucksIssuer», q1);
NonceLocator.provideFor(«allCommers»,
«nonce for AliceBucksIssuer», q1);
CapCert B, issued&signed by VatB, targets VatA:
CapCert(«CapCert A»);
const q2 = AllCommersNonceLocator.acceptFrom(
«VatID of VatA», «nonce for AliceBucksIssuer», null);
const q3 = NonceLocator.acceptFrom(«VatID of VatC»,
«nonce for a payment from Carol», null);
const q4 = q2.claim(q3);
NonceLocator.provideFor(«VatID of VatB», «yetAnotherNonce», q4);
CapCert C, issued&signed by VatB, targets VatA:
CapCert(«CapCert B»);
CapCert(«CapCert A»);
const q5 = AllCommersNonceLocator.acceptFrom(
«VatID of VatA», «nonce of AliceBucksIssuer», null);
const q6 = NonceLocator.acceptFrom(«VatID of VatB»,
«yetAnotherNonce», null);
const q7 = () => { return q5.isLive(q6); };
NonceLocator.provideFor(«allCommers», «isLiveNonce», q7);
CapCert example C
const storage = Noncer~.acceptFrom(«hostVatId», «storageNonce»);
const BLAKE3 = Noncer~.acceptFrom();
const AESGCM = Noncer~.acceptFrom();
const tmp0 = BLAKE3~.(sba[0]);
const tmp1 = tmp0~.equal(«expectedHash»);
const tmp2 = tmp1~.pick(«cipheredPayload», "");
const tmp3 = AESGCM~.decrypt(tmp2);
CapCert CashierCheque example #1,
targets Zey Bank Vat signed by same:
const q10 = NonceLocator~.acceptFrom(
«VatID of ZBV», «nonce for SingleUseToken payment»);
const q11 = NonceLocator~.acceptFrom(
«VatID of ZBV», «nonce for SingleUseToken Issuer»);
NonceLocator~.provideFor(
«VatID of ZBV», «nonce for SingleUseToken Issuer», q11);
const q12 = NonceLocator~.acceptFrom(
«VatID of ZBV», «nonce for seqBlock»);
NonceLocator~.provideFor(
«VatID of ZBV», «nonce for seqBlock», q12);
const q13 = q11~.isLive(q10);
const q14 = q12~.([
["m", "t1", ["@sba", 1], "make", ["@arr", ["@dat", 50000]]],
["m", "t2", ["@sba", 2], "claim", ["@arr", ["@sba", 3]]],
["m", "t3", ["@sba", 0], "withdraw", ["@arr", ["@qid", "t1"]]]
, ["rv", ["@qid", "t3"]]
]);
const q15 = q12~.([
["returnValue", ["@hpr", ["@sqb", [
["fso", ["@sba", 1], ["@arr", ["@dat", "cheque already spent or canceled"]]]
]]]]
]);
const q16 = q13~.pick(q14, q15);
const q17 = NonceLocator~.acceptFrom(
«VatID of ZBV», «nonce for Purse of moola»);
NonceLocator~.provideFor(
«VatID of ZBV», «nonce for Cashier Purse of moola», q17);
const q18 = «moola issuer»
const q19 = q18~.getAmountMath();
const q20 = q16~.apply([q17, q19, q11, q10]);
return q20;
CapCert, Cashier cheque #2, signed by Zey Bank Vat,
targets any bank vat
const sui = Noncer~.acceptFrom(«ZBV vatId», «nonce for SingleUseIssuer»);
Noncer~.provideFor(«ZBV vatId», «nonce for SingleUseIssuer», sui);
const sup = Noncer~.acceptFrom(«ZBV vatId», «uuid of payment»);
Noncer~.provideFor(«ZBV vatId», «uuid of payment», sup);
const k1 = sui~.isLive(sup);
const k2 = seqBlock(«
const k2_sup = sba(0);
const k2_sui = sba(1);
const k2_1 = k2_sui~.burn(k2_sui);
const k2_2 = [[«bank0 vatId», «CapCert sui burner»], «...«»];
const k2_3 = seqBlock~,(«
// sem núllar út, það par sem fyrri liður er jafnt og localVatId
»);
const k2_4 = seqBlock sem notar PostMaster til að pósta ónúlluð par seinni lið
»);
const k3 = seqBlock(«»);
const k4 = k1~.pick(k2, k3);
const k5 = Noncer~.getLocalVatId();
const k6 = Noncer~.acceptFrom(«ZBV vatId», «nonce for PostMaster»);
Noncer~.provideFor(«ZBV vatId», «nonce for PostMaster», k6);
const k8 = k4~.(sup, sui, k5, k6, k7);
return k8;
const makeCashierCheque = (opts) => {
return makeCapCert(opts.stringify([
["assignOnce", "einnotaNrA", ["@dat", opts.singleUseUUIDa]],
["assignOnce", "einnotaNrB", ["@dat", opts.singleUseUUIDb]],
["assignOnce", "einnotaIss", ["@dat", opts.singleUseIssuerNonce]],
["assignOnce", "noncer", ["@sqb", [
["assignOnce", "cashierBank", ["@dat", opts.signingKey.publicKey]],
["methodApply", "n",
["@outer", "@outer", "@qid", "Noncer"],
"acceptFrom",
["@arr", ["@qid", "cashierBank"], ["@sba", 0]]],
["methodApplySendOnly",
["@outer", "@qid", "Noncer"],
"provideFor",
["@arr", ["@qid", "cashierBank"], ["@sba", 0], ["@qid", "n"]]],
["returnValue", ["@qid", "n"]]
]]],
["functionApply", "sui", ["@qid", "noncer"],
["methodApply", "sup", ["@outer", "@qid", "Noncer"], "acceptFrom", ["@arr", ["@qid", "cashierBank"], ["@qid", "einnoraNrA"]]],
["methodApply", "q1", ["@qid", "sui"], "isLive", ["@arr", ["@qid", "sup"]]],
["methodApply", "q2", ["@qid", "q1"], "pick", ["@arr",
["@sqb", [
["methodApply", "t1", ["@outer", "@qid", "sui"], "claim", ["@arr", ["@outer", "@qid", "sup"]]],
["methodApplySendOnly", ["@outer", "@outer", "@qid", "Noncer"], "provideFor", ["@arr", ["@outer", "@qid", "cashierBank"], ["@outer", "@qid", "einnotaNrB"], ["@qid", "t1"]]],
["methodApply", "t2", ["@outer", "@outer", "Noncer"], "getLocalVatId", ["@arr"]],
["assignOnce", "t3", ["@arr"].concat(opts.corrispondingBanks.map((bankVatId) => {
const cert = makeCapCert(opts.stringify([
["assignOnce", "c1", ["@dat", opts.signingKey.publicKey]],
["assignOnce", "c2", ["@dat", opts.singleUseIssuerNonce]],
["methodApply", "c3", ["@outer", "@qid", "Noncer"], "acceptFrom", ["@arr", ["@qid", "c1"], ["@qid", "c2"]]],
["methodApplySendOnly", ["@outer", "@qid", "Noncer"], "provideFor", ["@arr", ["@qid", "c1"], ["@qid", "c2"], ["@qid", "c3"]]],
["methodApply", "c4", ["@outer", "@qid", "Noncer"], "acceptFrom", ["@arr", ["@qid", "c1"], ["@dat", opts.singleUseUUIDa]]],
["methodApply", "c5", ["@qid", "c3"], "claim", ["@arr", ["@qid", "c4"]]],
["methodApplySendOnly", ["@outer", "@qid", "Noncer"], "provideFor", ["@arr", ["@qid", "c1"], ["@dat", opts.singleUseUUIDb], ["@qid", "c5"]]],
["returnValue", ["@dat", true]]
]), opts.signingKey);
return ["@arr", ["@dat", bankVatId], ["@dat", cert]];
}))],
["methodApply", "t4", ["@outer", "@outer", "@qid", "Noncer"], "acceptFrom", ["@arr", ["@outer", "@qid", "cashierBank"], ["@dat", opts.PostMasterNonce]]],
["methodApplySendOnly", ["@outer", "@qid", "Noncer"], "provideFor", ["@arr", ["@outer", "@qid", "cashierBank"], ["@dat", opts.PostMasterNonce], ["@qid", "t4"]]],
["methodApplySendOnly", ["@qid", "t3"], "forEach",
["@arr", ["@sqb", [
["get", "t4_1", ["@sba", 0], ["@dat", 0]],
["methodApply", "t4_2", ["@outer", "@outer", "@outer", "@qid", "Noncer"], "areVatIDsEqual", ["@arr", ["@outer", "@qid", "t2"], ["@qid", "t4_1"]]],
["methodApply", "t4_3", ["@qid", "t4_2"], "pick", ["@arr", ["@sqb", []], ["@sqb", [
["methodApplySendOnly", ["@outer", "@outer", "@qid", "t4"], "post", ["@arr", ["@sba", 0]]]
]]],
["get", "t4_4", ["@sba", 0], ["@dat", 1]],
["functionApplySendOnly", ["@qid", "t4_3"], ["@arr", ["@qid", "t4_4"]]]
]]]],
["methodApply", "t5", ["@outer", "@outer", "@qid", "Noncer"], "acceptFrom", ["@arr", ["@qid", "cashierBank"], ["@dat", opts.currencyIssuerNonce]]],
["methodApplySendOnly", ["@outer", "@outer", "@qid", "Noncer"], "provideFor", ["@arr", ["@qid", "cashierBank"], ["@dat", opts.currencyIssuerNonce], ["@qid", "t5"]]],
["methodApply", "t6", ["@qid", "t5"], "getAmountMath", ["@arr"]],
["methodApply", "t7", ["@qid", "t6"], "make", ["@arr", ["@dat", opts.amount]]],
["methodApply", "t8", ["@outer", "@outer", "@qid", "Noncer"], "acceptFrom xxx
]],
["@sqb", []]
]],
["functionApply", "q3", ["@qid", "q2"], ["@arr"]],
["returnValue", ["@qid", "q3"]]
]), opts.signingKey);
}
const makeStore = (keyname, inp = []) => {
return new Map(inp);
}
const makeNonceLocatorMaker = (serializerSealer, g = null, w = null) => {
const gifts = (g === null) ? makeStore() : g ;
const wants = (w === null) ? makeStore() : w ;
return harden({
make: (myVatID) => {
const myGifts = makeStore(); // my gifts to others
const myWants = makeStore(); // my wants of others
gifts.init(myVatID, myGifts);
wants.init(myVatID, myWants);
return harden({
provideFor: (recipiantVatID, nonce, gift) => {
const vine = undefined;
if (wants.has(recipiantVatID)) {
const t1 = wants.get(recipiantVatID);
if (t1.has(myVatID)) {
const t2 = t1.get(myVatID);
if (t2.has(nonce)) {
t2.get(nonce).resolve(gift);
t2.delete(nonce);
if (t2.isEmpty()) {
t1.delete(myVatID);
}
return vine;
}
}
}
if (!myGifts.has(recipiantVatID)) {
myGifts.init(recipiantVatID, makeStore()); }
myGifts.get(recipiantVatID).init(nonce, gift);
return vine;
},
acceptFrom: (giverVatID, nonce, vine = null) => {
if (gifts.has(giverVatID) {
const t1 = gifts.get(giverVatID);
if (t1.has(myVatID)) {
const t2 = t1.get(myVatID);
if (t2.has(nonce)) {
const r = Promise.resolve(t2.get(nonce));
t2.delete(nonce);
if (t2.isEmpty()) {
t1.delete(myVatID);
}
return r;
}
}
}
return new Promise((resolve, reject) => {
const resolver = harden({ resolve, reject });
if (!myWants.has(giverVatID)) {
myWants.init(giverVatID, makeStore()); }
myWants.get(giverVatID).init(nonce, resolver);
});
}
});
},
__sealedDispatch: (sealer) => {
if (sealer === serializerSealer) {
const makeStorePortraid = (st) => {
return {"$call":[makeStore, "apply", [st.entries().map(
(item) => {
const [key, val] = item;
if ((typeof val) == "object") &&
(val instanceof Map)) {
return [key, makeStorePortraid(val)];
} else {
return item;
}
})]]};
}
const giftsPort = makeStorePortraid(gifts);
const wantsPort = makeStorePortraid(wants);
return serializerSealer.seal(
{"$call":[makeNonceLocatorMaker, "apply", [
serializerSealer, giftsPort, wantsPort]]});
}
}});
}
const makeSealerUnsealer = (brandName) => {
const boxes = new WeakMap();
const sealer = {};
sealer.seal = (item) => {
const box = harden({});
boxes.set(box, item);
return box;
};
const unsealer = {};
unsealer.unseal = (box) => boxes.get(box);
return harden({ sealer, unsealer });
}
co
const getNoncer = (() => {
const maker = makeNonceLocatorMaker(serializerSealer);
const noncers = new WeakMap();
return harden((vatId) => {
if (!noncers.has(vatId)) {
noncers.set(vatId, maker.make(vatId));
}
return noncers.get(vatId);
});
})();
const ActiveCapCert = async (certificate) => {
const { signer, body } = await verifyCert(certificate);
const noncer = getNoncer(signer);
const c = seqBlock(JSON_fullRevive(JSON.parse(body)), {
outer: (idx) => {
if (idx[0] === "@qid") {
if (idx[1] === "Noncer") { return noncer; }
if (idx[1] === "ActiveCapCert") { return ActiveCapCert; }
}
throw new Error("no such noun in outermost env of an ACC");
}
});
c.toJSON = () => { return {"$call":[{"$exit":"ActiveCapCert"}, "apply", [null, certificate]]} };
return c;
}
const PostMaster = (() => {
return harden({
makePostalRef: (givingVatId, nonce, mySigningPrivKey) => {
const letter = []; // .diverge();
letter.push(["m", "q0", ["@outer", "@qid", "Noncer"], "acceptFrom", ["@arr", ["@dat", givingVatId], ["@dat", nonce], ["@dat", null]]]);
var qidCounter = 0;
const makeQid = () => { return "q".concat(qidCounter++); };
const qidSeen = new Map();
const makeI = (specimen) => {
if (qidSeen.has(specimen)) {
return ["@qid", qidSeen.get(specimen)];
}
if (specimen instanceof Array) {
return ["@arr"].concat(specimen.map(makeI));
}
if (((typeof specimen) == "string") ||
((typeof specimen) == "number")) {
return ["@dat", specimen];
}
// xxx: to be filled in
};
const makeRef = (targetId) => {
const executor = (resolve, reject, resolveWithPresence) => {
// Proxy?
const presence = harden({
then: (resBack, errBack) => {},
catch: (errBack) => {},
finally: (doneBack) => {},
there: (migrantFunc) => {}
});
return resolveWithPresence(presence);
};
const handler = {
eventualGet: (target, prop) => {
const qid = makeQid();
letter.push(["get", qid, ["@qid", targetId], prop]);
return makeRef(qid);
},
eventualGetOnly: (target, prop) => {
letter.push(["getSendOnly", ["@qid", targetId], prob]);
void;
},
eventualSet: (target, prop, newVal) => {
void handler.eventualSetOnly(target, prob, newVal);
return newVal;
},
eventualSetOnly: (target, prob, newVal) => {
letter.push(["set", ["@qid", targetId], prob, makeI(newVal)]]);
void;
},
eventualApply: (target, args) => {
const qid = makeQid();
letter.push(["functionApply", qid, ["@qid", targetId], makeI(args)]);
return makeRef(qid);
},
eventualApplyOnly: (target, args) => {
letter.push(["functionApplySendOnly", ["@qid", targetId], makeI(args)]);
void;
},
eventualSend: (target, prop, args) => {
const qid = makeQid();
letter.push(["methodApply", qid, ["@qid", targetId], prob, makeI(args)]);
return makeRef(qid);
},
eventualSendOnly: (target, prop, args) => {
letter.push(["methofApplySendOnly", ["@qid", targetId], prob, makeI(args)]);
void;
}
};
const p = Promise.delegate(executor, handler);
qidSeen.set(p, targetId);
return p;
};
const ref = makeRef("q".concat(0));
const envelope = harden({
addFunctionApplication: (target, args) => {
},
addMethodApplication: (target, verb, args) => {
}
getSignedLetter: () => {
}
});
return { ref, envelope };
}
});
})();
const agoric_related = (() => {
const harden = (item) => { return item };
// identity function for now
const Array__unique = (arr) => {
return arr.reduce((acc, item) => {
if (!acc.includes(item)) { acc.push(item); }
return acc; }, []);
}
const exported = {};
exported.makeTimerService = (ticker) => {
var counter = 0n;
const handlers = [];
const timeSort = (a, b) => {
if (a.time < b.time) { return -1; }
if (a.time == b.time) { return 0; }
if (a.time > b.time) { return 1; }
}
ticker(() => {
handlers.forEach((item, idx) => {
if (item.time <= counter) {
item.handler~.wake(counter);
handlers[idx] = undefined;
}
});
counter = counter + 1n;
});
const ts = harden({
getCurrentTimestamp: () => counter,
setWakeup: (baseTime, handler) => {
handlers.push({time: baseTime, handler});
handlers.sort(timeSort);
return baseTime;
},
removeWakeup: (handler) => {
const times = [];
handlers.forEach((item, idx) => {
if (item == undefined) { return; }
if (item.handler === handler) {
times.push(item.time);
handlers[idx] = undefined;
}
});
return harden(times);
},
createRepeater: (delay, interval) => {
const myHandlers = [];
const myHandler = { wake: (time) => {
myHandlers.forEach((item) => item~.wake(time));
if (myHandlers.size != 0) {
ts.setWakeup(time + interval, myHandler);
}
} };
ts.setWakeup(ts.getCurrentTimestamp() + delay, myHandler);
return harden({
schedule: (handler) => {
myHandlers.push(handler);
return 1;
},
disable: () => {
myHandlers.clear();
}
});
}
});
return ts;
}
exported.produceIssuer = (allegedName, mathHelperName) => {
// soul state -begin-
const pursesAmount = new Map();
const paymentsAmount = new Map();
// soul state -end-
const makePurse = () => {
const purse = harden({
"getIssuer": () => { return issuer; },
"getCurrentAmount": () => {
return pursesAmount.get(purse);
},
"deposit": (payment, optAmount) => {
return paymentAmount;
},
"withdraw": (amount) => {
return newPayment;
},
getDepositFacet: () => depositFacet
});
const depositFacet = harden({
receive: purse.deposit,
getIssuer: purse.getIssuer
})
const zeroAmount = amountMath.getEmpty();
pursesAmount.set(purse, zeroAmount);
return purse;
};
const makePayment = (amount) => {
const payment = harden({
"getAllegedBrand": () => { return brand; }
});
paymentsAmount.set(payment, amount);
return payment;
}
const mint = harden({
"getIssuer": () => { return issuer; },
"mintPayment": (newAmount) => {
return makePayment(newAmount);
}
});
const issuer = harden({
"getBrand": () => { return brand; },
"getAllegedName": () => { return allegedName; },
"getAmountMath": () => { return amountMath; },
"getMathHelpersName": () => { return mathHelpersName; },
"makeEmptyPurse": () => {
// make a Purse
return makePurse();
},
"getAmountOf": (payment) => {
// payment is Payment
// return its Amount
if (paymentsAmount.has(payment)) {
const amount = paymentsAmount.get(payment);
return amount;
} else {
throw notAPaymentOfOurBrand(payment);
}
},
"burn": async (payment, optAmount = undefined) => {
// if optAmount !== undefined then insist
// the amount of the payment is equal
// return the Amount that was burned
[payment] = await Promise.allSettled([payment]);
if (!paymentsAmount.has(payment)) {
throw notAPaymentOfOurBrand(payment);
}
const amount = paymentsAmount.get(payment);
if (optAmount === undefined) { optAmount = amount; }
if (!amountMath.isEqual(amount, optAmount)) {
throw paymentAmountIsUnequal(amount, optAmount);
}
paymentsAmount.delete(payment);
return amount;
},
"claim": async (payment, optAmount = undefined) => {
// burns the payment and makes a new one of same amount
const amount = await issuer.burn(payment, optAmount);
return makePayment(amount);
},
"combine": (paymentsArray, optTotalAmount = undefined) => {
paymentsArray = Array.from(paymentsArray);
paymentsArray = await Promise.allSettled(paymentsArray);
paymentsArray = Array__unique(paymentsArray);
var runningTotal = amountMath.getEmpty();
paymentsArray.forEach((item) => {
if (!paymentsAmount.has(item)) {
throw notAPaymentOfOurBrand(item);
}
const amount = paymentsAmount.get(item);
runningTotal = amountMath.add(runningTotal, amount);
});
if (optTotalAmount === undefined) {
optTotalAmount = runningTotal;
}
if (!amountMath.isEqual(runningTotal, optTotalAmount)) {
throw paymentAmountIsUnEqual(runningTotal, optTotalAmount);
}
// Bonfire! Bál!
paymentsArray.forEach(issuer.burn);
return makePayment(runningTotal);
},
"split": (payment, paymentAmountA) => {
[payment] = await Promise.allSettled([payment]);
if (!paymentsAmount.has(payment)) {
throw notAPaymentOfOurBrand(payment);
}
const oldAmount = paymentsAmount.get(payment);
if (!amountMath.isGTE(oldAmount, paymentAmountA)) {
throw insufficientAmount(oldAmount, paymentAmountA);
}
const paymentAmountB = amountMath.subtract(oldAmount, paymentAmountA);
issuer.burn(payment);
const newPaymentA = makePayment(paymentAmountA);
const newPaymentB = makePayment(paymentAmountB);
return [newPaymentA, newPaymentB];
},
"splitMany": (payment, amountsArray) => {
[payment] = await Promise.allSettled([payment]);
amountsArray = await Promise.allSettled(amountsArray);
const amount = issuer.getAmountOf(payment);
const total = amountsArray.reduce((acc, item) => {
return amountMath.add(acc, item);
}, amountMath.getEmpty()};
if (!amountMath.isEqual(amount, total)) {
throw new Error("tbi");
}
issuer.burn(payment);
return amountsArray.map(makePayment);
},
"isLive": (payment) => {
// returns a Boolean
return paymentsAmount.has(payment);
}
});
const brandsAreEqual = (brandA, brandB) => {
// uncall portrayal comparison
const a = brandA.toJSON();
const b = brandB.toJSON();
return ((a["$call"][2][0] == b["$call"][2][0]) &&
(a["$call"][2][1] == b["$call"][2][1]));
};
// guards:
const Nat = (specimen) => {
const upchuck = () => {
throw new Error("Nat Guard did not pass specimen");
}
if ((typeof(specimen) != "bigint") &&
(typeof(specimen) != "number")) { upchuck(); }
if ((typeof(specimen) == "number") &&
(!Number.isSafeInteger(specimen))) { upchuck(); }
return specimen;
}
const ArrayOfOnly = (guard) => {
const upchuck = () => {
throw new Error("ArrayOfOnly guard did not pass specimen");
}
return (specimen) => {
if (!Array.isArray(specimen)) { upchuck(); }
return specimen.map(guard);
};
};
const PairOf = (lGuard, rGuard) => {
const upchuck = () => {
throw new Error("PairOf guard didnt pass specimen");
}
return (specimen) => {r
if (!Array.isArray(specimen)) { upchuck(); }
if (specimen.length != 2) { upchuck(); }
return [lGuard(specimen[0]), rGuard(specimen[1])];
};
};
const FourTupleOf = (first, sec, third, fourth) => {
const upchuck = () => {
throw new Error("FourTuple guard did not pass specimen");
}
return (specimen) => {
if (!Array.isArray(specimen)) { upchuck(); }
if (specimen.length != 4) { upchuck(); }
return [first(specimen[0]),
sec(specimen[1]),
third(specimen[2]),
fourth(specimen[3])];
}
}
const Array_equal = (a, b) => {
if (a.length != b.length) { return false; }
var result = true;
a.forEach((item, idx) => {
result = (item == b[idx]) ? result : false ;
});
return result;
}
const RecordOf = (recordWithGuards) => {
return (specimen) => {
if ((typeof specimen) != "object") { upchuck(); }
const specimenNames = Object.getOwnPropertyNames(specimen).sort();
const guardingNames = Object.getOwnPropertyNames(recordWithGuards);
if (!Array_equal(specimenNames, guardingNames)) {
upchuck();
}
return Object.fromEntries(guardingNames.map((name) => {
return [name, recordWithGuards[name](specimen(name))];
});
}
}
const identityFunc = (i) => i;
const makeMathHelperByName = (mathHelpersName) => {
switch (mathHelpersName) {
case "nat": {
const natHelper = harden({
"doAssertKind": (allegedExtent) => {
if ((typeof(allegedExtent) != "number") &&
(typeof(allegefExtent) != "bigint")) {
throw new Error("tbi");
}
},
"doGetEmpty": () => { return BigInt(0); },
"doIsEmpty": (extent) => {
natHelper.doAssertKind(extent);
return BigInt(0) == BigInt(extent);
},
"doIsGTE": (left, right) => {
natHelper.doAssertKind(left);
natHelper.doAssertKind(right);
return BigInt(left) >= BigInt(right);
},
"doIsEqual": (left, right) => {
natHelper.doAssertKind(left);
natHelper.doAssertKind(right);
return BigInt(left) == BigInt(right);
},
"doAdd": (left, right) => {
natHelper.doAssertKind(left);
natHelper.doAssertKind(right);
return BigInt(BigInt(left) + BigInt(right));
},
"doSubtract": (left, right) => {
natHelper.doAssertKind(left);
natHelper.doAssertKind(right);
return BigInt(BigInt(left) - BigInt(right));
},
});
return natHelper;
}
case "strSet": {
return strSetHelper;
}
case "sealedNat": {
const {sealer, unsealer} = makeSealerUnsealer();
const sealedNatHelper = harden({
"doAssertKind": (allegedExtent) => {
if (unsealer.unseal(allegedExtent) == undefined) {
throw new Error("tbi");
}
},
"doGetEmpty": () => sealer.seal(BigInt(0)),
"doIsEmpty": (ext) => {
sealedNatHelper.doAssertKind(ext);
return (BigInt(0) == unsealer.unseal(ext));
},
"doIsGTE": (v, h) => {
sealedNatHelper.doAssertKind(v);
sealedNatHelper.doAssertKind(h);
return (unsealer.unseal(v) >= unsealer.unseal(h));
},
"doIsEqual": (v, h) => (sealedNatHelper.doIsGTE(v, h) && sealedNat.doIsGTE(h, v)),
"doAdd": (v, h) => {
sealedNatHelper.doAssertKind(v);
h = (BigInt(h) == BigInt(1)) ? sealer.seal(BigInt(1)) : h;
sealedNatHelper.doAssertKind(h);
return sealer.seal(unsealer.unseal(v) + unsealer.unseal(h));
},
"doSubtract": (v, h) => {
sealedNatHelper.doAssertKind(v);
sealedNatHelper.doAssertKind(h);
return sealer.seal(unsealer.unseal(v) - unsealer.unseal(h));
}
});
return sealedNatHelper;
}
case "rectArea": {
// each extent is an array of rects
// each rect is a 4 tuple array [x, y, w, h]
const rect_g = RecordOf({x: Nat, y: Nat,
w: PosNat, h: PosNat});
const guard = ArrayOf(rect_g);
const isInside = (a, b) => {
return ((a.x >= b.x) &&
(a.y >= b.y) &&
(a.w <= b.w) &&
(a.h <= b.h));
};
const compare = (a, b) => {
if (a.y < b.y) { return -1; }
if (a.x < b.x) { return -1; }
if (a.w < b.w) { return -1; }
if (a.h < b.h) { return -1; }
return 1;
// i = ((t1?1:0)<<3) | ((t2?1:0)<<2) | ((t3?1:0)<<1) | (t4?1:0);
}
const isEqual = (a, b) => {
return ((BigInt(a.x) == BigInt(b.x)) &&
(BigInt(a.y) == BigInt(b.y)) &&
(BigInt(a.w) == BigInt(b.w)) &&
(BigInt(a.h) == BigInt(b.h)));
};
const consolidate = (extent) => {
var curr = (new Array(extent)).sort(compare);
var prev = rectHelper.doGetEmpty();
while (!rectHelper.isEqual(curr, prev)) {
prev = curr;
curr = curr.reduce((acc, b, idx) => {
const a = acc[-1];
if (a === undefined) {
acc.push(b);
return acc;
}
if (isEqual(a, b)) { return acc; }
// do we have two rect of equal height abutting?
if ((a.h == b.h) && (a.y == b.y) &&
((a.x + a.w) == b.x)) {
// combine them
acc[-1] = { x: a.x, y: b.y,
w: (a.w + b.w), h: a.h };
return acc;
}
// do we have two rect of equal width abutting?
if ((a.w == b.w) && (a.x == b.x) &&
((a.y + a.h) == b.y)) {
// combine them
acc[-1] = { x: a.x, y: a.y,
w: b.w, h: (a.h + b.h)];
return acc;
}
acc.push(b);
return acc;
}, []).sort(compare);
}
return curr;
};
const is__common = (a, b) => {
const k = {};
k.x1 = a.x;
k.x2 = (a.x + a.w);
k.y1 = a.y;
k.y2 = (a.y + a.h);
k.x3 = b.x;
k.x4 = (b.x + b.w);
k.y3 = b.y;
k.y4 = (b.y + b.h);
k.t1 = ((x3 <= x1) && (x1 < x4));
k.t2 = ((y3 <= y1) && (y1 < y4));
k.t3 = ((x3 <= x2) && (x2 < x4));
k.t4 = ((y3 <= y2) && (y2 < y4));
k.t5 = ((x1 <= x3) && (x3 < x2));
k.t6 = ((y1 <= y3) && (y3 < y2));
k.t7 = ((x1 <= x4) && (x4 < x2));
k.t8 = ((y1 <= y4) && (y4 < y2));
return k;
};
const isOverlap = (a, b) => {
const k = is__common(a,b);
return ((k.t1 && k.t2) || (k.t1 && k.t4) ||
(k.t3 && k.t2) || (k.t3 && k.t4) ||
(k.t5 && k.t6) || (k.t5 && k.t8) ||
(k.t7 && k.t6) || (k.t7 && k.t8));
};
const isCompletelyInside = (insider, outsider) => {
const k = is__common(insider, outsider);
return (k.t1 && k.t2 && k.t3 && k.t4);
}
const compactify = (arr) => {
return arr.filter((item) => (item != undefined));
}
const flatten = (arr) => {
var r = [];
arr.forEach((item) => {
if (Array.isArray(item)) {
r = r.concat(item);
} else {
r.push(item);
}
});
return r;
}
const subtract = (left, subtractand) => {
var result = Array(left);
var tmp;
var cont = true;
while (cont) {
result = flatten(compactify(result));
tmp = Array(result);
cont = false;
subtractand.forEach((sub) => {
tmp.forEach((l, li) => {
// overlap?
if (isOverlap(sub, l)) {
cont = true;
// is victim completely inside sub?
if (isCompletelyInside(l, sub)) {
// remove the victim
result[li] = undefined;
} else {
// what kind of spliting is required here?
// 2 splits:
const k = is__common(l, sub);
if (k.t1 && k.t3) {
// bottom or top being obscured?
if (k.t6) {
// bottom
result[li] = { x: l.x, y: l.y, w: l.w,
h: (sub.y - l.y) }
} else if (k.t8) {
// top
result[li] = { x: l.x, y: k.y4, w: l.w,
h: (l.h - (k.y4 - l.y)) }
}
}
if (k.t2 && k.t4) {
// left or right being obscured?
if (k.t5) {
} else if (k.t7) {
}
}
}
}
});
});
}
return result;
}
const rectHelper = harden({
"doAssertKind": (extent) => { guard(extent); },
"doGetEmpty": () => {
return harden([{ x: 0, y: 0, w: 0, h: 0}]);
},
"doIsEmpty": (extent) => {
rectHelper.doAssertKind(extent);
return ((extent.length == 1) &&
(BigInt(extent[0].x) == 0n) &&
(BigInt(extent[0].y) == 0n) &&
(BigInt(extent[0].w) == 0n) &&
(BigInt(extent[0].h) == 0n));
},
"doIsGTE": (l, r) => {
rectHelper.doAssertKind(l);
rectHelper.doAssertKind(r);
var result = true;
r.forEach((ir) => {
var tmp = false;
l.forEach((il) => {
tmp = isInside(ir, il) ? true : tmp;
});
result = tmp ? result : false;
});
return result;
},
"doIsEqual": (l, r) => {
return (rectHelper.doIsGTE(l, r) &&
rectHelper.doIsGTE(r, l));
},
"doAdd": (l, r) => {
rectHelper.doAssertKind(l);
rectHelper.doAssertKind(r);
return consolidate(l.concat(r));
},
"doSubtract": (l, r) => {
// there are four cases between
// each rect of l and each rect of r:
// a) former and latter do not overlap
// do nothing
// b) latter is inside of former resulting in:
// b.1) 4 split of former and recurse
// b.2) 9 split of former and recurse
// c) latter obscures former resulting in
// c.1) 2 split of former and recurse
// c.2) 4 split of former and recurse
// d) the latter completely obscures the former
// remove the former
rectHelper.doAssertKind(l);
rectHelper.doAssertKind(r);
return subtract(l, r);
}
});
return rectHelper;
}
case "rectArea_1": {
// deprecate virkar eigi eins og ég vill
// each extent is an set of pair of coordnates
// the set is just an array
// a pair is just two element array
// a coordnate is just two element array of bigints
const cg = PairOf(Nat, Nat);
const my_guard = ArrayOfOnly(PairOf(cg, cg));
const minCoord = (a, b) => {
if ((a[0] < b[0]) && (a[1] < b[1])) { return a; }
if ((a[0] < b[0]) && (a[1] > b[1])) { return ?; }
if ((a[0] > b[0]) && (a[1] < b[1])) { return ?; }
if ((a[0] > b[0]) && (a[1] > b[1])) { return b; }
return a;
}
const isCoordInsideRect = (coord, rect) => {
return ((minCoord(coord, a) == a) &&
(minCoord(coord, b) == coord));
}
const consolidate = (rectAreaInp) => {
var prev = rectAreaHelper.doGetEmpty();
var curr = rectAreaInp;
while (!rectAreaHelper.isEqual(prev, curr)) {
prev = curr;
curr = curr.reduce
}
return curr;
}
const rectAreaHelper = harden({
"doAssertKind": (extent) => {
my_guard(extent);
},
"doGetEmpty": () => {
const zeroZero = [BigInt(0), BigInt(0)];
const emptyRect = [zeroZero, zeroZero];
return [emptyRect];
},
"doIsEmpty": (extent) => {
rectAreaHelper.doAssertKind(extent);
var isEmpty = true;
extent.forEach((pair) => {
const coordA = pair[0];
const coordB = pair[1];
if (BigInt(coordA[0]) != 0n) { isEmpty = false; }
if (BigInt(coordA[1]) != 0n) { isEmpty = false; }
if (BigInt(coordB[0]) != 0n) { isEmpty = false; }
if (BigInt(coordB[1]) != 0n) { isEmpty = false; }
});
return isEmpty;
},
"doIsGTE": (left, right) => {
// a rectArea is considered GTE when it
// 'shades'/overlaps the other completely
rectAreaHelper.doAssertKind(left);
rectAreaHelper.doAssertKind(right);
var result = true;
right.forEach((rBox) => {
var t = false;
left.forEach((lBox) => {
if (isCoordInsideRect(rBox[0], lBox) &&
isCoordInsideRect(rBox[1], lBox) {
t = true;
}
});
if (!t) { result = false; }
});
return result;
},
"doIsEqual": (left, right) => {
rectAreaHelper.doAssertKind(left);
rectAreaHelper.doAssertKind(right);
// the rectAreas must overlap exactly
// const lSorted = left.map(identityFunc).sort(comp);
// const rSorted = right.map(identityFunc).sort(comp);
return (rectAreaHelper.doIsGTE(left, right) &&
rectAreaHelper.doIsGTE(right, left));
},
"doAdd": (l, r) => {
rectAreaHelper.doAssertKind(l);
rectAreaHelper.doAssertKind(r);
return consolidate(l.concat(r));
}
});
return rectAreaHelper;
}
}
};
const makeAmountMath = (brand, mathHelpersName) => {
const mathHelper = makeMathHelperByName(mathHelpersName);
const amountMath = harden({
"getBrand": () => { return brand; },
"getMathHelpersName": () => { return mathHelpersName; },
"make": (allegedExtent) => {
return amount;
},
"coerce": (allegedAmountOrExtent) => {
return amount;
},
"extent": (amount) => {
if (!brandsAreEqual(brand, amount.brand)) {
throw nonEqualBrands(brand, amount.brand);
}
return amount.extent;
},
"getEmpty": () => {
return harden({ brand,
"extent": mathHelper.doGetEmpty() });
},
"isEmpty": (amount) => {
return mathHelper.doIsEmpty(amountMath.extent(amount));
},
"isGTE": (leftAmount, rightAmount) => {
const leftExtent = amountMath.extent(leftAmount);
const rightExtent = amountMath.extent(rightAmount);
return mathHelper.doIsGTE(leftExtent, rightExtent);
},
"isEqual": (leftAmount, rightAmount) => {
// amountMath er upphæðarReiknir
const leftExtent = amountMath.extent(leftAmount);
const rightExtent = amountMath.extent(rightAmount);
return mathHelper.doIsEqual(leftExtent, rightExtent);;
},
"add": (leftAmount, rightAmount) => {
const leftExtent = amountMath.extent(leftAmount);
const rightExtent = amountMath.extent(rightAmount);
const extent = mathHelper.doAdd(leftExtent, rightExtent);
const amount = harden({ brand, extent });
return amount;
},
"subtract": (leftAmount, rightAmount) => {
const leftExtent = amountMath.extent(leftAmount);
const rightExtent = amountMath.extent(rightAmount);
const extent = mathHelper.doSubtract(leftExtent, rightExtent);
const amount = harden({ brand, extent });
return amount;
},
"toJSON": () => {
return {"$call":[makeAmountMath, "apply", [brand, mathHelpersName]]};
}
});
return amountMath;
};
exported.makeAmountMath = makeAmountMath;
const makeBrand = (issuer, allegedName) => {
return harden({
"isMyIssuer": (paramIssuer) => {
// returns a Boolean
return (paramIssuer === issuer);
},
"getAllegedName": () => { return allegedName; },
"toJSON": () => {
return {"$call": [makeBrand, "apply", [issuer, allegedName]]};
}
});
};
const brand = makeBrand(issuer, allegedName);
const amountMath = makeAmountMath(brand, mathHelpersName);
return harden({ mint, issuer, amountMath, brand });
}
return harden(exported);
})();;
// Clueless Software Agent stuff
const make_NoncerService = async (storage) => {
const rootSecret = await storage.get("root-secret");
const doRequest = (roon, ...restOfArgs) => {
const checker = makeRoonChecker("NoncerService");
checker.setRootSecret(rootSecret);
checker.addCavetChecker(timeCavetChecker);
const result = []; // woulde be FlexList in E
var cellId = undefined;
var cellPerm = undefined;
checker.addCavetChecker((cavet) => {
const [first, second, ...rest] = cavet.split(" ");
if (first === "noncer") {
switch (second) {
case "cell-uuid": {
const [id, perm] = rest;
if (cellId !== undefined) {
throw new Error("cell-uuid specifier already specified");
}
[cellId, cellPerm] = [id, perm.split(",")];
return true;
}; break;
case "read": {
if (cellId === undefined) {
throw new Error("cell-uuid was not specified prior to read");
}
if (!cellPerm.includes("read")) {
throw new Error("this roon does not have read permission for the specified cell");
}
result.push(storage.get(cellId));
return true;
}; break;
case "write": {
if (cellId === undefined) {
throw new Error("cell-uuid was not specified prior to write");
}
const [value] = rest;
if (!cellPerm.includes("write")) {
throw new Error("this roon does not have write permission for the specified cell");
}
storage.set(cellId, value);
return true;
}; break;
case "deny": {
if (cellId === undefined) {
throw new Error("cell-uuid was not specified prior to a deny");
}
const [denied] = rest;
if (!cellPerm.includes(denied)) {
throw new Error("this roon already does not have the denied permission");
}
cellPerm = cellPerm.filter((i) => (i != denied));
return true;
}; break;
}
}
return undefined;
});
checker.check(roon);
return results;
}
return harden({ do: doRequest });
};
///////////////////////////////////////////////////////
//
// hmm.. stakmeingi þar sem hvert stak hefur sitt UUID
// nota líka bit-sel-shuffle til að velja bita staksins
// bit-sel-shuffle er permutation-box úr symmetric key crypto?
const BasicCSA = (envStateGatherer, expectedHash, payload) => {
const key = envStateGatherer().toString();
if (SHA256(key) == expectedHash) {
eval(AES256(key, payload));
}
}
// spurning um hvernig (x < constant) og co væri útfært
const make_xLessThanConst_CSA = (constant, xWidthInBits, payloadPlaintext, randomBytesSrc) => {
// method a, one giant collection of BCSAs, of two halfs
const con = randomBytesSrc(42).toString(16);
const xWidthInNybbles = Math.int(xWidthInBits / 4) + 1;
var csa = "(x) => {\n";
csa = csa.concat(" var t = \"\";\n");
csa = csa.concat(" const xs = leftpad(x.toString(16), ", xWidthInNybbles.toString(10), ", \"0\");\n");
for (let v = 0; v < constant; v++) {
const vs = leftpad(v.toString(16), xWidthInNybbles, "0");
csa = csa.concat(" BasicCSA(() => xs, \"", SHA256(vs), "\", hex2bytes(\"",
bytes2hex(AES256(vs, "t = \"".concat(con, "\"; void 0x", randomBytesSrc(42).toString(16), ";"))),
"\"));\n");
}
for (let v = constant; v < 2**xWidthInBits; v++) {
const vs = leftpad(v.toString(16), xWidthInNybbles, "0");
let alt = con; while (alt == con) { alt = randomBytesSrc(42).toString(16); }
csa = csa.concat(" BasicCSA(() => xs, \"", SHA256(vs), "\", hex2bytes(\"",
bytes2hex(AES256(vs, "t = \"".concat(alt, "\"; void 0x", randomBytesSrc(42).toString(16), ";"))),
"\"));\n");
}
csa = csa.concat(" BasicCSA(() => t, \"", SHA256(con),
"\", hex2bytes(\"", bytes2hex(AES256(con, payloadPlaintext)), "\"));\n");
csa = csa.concat("}");
return csa;
}
//////////////////////////////////////////////////
// What does a changing room/booth, phonebooth, wc stall and voting booth have in commom?
// They offer privacy for certain tasks.
// I am going to call that generilized concept privacy chamber (is: einkaklefi) for now.
// in a cap-lore terms, the chamber is veiled (mágera: finna link á þá síðu)
// Implementation ideas:
// use Javacard+GlobalPlatform smartcard or Apple secure enclave or even Intel SGX as substrate
// for an macro extended PRA dual stack machine whose bytecode is used for those privacy sensitive tasks.
@zarutian
Copy link
Author

zarutian commented Mar 1, 2020

afrit á síma tekið um 23:35 29 feb v96

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment