-
-
Save zarutian/fb21d0a8c910ab255401 to your computer and use it in GitHub Desktop.
CapTP using MessagePack wire encoding.
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
CapTP using MsgPack (v4.3.2) | |
(MsgPack see https://github.com/msgpack/msgpack/blob/master/spec.md ) | |
letrc := msgpck_ext_0 ( msgpck_uint msgpck_any ) -- is same as <msgpck_any> but also adds the object to the ibid table | |
ibid := msgpck_ext_1 ( msgpck_uint ) -- looks up in the ibid table, if anything isnt found returns nil | |
messages := message [messages] | |
message := DeliverOnly | Deliver | GCExport | GCAnswer | Shutdown | Terminated | |
DeliverOnly := msgpck_ext_2 ( recipiant verb args namedArgs ) | |
Deliver := msgpck_ext_3 ( answerPos rdr recipiant verb args namedArgs ) | |
GCExport := msgpck_ext_4 ( exportPos wireDelta ) | |
GCAnswer := msgpck_ext_5 ( answerPos ) | |
Shutdown := msgpck_ext_6 ( recivedCount ) | |
Terminated := msgpck_ext_7 ( problem ) | |
recipiant := anyObj | |
verb := msgpck_UTF8_string | |
args := msgpck_array ( anyObj* ) | |
namedArgs := msgpck_map ( anyPair* ) | elided | |
anyPair := anyObj anyObj | |
elided : basically means it is left out | |
anyObj := Export | Answer | Import | Question | newFarDesc | | |
newRemotePromiseDesc | newPromise3Desc | RemoteCall | | |
RemoteDelviery | LocatorUnumDesc | SturdyRef | msgpck_any | | |
ActiveCapCert | Macaroony | PostalRefACC | PostalRefM | |
Export := msgpck_ext_8 ( exportPos ) | |
Answer := msgpck_ext_9 ( answerPos ) | |
Import := msgpck_ext_10 ( importPos ) | |
Question := msgpck_ext_11 ( questionPos ) | |
newFarDesc := msgpck_ext_12 ( importPos SwissHash ) | |
newRemotePromiseDesc := msgpck_ext_13 ( importPos rdrPos rdrBase ) | |
newPromise3Desc := msgpck_ext_14 ( searchPath hostID nonce vine ) | |
RemoteDeliver := msgpck_ext_15 ( recipiant verb args namedArgs ) | |
RemoteCall := msgpck_ext_16 ( recipiant verb args namedArgs ) | |
LocatorUnumDesc := msgpck_ext_17 ( ) | |
SturdyRef := msgpck_ext_18 ( locator searchPath hostId swissNum expiry ) | |
NonceLocator := msgpck_ext_8 ( <exportPos == 0> ) | msgpck_ext_9 ( <importPos == 0> ) | |
exportPos := msgpck_uint -- speaker imports, listener exports (Speaker: "Hey listener, about your export #xxx...") | |
importPos := msgpck_uint -- speaker exports, listener imports (Speaker: "Hey listener, about my export #xxx...") | |
answerPos := msgpck_uint -- speaker assigns, listener follows | |
questionPos := msgpck_uint -- speaker follows, listener assigns | |
searchPath := msgpck_array( [searchPathItem [ searchPathItems ] ] ) | |
searchPathItem := msgpck_string | |
searchPathItems := searchPathItem [ searchPathItems ] | |
hostId := VatID | |
vine := anyObj | |
rdr := anyObj | |
rdrPos := answerPos | |
rdrBase := swissBase | |
swissHash := crypto_hash(swissNum) | |
swissNum := crypto_hash(swissBase) | |
swissBase := random_bytestring | |
expiry := msgpck_ext26 (RFC3339 date as utf8/ASCII) | | |
msgpck_ext27 (TAI64 date as binary bytes) -- see https://cr.yp.to/libtai/tai64.html can be 8, 12 or 16 bytes | |
-- use another extenstion nrs for other cryptographic hashes | |
crypto_hash(item) := msgpck_ext19 (SHA256(item)) | | |
msgpck_ext24 (Blake2d_32(item)) | | |
msgpck_ext25 (Blake2d_64(item)) | |
VatId := crypto_hash(<public key of that Vat>) | |
ActiveCapCert := msgPack_ext20 ( ACC_issuer ACC_function ACC_signature ) | |
PostalRefACC := msgpck_ext21 ( ) | |
Macaroony := msgpck_ext22 ( libmacaroon_format ) | |
PostalRefRefM := msgpck_ext23 ( ) | |
ACC_issuer := VatId | OpenPGP_public_key | OpenSSL_public_key | |
ACC_function := ACC_function_parameters ACC_function_body | |
ACC_function_parameters := ACC_function_parameter* | |
ACC_function_body : Thinking about restrecting these to computing class of primitive recursive functions. | |
ACC_signature : ACC_issuers signature of ACC_function | |
perhaps see SPKI on how to store signatures and public keys. | |
msgpck_any := msgpck_int | msgpck_bytestring | msgpck_UTF8_string | msgpck_bool | | |
msgpck_map ( msgpck_map_entry* ) | msgpck_array ( msgpck_any* ) | anyObj | |
msgpck_UTF8_string := msgpck_string | |
msgpck_map_entry := msgpck_any msgpck_any | |
libmacaroon_format := libmacaroon_record [...] # not base64 encoded | |
libmacaroon_record := libmacaroon_recordLength libmacaroon_recordUTF8string | |
libmacaroon_recordLength := libmacaroon_hexDigit * 4 # bigendian length of the following string | |
libmacaroon_hexDigit := "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" | "A" | "B" | "C" | "D" | "E" | "F" | |
libmacaroon_recordUTF8string := libmacaroon_identifier | libmacaroon_signature | libmacaroon_1stPartyCaveat | | |
libmacaroon_3rdPartyCaveat | libmacaroon_3rdPartyDischarge | macaroony_messages | | |
macaroony_MustByVatCaveat | macaroony_encrypted | |
macaroony_messages := "mrymsg " messages | |
libmacaroon_identifier := "identifier vatId:" hex(vatId) " swissHash:" hex(swissHash) # the corrisponding swissNum is then the starting HMAC key of the macaroon | |
Generally, the smallest possible msgpck representation is used for each datum. | |
Example 1: | |
(doesnt use ibids) | |
I = initiator, the vat that initiates the connection | |
S = servicer, the vat that recives that initation | |
the hexdecimals are the data sent on the wire (not though as hex but as bytes) the rest is just commentary | |
--- initatior establishes an VatTP to servicer | |
I: | |
c73803 Deliver message | |
01 answer position #1 (servicer is expected to answer and put it at this position in its answer table) | |
d5 redirector (rdr) is a newFarDesc | |
01 export position #1 (initator is exporting) | |
c0 no swissHash | |
d40800 recipiant is the nonceLocator at servicers end | |
ab 6c6f6f6b75705377697373 -- verb is "lookupSwiss" | |
92 args array | |
c72013 swissNum of "Calculator" | |
668b80455fdbae2f6816c7d0d542c0238d627b3da0454e14388bd429713590e1 | |
c0 no vine | |
c71303 Deliver message | |
02 answer position #2 | |
d5 redirector (rdr) is a newFarDesc | |
02 export position #2 (initator is exporting) | |
c0 no swissHash | |
d40901 recipiant is the answer #1 in servicers answers table | |
a8 6d756c7469706c79 verb is "multiply" | |
92 args array | |
02 the number 2 | |
03 the number 3 | |
c70f03 Deliver message | |
03 answer position #3 | |
d5 redirector (rdr) is a newFarDesc | |
03 export position #3 (initator is exporting) | |
c0 no swissHash | |
d40901 recipiant is the answer #1 in servicers answers table | |
a4 706c7573 verb is "plus" | |
92 args array | |
04 the number 4 | |
03 the number 3 | |
c70f03 Deliver message | |
04 answer position #4 | |
d5 redirector (rdr) is a newFarDesc | |
04 export position #4 (initator is exporting) | |
c0 no swissHash | |
d40901 recipiant is the answer #1 in servicers answers table | |
a8 6d756c7469706c79 verb is "multiply" | |
92 args array | |
d40902 answer #2 | |
d40903 answer #3 | |
(126 bytes in this packet/tcp_segment) | |
S: | |
c70e02 DeliverOnly | |
d40801 recipiant is initiators export #1 | |
a3 72756e verb is "run" | |
91 args array | |
d40b01 the answer to initiators question #1 | |
c70902 DeliverOnly | |
d40802 recipiant is initiators export #2 | |
a3 72756e verb is "run" | |
91 args array | |
06 the number 6 | |
c70902 DeliverOnly | |
d40803 recipiant is initators export #3 | |
a3 72756e verb is "run" | |
91 args array | |
07 the number 7 | |
c70c02 DeliverOnly | |
d40804 recipiant is initators export #4 | |
a3 72756e verb is "run" | |
91 args array | |
2a the number 42 | |
(50 bytes in this packet/tcp_segment) | |
Example 2: | |
(uses ibids) | |
I: | |
c7__03 Deliver message | |
01 answer position nr #1 | |
d5 redirector, a new fardesc | |
42 export position nr #66 | |
c0 no swissHash | |
d40800 recipiant is the nonceLocator at servicers end | |
c70d00 letrc | |
01 ibid location 1 | |
ab 6c6f6f6b75705377697373 the verb "lookupSwiss" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# This file is now out of date, see instead https://github.com/zarutian/monte_stuff/blob/streamcap-use/serial/kits/msgpckKit.mt | |
# Monte syntax&semantics | |
def makeMsgunpacker (fount, drain) as DeepFrozen: | |
var buffer := [].diverge() | |
var k := [].asMap().diverge() | |
k['\x00'] = fn (byte): | |
buffer := buffer.slice(1, buffer.size() - 1) | |
drain <- receive(decodeU8bit(byte)) | |
return | |
for (var i := 1; i <= 0x7f; i++) | |
k[i.asChar()] = k['\x00'] | |
k['\x80'] := fn (byte): | |
# Fixmap | |
buffer := buffer.slice(1, buffer.size() - 1) | |
var pairn := decodeU8bit(byte.and(0x0f)) | |
drain <- receive(makeMapMark(pairn)) | |
return | |
for (var i := 0x81; i <= 0x8f; i++) | |
k[i.asChar()] = k['\x80'] | |
k['\x90'] = fn (byte): | |
# Fixarray | |
buffer := buffer.slice(1, buffer.size() - 1) | |
var itemn := decodeU8bit(byte.and(0x0f)) | |
drain <- receive(makeArrayMark(itemn)) | |
return | |
for (var i := 0x91; i <= 0x9f; i++) | |
k[i.asChar()] := k['\x90'] | |
k['\xa0'] := fn (byte) | |
# Fixstr | |
var size := buffer.size() | |
var length := decodeU8bit(byte.and(0x1f)) | |
if (size < (1 + length)) | |
return | |
var str := buffer.slice(1, length) | |
buffer := buffer.slice((1 + length), size - 1) | |
drain <- receive(makeStr(str)) | |
return | |
for (var i := 0xa1; i <= 0xbf; i++) | |
k[i.asChar()] := k['\xa0'] | |
k['\xc0'] = fn (_): | |
# Nil | |
buffer := buffer.slice(1, buffer.size() - 1) | |
drain <- receive(Nil) | |
return | |
k['\xc1'] = fn (_): | |
# never used | |
buffer := buffer.slice(1, buffer.size() - 1) | |
return | |
k['\xc2'] = fn (_): | |
# Boolean false | |
buffer := buffer.slice(1, buffer.size() - 1) | |
drain <- receive(false) | |
return | |
k['\xc3'] = fn(_): | |
# Boolean true | |
buffer := buffer.slice(1, buffer.size() - 1) | |
drain <- receive(true) | |
return | |
k['\xc4'] = fn (_): | |
# Bin 8 | |
var size = buffer.size() | |
if (size < 2) | |
return | |
var length := decodeU8bit(buffer[1]) | |
if (size < (2 + length)) | |
return | |
var bin := buffer.slice(2, (2 + length - 1)) | |
buffer := buffer.slice((2 + length), size - 1) | |
drain <- receive(makeBinary(bin)) | |
return | |
k['\xc5'] = fn (_): | |
# Bin 16 | |
var size = buffer.size() | |
if (size < 3) | |
return | |
var length := decodeU16bit(buffer.slice(1,2)) | |
if (size < (3 + length)) | |
return | |
var bin := buffer.slice(3, (3 + length - 1)) | |
buffer := buffer.slice((3 + length), size - 1) | |
drain <- receive(makeBinary(bin)) | |
return | |
k['\xc6'] = fn (_): | |
# Bin 32 | |
var size = buffer.size() | |
if (size < 5) | |
return | |
var length := decodeU32bit(buffer.slice(1,4)) | |
if (size < (5 + length)) | |
return | |
var bin := buffer.slice(5, (5 + length - 1)) | |
buffer := buffer.slice((5 + length), size - 1) | |
drain <- receive(makeBinary(bin)) | |
return | |
k['\xc7'] = fn (_): | |
# Ext 8 | |
var size = buffer.size() | |
if (size < 3) | |
return | |
var length := decodeU8bit(buffer[1]) | |
var type := decodeI8bit(buffer[2]) | |
if (size < (3 + length)) | |
return | |
var ext := buffer.slice(3, (3 + length - 1)) | |
buffer := buffer.slice((3 + length), size - 1) | |
drain <- receive(makeExt(type, ext)) | |
return | |
k['\xc8'] = fn (_): | |
# Ext 16 | |
var size = buffer.size() | |
if (size < 4) | |
return | |
var length := decodeU16bit(buffer.slice(1,2)) | |
var type := decodeI8bit(buffer[3]) | |
if (size < (4 + length)) | |
return | |
var ext := buffer.slice(4, (4 + length - 1)) | |
buffer := buffer.slice((4 + length), size - 1) | |
drain <- receive(makeExt(type, ext)) | |
return | |
k['\xc9'] = fn (_): | |
# Ext 32 | |
var size = buffer.size() | |
if (size < 6) | |
return | |
var length := decodeU32bit(buffer.slice(2, 5)) | |
var type := decodeU8bit(buffer[6]) | |
if (size < (7 + length)) | |
return | |
var ext := buffer.slice(7, (7 + length - 1)) | |
buffer := buffer.slice((7 + length), size - 1) | |
drain <- receive(makeExt(type, ext)) | |
return | |
k['\xca'] := fn (_): | |
# Float, single | |
if (buffer.size() < 5) | |
return | |
var f := buffer.slice(1, 4) | |
buffer := buffer.slice(5, buffer.size() - 1) | |
drain <- receive(makeFloat(f)) | |
return | |
k['\xcb'] := fn (_): | |
# Float, double | |
if (buffer.size() < 9) | |
return | |
var f := buffer.slice(1,8) | |
buffer := buffer.slice(9, buffer.size() - 1) | |
drain <- receive(makeFloat(f)) | |
return | |
k['\xcc'] := fn (_): | |
# Uint 8 | |
k['\xcd`] := fn (_): | |
# Uint 16 | |
k['\xce'] := fn (_): | |
# Uint 32 | |
k['\xcf'] := fn (_): | |
# Uint 64 | |
return object unpacker: | |
to receive(byte): | |
buffer with= (byte) | |
k[buffer[0]](buffer[0]) | |
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
local subgraphKit = {} | |
subgraphKit.makeBuilder = function (environ) -- near_guard on return values | |
local nextTemp = 0 | |
local temps = {} | |
local Node = any_guard | |
local Root = any_guard | |
local subgraphBuilder = {} | |
subgraphBuilder.getNodeType = function () | |
return near_guard(Node) | |
end | |
subgraphBuilder.getRootType = function () | |
return near_guard(Node) | |
end | |
subgraphBuilder.buildRoot = function (root) | |
return Root(Node(root)) | |
end | |
subgraphBuilder.buildLiteral = function (value) | |
return Node(value) | |
end | |
subgraphBuilder.buildImport = function (varName) | |
return Node(environ[string_guard(varName)]) | |
end | |
subgraphBuilder.buildIbid = function (tempIndex) | |
return Node(temps[int_guard(tempIndex)]) | |
end | |
subgraphBuilder.buildCall = function (reciver, verb, args) | |
reciver = Node(reciver) | |
verb = string_guard(verb) | |
args = array_guard(Node, args) | |
return Node(reciver[verb](args)) -- not quite sure about the args passing is correct | |
end | |
subgraphBuilder.buildPromise = function () | |
local promIdx = nextTemp | |
nextTemp = nextTemp + 2 | |
local prom, res = Reference.promise() | |
temps[promIdx] = prom | |
temps[promIdx + 1] = res | |
return int_guard(promIdx) | |
end | |
subgraphBuilder.buildDefrec = function (resIdx, rValue) | |
resIdx = int_guard(resIdx) | |
rValue = Node(rValue) | |
temps[resIdx].resolve(rValue) | |
return rValue | |
end | |
subgraphBuilder.buildDefine = subgraphBuilder.buildDefrec -- no non-cyclic cases optimization | |
return subgraphBuilder | |
end | |
local msgPckKit = {} | |
msgPckKit.makeBuilder = function (environ) | |
local Node = bytestring_guard | |
local Root = any_guard | |
local msgPckBuilder = {} | |
msgPckBuilder.getNodeType = function () | |
return near_guard(Node) | |
end | |
msgPckBuilder.getRootType = function () | |
return near_guard(Node) | |
end | |
msgPckBuilder.buildRoot = function (root) | |
return Root(Node(root)) | |
end | |
msgPckBuilder.buildLiteral = function (value) | |
if nil_guard.matches(value) then | |
return Node("\xC0") | |
end | |
if bool_guard.matches(value) then | |
if value == false then | |
return Node("\xC2") | |
else | |
return Node("\xC3") | |
end | |
end | |
if int_guard.matches(value) then | |
if 0 <= value and value <= 127 then | |
-- do this with something like string format or some such | |
local lut = {} | |
lut[0] = "\x00" | |
lut[1] = "\x01" | |
lut[2] = "\x02" | |
lut[3] = "\x03" | |
lut[4] = "\x04" | |
return Node(lut[value]) | |
else if -1 >= value and value >= -32 then | |
else if 128 <= value and value <= 255 then | |
else if 256 <= value and value <= 65535 then | |
else if 65536 <= value and value <= Math.pow(2,32)-1 then | |
else if Math.pow(2,32) <= value then | |
end | |
end | |
end | |
msgPckBuilder.buildImport = function (varName) | |
return Node(environ[string_guard(varName)]) | |
end | |
msgPckBuilder.buildIbid = function (tempIndex) | |
return Node(int_guard(tempIndex)) | |
end | |
msgPckBuilder.buildCall = function (reciver, verb, args) | |
reciver = Node(reciver) | |
verb = string_guard(verb) | |
args = array_guard(Node, args) | |
return Node(reciver[verb](args)) -- not quite sure about the args passing is correct | |
end | |
msgPckBuilder.buildPromise = function () | |
local promIdx = nextTemp | |
nextTemp = nextTemp + 2 | |
local prom, res = Reference.promise() | |
temps[promIdx] = prom | |
temps[promIdx + 1] = res | |
return int_guard(promIdx) | |
end | |
subgraphBuilder.buildDefrec = function (resIdx, rValue) | |
resIdx = int_guard(resIdx) | |
rValue = Node(rValue) | |
temps[resIdx].resolve(rValue) | |
return rValue | |
end | |
subgraphBuilder.buildDefine = subgraphBuilder.buildDefrec | |
return msgPckBuilder | |
end | |
local makeUnevaler = function (uncallerList, unenvironMap) -- near_guard on return value | |
local unevaler = {} | |
unevaler.recognize = function (root, builder) | |
local Root = builder.getRootType() | |
local Node = builder.getNodeType() | |
local uncallers = snapshot(uncallerList) | |
local unenviron = diverge(unenvironMap) | |
local generate | |
local genCall = function (reciver verb, args) | |
verb = string_guard(verb) | |
args = array_guard(any_guard, args) | |
local recExpr = generate(reciver) | |
local argExprs = {} | |
for arg in args do | |
table.insert(argExpr, generate(arg)) | |
end | |
return Node(builder.buildCall(recExpr, verb, argExpr)) | |
end | |
local genObject = function (obj) | |
if int_guard.matches(obj) then | |
return Node(builder.buildLiteral(obj)) | |
end | |
if float64_guard.matches(obj) then | |
return Node(builder.buildLiteral(obj)) | |
end | |
if char_guard.matches(obj) then | |
return Node(builder.buildLiteral(obj)) | |
end | |
-- twine stuff?!? | |
for uncaller in uncallers do | |
local rec, verb, args = uncaller.optUncall(obj) | |
if rec ~= nil then | |
return genCall(rec, verb, args) | |
end | |
end | |
throw("Can not uneval " .. obj) | |
end | |
local genVarUse = function (varId) | |
varId = or_guard(varId, string_guard, int_guard) | |
if string_guard.matcheS(varId) then | |
return Node(builder.buildImport(varName)) | |
else | |
return Node(builder.buildIbid(varName)) | |
end | |
end | |
generate = function (object) | |
end | |
return Root( /* */ ) | |
end | |
end | |
local makeSurgeon |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment