@crowdedkingdoms/ckx-kit 0.0.0-stage → 0.1.0-dev.1
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/LICENSE-APACHE +176 -0
- package/LICENSE-MIT +21 -0
- package/README.md +76 -2
- package/checks/compute-toolchain/host-catalog.json +68 -0
- package/crates/ckx-sdk/Cargo.toml +17 -0
- package/crates/ckx-sdk/LICENSE-APACHE +176 -0
- package/crates/ckx-sdk/LICENSE-MIT +21 -0
- package/crates/ckx-sdk/README.md +47 -0
- package/crates/ckx-sdk/src/abi.rs +115 -0
- package/crates/ckx-sdk/src/cron.rs +717 -0
- package/crates/ckx-sdk/src/emit.rs +140 -0
- package/crates/ckx-sdk/src/lib.rs +588 -0
- package/crates/ckx-sdk/src/model.rs +482 -0
- package/crates/ckx-sdk/src/node.rs +942 -0
- package/crates/ckx-sdk/src/rt.rs +519 -0
- package/crates/crowdy-client-sdk/Cargo.toml +15 -0
- package/crates/crowdy-client-sdk/LICENSE-APACHE +176 -0
- package/crates/crowdy-client-sdk/LICENSE-MIT +21 -0
- package/crates/crowdy-client-sdk/README.md +25 -0
- package/crates/crowdy-client-sdk/src/lib.rs +698 -0
- package/dist/checks/src/build/client-capabilities.js +123 -0
- package/dist/checks/src/build/exec-source.js +343 -0
- package/dist/checks/src/build/rust-source-guard.js +165 -0
- package/dist/checks/src/build/wasm-inspect.js +249 -0
- package/dist/cli/src/build.js +99 -0
- package/dist/cli/src/crate.js +64 -0
- package/dist/cli/src/doctor.js +51 -0
- package/dist/cli/src/kit.js +66 -0
- package/dist/cli/src/main.js +109 -0
- package/dist/cli/src/new.js +74 -0
- package/dist/cli/src/tools.js +104 -0
- package/kit.pin +9 -0
- package/package.json +81 -4
- package/rust-toolchain.toml +6 -0
- package/starters/ckx.json +9 -0
- package/starters/grid-mod/Cargo.toml +13 -0
- package/starters/grid-mod/src/lib.rs +82 -0
- package/starters/matchmaker/Cargo.toml +13 -0
- package/starters/matchmaker/src/lib.rs +362 -0
- package/starters/npc-mobs/Cargo.toml +14 -0
- package/starters/npc-mobs/src/lib.rs +469 -0
- package/starters/session/Cargo.toml +13 -0
- package/starters/session/src/lib.rs +395 -0
- package/starters/world-tick/Cargo.toml +14 -0
- package/starters/world-tick/src/lib.rs +346 -0
- package/templates/client/Cargo.toml +16 -0
- package/templates/client/src/lib.rs +31 -0
- package/templates/hub/Cargo.toml +11 -0
- package/templates/hub/src/lib.rs +73 -0
- package/templates/spoke/Cargo.toml +11 -0
- package/templates/spoke/src/lib.rs +53 -0
- package/tools/instrument/Cargo.lock +140 -0
- package/tools/instrument/Cargo.toml +11 -0
- package/tools/instrument/src/main.rs +165 -0
- package/vendor.lock +167 -0
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
//! Compute-module instrumentation CLI (production version of the Phase 0
|
|
2
|
+
//! spike tool). Pipeline stage between `cargo build` and `wasm-opt`:
|
|
3
|
+
//!
|
|
4
|
+
//! Usage: instrument <input.wasm> <output.wasm> [--max-memory-mb N]
|
|
5
|
+
//!
|
|
6
|
+
//! 1. Validates the module's import surface against the platform allowlist
|
|
7
|
+
//! (the `ck` host API + the minimal deterministic WASI stub set).
|
|
8
|
+
//! 2. Clamps the module's linear-memory maximum to `--max-memory-mb` (worker
|
|
9
|
+
//! resourceLimits do NOT cover wasm memory — this is the real cap).
|
|
10
|
+
//! 3. Injects mutable-global gas metering (exported global `ck_fuel`):
|
|
11
|
+
//! every metered block decrements the global; on exhaustion the global is
|
|
12
|
+
//! set to the u64::MAX sentinel and the module traps (`unreachable`).
|
|
13
|
+
//! The host sets/reads `ck_fuel` around each entry call.
|
|
14
|
+
|
|
15
|
+
use anyhow::{bail, Context, Result};
|
|
16
|
+
use radix_wasm_instrument::gas_metering::{inject, mutable_global, ConstantCostRules};
|
|
17
|
+
use radix_wasm_instrument::utils::module_info::ModuleInfo;
|
|
18
|
+
use wasmparser::{Parser, Payload, TypeRef};
|
|
19
|
+
|
|
20
|
+
const WASM_PAGE_BYTES: u64 = 65536;
|
|
21
|
+
|
|
22
|
+
const ALLOWED_CK_IMPORTS: &[&str] =
|
|
23
|
+
&["log", "now_ms", "state_get", "state_set", "host_call"];
|
|
24
|
+
const ALLOWED_WASI_IMPORTS: &[&str] = &[
|
|
25
|
+
"environ_get",
|
|
26
|
+
"environ_sizes_get",
|
|
27
|
+
"fd_write",
|
|
28
|
+
"proc_exit",
|
|
29
|
+
"clock_time_get",
|
|
30
|
+
"random_get",
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
fn validate_imports(wasm: &[u8]) -> Result<()> {
|
|
34
|
+
for payload in Parser::new(0).parse_all(wasm) {
|
|
35
|
+
if let Payload::ImportSection(reader) = payload? {
|
|
36
|
+
for import in reader {
|
|
37
|
+
let import = import?;
|
|
38
|
+
if !matches!(import.ty, TypeRef::Func(_)) {
|
|
39
|
+
bail!("non-function import {}::{} not allowed", import.module, import.name);
|
|
40
|
+
}
|
|
41
|
+
let allowed = match import.module {
|
|
42
|
+
"ck" => ALLOWED_CK_IMPORTS.contains(&import.name),
|
|
43
|
+
"wasi_snapshot_preview1" => ALLOWED_WASI_IMPORTS.contains(&import.name),
|
|
44
|
+
_ => false,
|
|
45
|
+
};
|
|
46
|
+
if !allowed {
|
|
47
|
+
bail!("import {}::{} not in allowlist", import.module, import.name);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
Ok(())
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/// Rewrite the memory section so every defined memory carries a maximum of at
|
|
56
|
+
/// most `max_pages`. Rebuilds just the memory section bytes and splices them
|
|
57
|
+
/// into the module (sections are independently sized, so this is safe).
|
|
58
|
+
fn clamp_memory(wasm: &[u8], max_pages: u64) -> Result<Vec<u8>> {
|
|
59
|
+
let mut mem_section_range: Option<std::ops::Range<usize>> = None;
|
|
60
|
+
let mut memories: Vec<wasmparser::MemoryType> = Vec::new();
|
|
61
|
+
|
|
62
|
+
for payload in Parser::new(0).parse_all(wasm) {
|
|
63
|
+
if let Payload::MemorySection(reader) = payload? {
|
|
64
|
+
mem_section_range = Some(reader.range());
|
|
65
|
+
for mem in reader {
|
|
66
|
+
memories.push(mem?);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
let Some(range) = mem_section_range else {
|
|
71
|
+
// No defined memory (e.g. imported) -- nothing to clamp; the import
|
|
72
|
+
// gate already rejects non-function imports, so this cannot happen
|
|
73
|
+
// for accepted modules.
|
|
74
|
+
return Ok(wasm.to_vec());
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
let mut section = wasm_encoder::MemorySection::new();
|
|
78
|
+
for mem in &memories {
|
|
79
|
+
if mem.memory64 || mem.shared {
|
|
80
|
+
bail!("memory64/shared memories are not allowed");
|
|
81
|
+
}
|
|
82
|
+
if mem.initial > max_pages {
|
|
83
|
+
bail!(
|
|
84
|
+
"module declares initial memory of {} pages (> clamp of {} pages)",
|
|
85
|
+
mem.initial,
|
|
86
|
+
max_pages
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
let clamped_max = mem.maximum.map_or(max_pages, |m| m.min(max_pages));
|
|
90
|
+
section.memory(wasm_encoder::MemoryType {
|
|
91
|
+
minimum: mem.initial,
|
|
92
|
+
maximum: Some(clamped_max),
|
|
93
|
+
memory64: false,
|
|
94
|
+
shared: false,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Encode the replacement section (id byte + LEB size + payload).
|
|
99
|
+
let mut replacement = Vec::new();
|
|
100
|
+
wasm_encoder::Section::append_to(§ion, &mut replacement);
|
|
101
|
+
|
|
102
|
+
// `range` covers the section payload (not the id/size header). Locate the
|
|
103
|
+
// header: it ends where the payload begins. The id byte for the memory
|
|
104
|
+
// section is 5; scan backwards over the LEB128 size.
|
|
105
|
+
let payload_start = range.start;
|
|
106
|
+
let mut header_start = payload_start - 1;
|
|
107
|
+
// size LEB: walk back while continuation bit set on the previous byte.
|
|
108
|
+
while header_start > 0 && wasm[header_start - 1] & 0x80 != 0 {
|
|
109
|
+
header_start -= 1;
|
|
110
|
+
}
|
|
111
|
+
header_start -= 1; // the section id byte
|
|
112
|
+
if wasm[header_start] != 5 {
|
|
113
|
+
bail!("failed to locate memory section header");
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
let mut out = Vec::with_capacity(wasm.len() + 8);
|
|
117
|
+
out.extend_from_slice(&wasm[..header_start]);
|
|
118
|
+
out.extend_from_slice(&replacement);
|
|
119
|
+
out.extend_from_slice(&wasm[range.end..]);
|
|
120
|
+
Ok(out)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
fn main() -> Result<()> {
|
|
124
|
+
let args: Vec<String> = std::env::args().collect();
|
|
125
|
+
let (input, output, max_memory_mb) = match args.as_slice() {
|
|
126
|
+
[_, i, o] => (i.clone(), o.clone(), 64u64),
|
|
127
|
+
[_, i, o, flag, n] if flag == "--max-memory-mb" => (
|
|
128
|
+
i.clone(),
|
|
129
|
+
o.clone(),
|
|
130
|
+
n.parse::<u64>().context("parsing --max-memory-mb")?,
|
|
131
|
+
),
|
|
132
|
+
_ => bail!("usage: instrument <input.wasm> <output.wasm> [--max-memory-mb N]"),
|
|
133
|
+
};
|
|
134
|
+
if max_memory_mb == 0 {
|
|
135
|
+
bail!("--max-memory-mb must be >= 1");
|
|
136
|
+
}
|
|
137
|
+
let max_pages = (max_memory_mb * 1024 * 1024) / WASM_PAGE_BYTES;
|
|
138
|
+
|
|
139
|
+
let wasm = std::fs::read(&input).with_context(|| format!("reading {input}"))?;
|
|
140
|
+
validate_imports(&wasm)?;
|
|
141
|
+
let clamped = clamp_memory(&wasm, max_pages)?;
|
|
142
|
+
wasmparser::validate(&clamped).context("validating memory-clamped module")?;
|
|
143
|
+
|
|
144
|
+
let mut info =
|
|
145
|
+
ModuleInfo::new(&clamped).map_err(|e| anyhow::anyhow!("parsing module: {e:?}"))?;
|
|
146
|
+
let backend = mutable_global::Injector::new("env", "ck_fuel");
|
|
147
|
+
// Uniform cost of 1 per instruction; production per-instruction weights
|
|
148
|
+
// are Phase 10 load-test work (the fuel scale is calibrated in policy).
|
|
149
|
+
let instrumented = inject(&mut info, backend, &ConstantCostRules::default())
|
|
150
|
+
.context("injecting gas metering")?;
|
|
151
|
+
|
|
152
|
+
wasmparser::validate(&instrumented).context("validating instrumented module")?;
|
|
153
|
+
|
|
154
|
+
std::fs::write(&output, &instrumented).with_context(|| format!("writing {output}"))?;
|
|
155
|
+
eprintln!(
|
|
156
|
+
"instrumented {} ({} bytes) -> {} ({} bytes, +{:.1}%, memory max {} pages)",
|
|
157
|
+
input,
|
|
158
|
+
wasm.len(),
|
|
159
|
+
output,
|
|
160
|
+
instrumented.len(),
|
|
161
|
+
(instrumented.len() as f64 / wasm.len() as f64 - 1.0) * 100.0,
|
|
162
|
+
max_pages
|
|
163
|
+
);
|
|
164
|
+
Ok(())
|
|
165
|
+
}
|
package/vendor.lock
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
# This file is automatically @generated by Cargo.
|
|
2
|
+
# It is not intended for manual editing.
|
|
3
|
+
version = 4
|
|
4
|
+
|
|
5
|
+
[[package]]
|
|
6
|
+
name = "autocfg"
|
|
7
|
+
version = "1.5.1"
|
|
8
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
9
|
+
checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"
|
|
10
|
+
|
|
11
|
+
[[package]]
|
|
12
|
+
name = "base64"
|
|
13
|
+
version = "0.22.1"
|
|
14
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
15
|
+
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
|
|
16
|
+
|
|
17
|
+
[[package]]
|
|
18
|
+
name = "ckx-sdk"
|
|
19
|
+
version = "0.8.0"
|
|
20
|
+
dependencies = [
|
|
21
|
+
"base64",
|
|
22
|
+
"rmp-serde",
|
|
23
|
+
"serde",
|
|
24
|
+
"serde_json",
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
[[package]]
|
|
28
|
+
name = "crowdy-client-sdk"
|
|
29
|
+
version = "0.1.0"
|
|
30
|
+
dependencies = [
|
|
31
|
+
"serde",
|
|
32
|
+
"serde_json",
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
[[package]]
|
|
36
|
+
name = "itoa"
|
|
37
|
+
version = "1.0.18"
|
|
38
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
39
|
+
checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
|
|
40
|
+
|
|
41
|
+
[[package]]
|
|
42
|
+
name = "memchr"
|
|
43
|
+
version = "2.8.3"
|
|
44
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
45
|
+
checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
|
|
46
|
+
|
|
47
|
+
[[package]]
|
|
48
|
+
name = "num-traits"
|
|
49
|
+
version = "0.2.19"
|
|
50
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
51
|
+
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
|
52
|
+
dependencies = [
|
|
53
|
+
"autocfg",
|
|
54
|
+
]
|
|
55
|
+
|
|
56
|
+
[[package]]
|
|
57
|
+
name = "proc-macro2"
|
|
58
|
+
version = "1.0.107"
|
|
59
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
60
|
+
checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9"
|
|
61
|
+
dependencies = [
|
|
62
|
+
"unicode-ident",
|
|
63
|
+
]
|
|
64
|
+
|
|
65
|
+
[[package]]
|
|
66
|
+
name = "quote"
|
|
67
|
+
version = "1.0.47"
|
|
68
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
69
|
+
checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001"
|
|
70
|
+
dependencies = [
|
|
71
|
+
"proc-macro2",
|
|
72
|
+
]
|
|
73
|
+
|
|
74
|
+
[[package]]
|
|
75
|
+
name = "rmp"
|
|
76
|
+
version = "0.8.15"
|
|
77
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
78
|
+
checksum = "4ba8be72d372b2c9b35542551678538b562e7cf86c3315773cae48dfbfe7790c"
|
|
79
|
+
dependencies = [
|
|
80
|
+
"num-traits",
|
|
81
|
+
]
|
|
82
|
+
|
|
83
|
+
[[package]]
|
|
84
|
+
name = "rmp-serde"
|
|
85
|
+
version = "1.3.1"
|
|
86
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
87
|
+
checksum = "72f81bee8c8ef9b577d1681a70ebbc962c232461e397b22c208c43c04b67a155"
|
|
88
|
+
dependencies = [
|
|
89
|
+
"rmp",
|
|
90
|
+
"serde",
|
|
91
|
+
]
|
|
92
|
+
|
|
93
|
+
[[package]]
|
|
94
|
+
name = "serde"
|
|
95
|
+
version = "1.0.229"
|
|
96
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
97
|
+
checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba"
|
|
98
|
+
dependencies = [
|
|
99
|
+
"serde_core",
|
|
100
|
+
"serde_derive",
|
|
101
|
+
]
|
|
102
|
+
|
|
103
|
+
[[package]]
|
|
104
|
+
name = "serde_core"
|
|
105
|
+
version = "1.0.229"
|
|
106
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
107
|
+
checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48"
|
|
108
|
+
dependencies = [
|
|
109
|
+
"serde_derive",
|
|
110
|
+
]
|
|
111
|
+
|
|
112
|
+
[[package]]
|
|
113
|
+
name = "serde_derive"
|
|
114
|
+
version = "1.0.229"
|
|
115
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
116
|
+
checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348"
|
|
117
|
+
dependencies = [
|
|
118
|
+
"proc-macro2",
|
|
119
|
+
"quote",
|
|
120
|
+
"syn",
|
|
121
|
+
]
|
|
122
|
+
|
|
123
|
+
[[package]]
|
|
124
|
+
name = "serde_json"
|
|
125
|
+
version = "1.0.151"
|
|
126
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
127
|
+
checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14"
|
|
128
|
+
dependencies = [
|
|
129
|
+
"itoa",
|
|
130
|
+
"memchr",
|
|
131
|
+
"serde",
|
|
132
|
+
"serde_core",
|
|
133
|
+
"zmij",
|
|
134
|
+
]
|
|
135
|
+
|
|
136
|
+
[[package]]
|
|
137
|
+
name = "syn"
|
|
138
|
+
version = "3.0.6"
|
|
139
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
140
|
+
checksum = "8593e8e72159ed2257d083c7a454a85cbf854f37a0966d8d483aff8c8a3ebcee"
|
|
141
|
+
dependencies = [
|
|
142
|
+
"proc-macro2",
|
|
143
|
+
"quote",
|
|
144
|
+
"unicode-ident",
|
|
145
|
+
]
|
|
146
|
+
|
|
147
|
+
[[package]]
|
|
148
|
+
name = "unicode-ident"
|
|
149
|
+
version = "1.0.26"
|
|
150
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
151
|
+
checksum = "d245f478577f809a851594d02313b640fb437e0bb33866753cff937863096954"
|
|
152
|
+
|
|
153
|
+
[[package]]
|
|
154
|
+
name = "vendor-superset"
|
|
155
|
+
version = "0.0.1"
|
|
156
|
+
dependencies = [
|
|
157
|
+
"ckx-sdk",
|
|
158
|
+
"crowdy-client-sdk",
|
|
159
|
+
"serde",
|
|
160
|
+
"serde_json",
|
|
161
|
+
]
|
|
162
|
+
|
|
163
|
+
[[package]]
|
|
164
|
+
name = "zmij"
|
|
165
|
+
version = "1.0.23"
|
|
166
|
+
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
167
|
+
checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b"
|