@adapt-toolkit/mufl 0.10.8 → 0.10.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/mufl_stdlib/config.mufl +2 -0
- package/mufl_stdlib/cryptography/address_document.mm +34 -0
- package/mufl_stdlib/cryptography/attestation/node_description.mm +3 -1
- package/mufl_stdlib/limits.mm +67 -0
- package/package.json +1 -1
- package/prebuilds/linux-x64/mufl +0 -0
- package/prebuilds/linux-x64/mufl-compile +0 -0
- package/transactions/__t_wrapper.mm +4 -1
- package/transactions/transaction.mm +8 -3
package/mufl_stdlib/config.mufl
CHANGED
|
@@ -6,6 +6,7 @@ config script {
|
|
|
6
6
|
$current_transaction_info->#"current_transaction_info.mm",
|
|
7
7
|
$identity_proof_document->#"identity_proof_document.mm",
|
|
8
8
|
$lists->#"lists.mm",
|
|
9
|
+
$limits->#"limits.mm",
|
|
9
10
|
$vector->#"vector.mm",
|
|
10
11
|
$platform_type_id->#"platform_type_id.mm",
|
|
11
12
|
$transaction_message_decoder->#"transaction_message_decoder.mm",
|
|
@@ -51,6 +52,7 @@ config script {
|
|
|
51
52
|
$current_transaction_info->#"current_transaction_info.mm",
|
|
52
53
|
$identity_proof_document->#"identity_proof_document.mm",
|
|
53
54
|
$lists->#"lists.mm",
|
|
55
|
+
$limits->#"limits.mm",
|
|
54
56
|
$vector->#"vector.mm",
|
|
55
57
|
$platform_type_id->#"platform_type_id.mm",
|
|
56
58
|
$transaction_message_decoder->#"transaction_message_decoder.mm",
|
|
@@ -201,6 +201,40 @@ library address_document loads libraries address_document_types, key_storage, ke
|
|
|
201
201
|
RETURN ($version->1, $identity->my_identity, $authorizations->signatures).
|
|
202
202
|
}
|
|
203
203
|
|
|
204
|
+
// The address document for the TRANSPORT identity-proof (node_description) —
|
|
205
|
+
// the self-attestation attached to EVERY outgoing external transaction. The
|
|
206
|
+
// identity is the full v2 record (the $e2e_bundle stays: receivers read the
|
|
207
|
+
// sender's e2e identity key off it for the inbound E2E decode hook), but
|
|
208
|
+
// $authorizations carries TWO self-signatures per SIGN key: one over
|
|
209
|
+
// _value_id(v2 identity) and one over _value_id(v1 bundle-less identity).
|
|
210
|
+
// A pre-e2e_bundle validator (SDK <= 0.9.x schema, e.g. the deployed
|
|
211
|
+
// ours-mcp 0.10.1) re-hashes the identity WITHOUT $e2e_bundle and finds the
|
|
212
|
+
// v1-hash signature in its any-match loop; a current validator finds the
|
|
213
|
+
// v2-hash signature. NOT memoised and used ONLY by node_description::create,
|
|
214
|
+
// so the main address document (invites, delegation certs, readvertise
|
|
215
|
+
// payloads — and every cert ad-hash binding) stays strict v2-sig-only.
|
|
216
|
+
produce_transport_address_document = fn (_) -> t_address_document
|
|
217
|
+
{
|
|
218
|
+
base_identity = key_storage::get_my_identity().
|
|
219
|
+
my_identity = ( $key_list -> (base_identity $key_list),
|
|
220
|
+
$default_keys -> (base_identity $default_keys),
|
|
221
|
+
$container_id -> (base_identity $container_id),
|
|
222
|
+
$e2e_bundle -> e2e::my_public_bundle() ).
|
|
223
|
+
v1_identity = ( $key_list -> (base_identity $key_list),
|
|
224
|
+
$default_keys -> (base_identity $default_keys),
|
|
225
|
+
$container_id -> (base_identity $container_id) ).
|
|
226
|
+
signatures IS crypto_signature(,) = (,).
|
|
227
|
+
hash_v2 = _value_id my_identity.
|
|
228
|
+
hash_v1 = _value_id v1_identity.
|
|
229
|
+
|
|
230
|
+
sc my_identity $key_list -- (key -> ) ?? key_get_function key == $SIGN {
|
|
231
|
+
signatures (key_storage::sign hash_v2 (_crypto_get_key_id key)) -> TRUE.
|
|
232
|
+
signatures (key_storage::sign hash_v1 (_crypto_get_key_id key)) -> TRUE.
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
RETURN ($version->m_current_version, $identity->my_identity, $authorizations->signatures).
|
|
236
|
+
}
|
|
237
|
+
|
|
204
238
|
// The address document to hand a peer, down-levelled when the peer is a v1
|
|
205
239
|
// (pre-E2E) node. peer_is_v1 NIL/FALSE => the current (v2) document (memoised as
|
|
206
240
|
// usual); TRUE => a freshly built v1 document (not memoised). This is the single
|
|
@@ -2,7 +2,9 @@ library node_description loads libraries address_document, container_associated_
|
|
|
2
2
|
metadef t_node_description: identity_proof_document_types::t_node_description.
|
|
3
3
|
|
|
4
4
|
create = fn (_) -> t_node_description {
|
|
5
|
-
|
|
5
|
+
// Transport self-attestation: dual-signed (v2-hash + v1-hash) so both
|
|
6
|
+
// current and pre-e2e_bundle-schema peers can verify the self-signature.
|
|
7
|
+
ad = address_document::produce_transport_address_document().
|
|
6
8
|
associated_data = container_associated_data::create().
|
|
7
9
|
return ($address_document -> ad, $container_associated_data -> associated_data).
|
|
8
10
|
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// Governance wrapper for the per-packet limits primitive.
|
|
2
|
+
//
|
|
3
|
+
// The engine exposes a single dangerous primitive, _set_limits, which mutates the packet's
|
|
4
|
+
// committed limits. It is DANGEROUS, so a packet's code must grab() it to use it. Authorization for
|
|
5
|
+
// a limit change -- who may change limits, and under what conditions -- is entirely the packet
|
|
6
|
+
// developer's policy: this library provides only the MECHANISM (the raw application path), and the
|
|
7
|
+
// engine enforces the hard FLOOR (a change can never exceed the global ceilings). The wrapper does
|
|
8
|
+
// NOT impose or imply any particular authorization model (no built-in signature requirement); the
|
|
9
|
+
// developer composes whatever check their policy needs -- signed request, owner identity, multi-sig,
|
|
10
|
+
// ... -- around set_limits before applying a change. It follows the same inject-a-grabbed-primitive
|
|
11
|
+
// pattern as key_storage (the app grabs _set_limits and calls limits::init to bind it here).
|
|
12
|
+
//
|
|
13
|
+
// The engine primitive validates the {name -> count} dictionary shape, the canonical dimension
|
|
14
|
+
// names, and the [1, ceiling] ranges.
|
|
15
|
+
//
|
|
16
|
+
// Named tiers (for reference; resolved by the ENGINE, not this library): a transaction's source-level
|
|
17
|
+
// limits(...) clause also accepts three vetted bundles by name -- $limits::small, $limits::standard,
|
|
18
|
+
// $limits::heavy -- expanded at compile time by the clause. The engine's resolver is authoritative;
|
|
19
|
+
// the bundles are:
|
|
20
|
+
// $limits::small = { fuel_ops -> 10000, call_depth -> 64, constructed_elems -> 4000 }
|
|
21
|
+
// $limits::standard = { fuel_ops -> 100000, call_depth -> 256, constructed_elems -> 40000 }
|
|
22
|
+
// $limits::heavy = { fuel_ops -> 500000, call_depth -> 1024, constructed_elems -> 200000 }
|
|
23
|
+
// They bound the compute dimensions only; structural dimensions stay at the enclosing effective, and
|
|
24
|
+
// explicit entries after a tier override it pairwise. A conformance unit test pins the engine's
|
|
25
|
+
// value table red-on-drift; if a ratified change lands there, update this doc block to match.
|
|
26
|
+
library limits {
|
|
27
|
+
|
|
28
|
+
hidden {
|
|
29
|
+
// Placeholder for the injected primitive. If a packet calls a limits function without first
|
|
30
|
+
// grabbing _set_limits and injecting it via init, this aborts loudly rather than silently
|
|
31
|
+
// doing nothing.
|
|
32
|
+
_set_limits is (any -> nil) = fn (_: any) -> nil {
|
|
33
|
+
abort "limits: _set_limits primitive was not grabbed and injected (call limits::init)." when TRUE.
|
|
34
|
+
return NIL.
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Bind the grabbed _set_limits primitive. Called once from the packet's code:
|
|
39
|
+
// set = grab(_set_limits). limits::init ($_set_limits -> set).
|
|
40
|
+
init = fn (_:($_set_limits -> set: (any -> nil))) {
|
|
41
|
+
_set_limits -> set.
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Apply a {name -> count} limit change. This library provides the MECHANISM only -- authorization
|
|
45
|
+
// is the packet developer's responsibility: perform whatever check your policy requires (signed
|
|
46
|
+
// request, owner identity, multi-sig, ...) BEFORE calling this. The engine primitive still
|
|
47
|
+
// validates the dictionary shape, the canonical dimension names, and the [1, ceiling] ranges, so
|
|
48
|
+
// a change can never exceed the global ceilings regardless of the caller's policy.
|
|
49
|
+
set_limits = fn (new_limits: any) -> nil {
|
|
50
|
+
_set_limits new_limits.
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Packet-creation defaults. The SDK passes packet-creation options inside the init argument; by
|
|
54
|
+
// convention a packet that wants creation-time default limits reads a `limits` block ({name ->
|
|
55
|
+
// count}, the same shape as set_limits) from its init argument and applies it here, e.g. in the
|
|
56
|
+
// packet's init transaction:
|
|
57
|
+
//
|
|
58
|
+
// set = grab(_set_limits).
|
|
59
|
+
// limits::init ($_set_limits -> set).
|
|
60
|
+
// if (init_arg $limits) != NIL {
|
|
61
|
+
// limits::set_limits (init_arg $limits).
|
|
62
|
+
// }
|
|
63
|
+
//
|
|
64
|
+
// This is a REQUEST TO THE PACKET'S CODE, not an engine feature: a packet whose code ignores the
|
|
65
|
+
// block simply keeps the global defaults. The engine still enforces the [1, ceiling] floor on
|
|
66
|
+
// whatever is applied.
|
|
67
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adapt-toolkit/mufl",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.10",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"description": "The MUFL toolchain: prebuilt `mufl` (REPL) and `mufl-compile` (compiler) engine binaries plus the MUFL stdlib, meta, and transactions trees they need at run time. Linux x64 only; the binaries are proprietary (AEFL) — see LICENSE and NOTICE.",
|
package/prebuilds/linux-x64/mufl
CHANGED
|
Binary file
|
|
Binary file
|
|
@@ -5,7 +5,10 @@
|
|
|
5
5
|
|
|
6
6
|
library __t_wrapper loads libraries transaction, key_storage, transaction_queue, identity_proof_document_types, e2e {
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
// $__limits (optional): the per-call resource budget carried inside the signed message (see
|
|
9
|
+
// transaction::unsigned_message). Kept as `any+` here too so a budgeted message decodes; the
|
|
10
|
+
// engine validates and folds it. Absent = no budget.
|
|
11
|
+
metadef t_trn: ($name->str, $targ->any, $__limits->any+).
|
|
9
12
|
metadef t_trn_extended: ($trn->t_trn, $is_signed->bool, $is_encrypted->bool, $is_e2e->bool+).
|
|
10
13
|
metadef t_trn_message_info: (
|
|
11
14
|
$decoded_envelope -> transaction::envelope::external::decoded_type || t_trn,
|
|
@@ -13,7 +13,12 @@ library transaction loads libraries key_utils, key_storage, identity_proof_docum
|
|
|
13
13
|
// }
|
|
14
14
|
// }
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
// $__limits (optional) is the per-call resource budget: a {name -> count} dictionary the engine
|
|
17
|
+
// folds into this transaction's effective limits (tighten-only). It rides INSIDE the signed
|
|
18
|
+
// message, so it is authenticated input -- a post-sign edit changes the message value-id and
|
|
19
|
+
// fails signature verification. Absent means no per-call budget (unchanged behaviour). The engine
|
|
20
|
+
// validates the dictionary (canonical dimension names, [1, ceiling]); the field type is `any+`.
|
|
21
|
+
metadef unsigned_message: ($name -> str, $targ -> any, $__limits -> any+).
|
|
17
22
|
metadef signed_message: ($trn -> unsigned_message, $ptsignature -> crypto_signature).
|
|
18
23
|
metadef encrypted_pt_signed_message: ($encrypted_message -> crypto_message, $ptsignature -> crypto_signature).
|
|
19
24
|
metadef encrypted_em_signed_message: ($encrypted_message -> crypto_message, $emsignature -> crypto_signature).
|
|
@@ -81,7 +86,7 @@ library transaction loads libraries key_utils, key_storage, identity_proof_docum
|
|
|
81
86
|
}
|
|
82
87
|
|
|
83
88
|
hidden {
|
|
84
|
-
sign = fn (_:($trn -> tn: ($name -> str, $targ -> any))) -> signed_message {
|
|
89
|
+
sign = fn (_:($trn -> tn: ($name -> str, $targ -> any, $__limits -> any+))) -> signed_message {
|
|
85
90
|
signature = key_storage::default_sign (_value_id tn |).
|
|
86
91
|
return ($trn -> tn, $ptsignature -> signature) as signed_message.
|
|
87
92
|
}
|
|
@@ -179,7 +184,7 @@ library transaction loads libraries key_utils, key_storage, identity_proof_docum
|
|
|
179
184
|
return ($result_kind -> results::kind::success, $result -> actions).
|
|
180
185
|
}
|
|
181
186
|
|
|
182
|
-
encrypt = fn (_:($cid -> cid: t_container_id, $trn -> tn: ($name -> str, $targ -> any), $isemsignature -> isem: bool)
|
|
187
|
+
encrypt = fn (_:($cid -> cid: t_container_id, $trn -> tn: ($name -> str, $targ -> any, $__limits -> any+), $isemsignature -> isem: bool)
|
|
183
188
|
) -> encrypted_signed_message
|
|
184
189
|
{
|
|
185
190
|
encrypted_data = key_storage::default_encrypt tn cid.
|