-
-
Save zarutian/2cb903d37364b9a7518c300417c23801 to your computer and use it in GitHub Desktop.
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 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. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
afrit á síma tekið um 23:35 29 feb v96