@hazae41/bobine 0.0.6 → 0.0.7
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/README.md +57 -15
- package/out/mod.d.ts +2 -0
- package/out/mod.js +39 -0
- package/out/mods/server/bin.d.ts +1 -1
- package/out/mods/server/bin.js +64 -29
- package/out/mods/server/mod.d.ts +1 -1
- package/package.json +5 -16
package/README.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
A blockchain in your garage
|
|
4
4
|
|
|
5
|
+
https://bobine.tech/
|
|
6
|
+
|
|
5
7
|
## Features
|
|
6
8
|
|
|
7
9
|
- Ultra simple
|
|
@@ -17,10 +19,35 @@ A blockchain in your garage
|
|
|
17
19
|
|
|
18
20
|
### Binary
|
|
19
21
|
|
|
22
|
+
Generate an Ed25519 keypair by running the following code in your browser/Node/Deno console
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
const keypair = await crypto.subtle.generateKey("Ed25519", true, ["sign", "verify"])
|
|
26
|
+
|
|
27
|
+
const privateKey = await crypto.subtle.exportKey("pkcs8", keypair.privateKey)
|
|
28
|
+
|
|
29
|
+
const publicKey = await crypto.subtle.exportKey("raw", keypair.publicKey)
|
|
30
|
+
|
|
31
|
+
console.log(`ED25519_PRIVATE_KEY_HEX=${new Uint8Array(privateKey).toHex()}`)
|
|
32
|
+
|
|
33
|
+
console.log(`ED25519_PUBLIC_KEY_HEX=${new Uint8Array(publicKey).toHex()}`)
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Create an `.env.local` file and replace your Ed25519 values
|
|
37
|
+
|
|
38
|
+
```env
|
|
39
|
+
DATABASE_PATH=./local/database.db
|
|
40
|
+
|
|
41
|
+
SCRIPTS_PATH=./local/scripts
|
|
42
|
+
|
|
43
|
+
ED25519_PRIVATE_KEY_HEX=302e020100300506032b657004220420edff8b2503b91f58bc0f0435ca17de549f89d6a7cde4c277161e031669395005
|
|
44
|
+
ED25519_PUBLIC_KEY_HEX=90dcd81a473a4e59a84df6cb8f77af3d34c7fd6171ed959ca04a75f07a57b4b9
|
|
45
|
+
```
|
|
46
|
+
|
|
20
47
|
Run the server with Deno
|
|
21
48
|
|
|
22
49
|
```bash
|
|
23
|
-
deno run
|
|
50
|
+
deno run -A jsr:@hazae41/bobine serve --env=./.env.local
|
|
24
51
|
```
|
|
25
52
|
|
|
26
53
|
### Library
|
|
@@ -71,16 +98,29 @@ Accepts a form data with the following fields
|
|
|
71
98
|
|
|
72
99
|
## WebAssembly API
|
|
73
100
|
|
|
74
|
-
|
|
101
|
+
The WebAssembly VM extensively uses reference types for its API and for module-to-module communication
|
|
102
|
+
|
|
103
|
+
### AssemblyScript
|
|
104
|
+
|
|
105
|
+
You can use [stdbob](https://github.com/hazae41/stdbob) to easily import AssemblyScript declarations for all internal modules
|
|
106
|
+
|
|
107
|
+
Or you can declare internal modules manually with the module name and method name
|
|
75
108
|
|
|
76
|
-
|
|
109
|
+
```tsx
|
|
110
|
+
@external("bigints", "add")
|
|
111
|
+
declare function add(x: externref, y: externref): externref
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
And you can declare external modules by using the module address as hex
|
|
77
115
|
|
|
78
116
|
```tsx
|
|
79
117
|
@external("5feeee846376f6436990aa2757bc67fbc4498bcc9993b647788e273ad6fde474", "add")
|
|
80
|
-
declare function add(x:
|
|
118
|
+
declare function add(x: externref, y: externref): externref
|
|
81
119
|
```
|
|
82
120
|
|
|
83
|
-
###
|
|
121
|
+
### All internal modules
|
|
122
|
+
|
|
123
|
+
#### blobs
|
|
84
124
|
|
|
85
125
|
You can pass bytes between modules by storing them in the blob storage and loading them via reference
|
|
86
126
|
|
|
@@ -94,7 +134,7 @@ You can pass bytes between modules by storing them in the blob storage and loadi
|
|
|
94
134
|
|
|
95
135
|
- `blob.to_hex/from_hex/to_base64/from_base64(blob: blobref): blobref` = convert blobs to/from hex/base64 without loading them into memory
|
|
96
136
|
|
|
97
|
-
|
|
137
|
+
#### bigints
|
|
98
138
|
|
|
99
139
|
You can work with infinite-precision bigints
|
|
100
140
|
|
|
@@ -120,7 +160,7 @@ You can work with infinite-precision bigints
|
|
|
120
160
|
|
|
121
161
|
- `bigints.from_base10(base16: blobref): bigintref` = convert base10 utf8 bytes to bigint
|
|
122
162
|
|
|
123
|
-
|
|
163
|
+
#### packs
|
|
124
164
|
|
|
125
165
|
You can pack various arguments (numbers, refs) into a pack which can be passed between modules and/or encoded/decoded into bytes
|
|
126
166
|
|
|
@@ -175,7 +215,9 @@ function writePack(pack: packref) {
|
|
|
175
215
|
|
|
176
216
|
- `packs.get<T>(pack: packref, index: i32): T` = get the value of a pack at `index` (throws if not found)
|
|
177
217
|
|
|
178
|
-
|
|
218
|
+
- `packs.length(pack: packref): i32` = get the length of a pack
|
|
219
|
+
|
|
220
|
+
#### env
|
|
179
221
|
|
|
180
222
|
Get infos about the executing environment
|
|
181
223
|
|
|
@@ -183,7 +225,7 @@ Get infos about the executing environment
|
|
|
183
225
|
|
|
184
226
|
- `env.uuid(): blobref` = get the unique uuid of this environment (similar to a chain id)
|
|
185
227
|
|
|
186
|
-
|
|
228
|
+
#### modules
|
|
187
229
|
|
|
188
230
|
Modules are identified by their address as a blob of bytes (pure sha256-output 32-length bytes without any encoding)
|
|
189
231
|
|
|
@@ -195,7 +237,7 @@ Modules are identified by their address as a blob of bytes (pure sha256-output 3
|
|
|
195
237
|
|
|
196
238
|
- `modules.self(): blobref` = get your module address as blob
|
|
197
239
|
|
|
198
|
-
|
|
240
|
+
#### storage
|
|
199
241
|
|
|
200
242
|
You can use a private storage (it works like storage and events at the same time)
|
|
201
243
|
|
|
@@ -203,13 +245,13 @@ You can use a private storage (it works like storage and events at the same time
|
|
|
203
245
|
|
|
204
246
|
- `storage.get(key: blobref): blobref` = get the latest value from storage at key
|
|
205
247
|
|
|
206
|
-
|
|
248
|
+
#### sha256
|
|
207
249
|
|
|
208
250
|
Use the SHA-256 hashing algorithm
|
|
209
251
|
|
|
210
252
|
- `sha256.digest(payload: blobref): blobref` = hash the payload and returns the digest
|
|
211
253
|
|
|
212
|
-
|
|
254
|
+
#### ed25519
|
|
213
255
|
|
|
214
256
|
Use the Ed25519 signing algorithm
|
|
215
257
|
|
|
@@ -217,11 +259,11 @@ Use the Ed25519 signing algorithm
|
|
|
217
259
|
|
|
218
260
|
- `ed25519.sign(payload: blobref): blobref` = (experimental) sign payload using the miner's private key
|
|
219
261
|
|
|
220
|
-
|
|
262
|
+
#### symbols (experimental)
|
|
221
263
|
|
|
222
264
|
- `symbols.create(): symbolref` = create a unique reference that can be passed around
|
|
223
265
|
|
|
224
|
-
|
|
266
|
+
#### refs (experimental)
|
|
225
267
|
|
|
226
268
|
- `refs.numerize(ref: symbolref/blobref/packref): i32` = translate any reference into a unique private pointer that can be stored into data structures
|
|
227
269
|
|
|
@@ -245,4 +287,4 @@ export function verify(session: symbolref) {
|
|
|
245
287
|
}
|
|
246
288
|
```
|
|
247
289
|
|
|
248
|
-
You should never accept a pointer instead of a real reference because they can be easily guessed by an attacking module
|
|
290
|
+
You should never accept a pointer instead of a real reference because they can be easily guessed by an attacking module
|
package/out/mod.d.ts
CHANGED
package/out/mod.js
CHANGED
|
@@ -1 +1,40 @@
|
|
|
1
|
+
#!/usr/bin/env deno
|
|
1
2
|
export * from "./mods/mod.js";
|
|
3
|
+
import process from "node:process";
|
|
4
|
+
import * as server from "./mods/server/bin.js";
|
|
5
|
+
export async function main(args) {
|
|
6
|
+
const subargs = new Array();
|
|
7
|
+
for (let i = 0; i < args.length; i++) {
|
|
8
|
+
const arg = args[i];
|
|
9
|
+
if (arg.startsWith("--")) {
|
|
10
|
+
subargs.push(arg);
|
|
11
|
+
continue;
|
|
12
|
+
}
|
|
13
|
+
if (arg === "serve") {
|
|
14
|
+
subargs.push(...args.slice(i + 1));
|
|
15
|
+
await server.main(subargs);
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
if (arg === "create") {
|
|
19
|
+
console.log("Create command is not implemented yet.");
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
if (arg === "execute") {
|
|
23
|
+
console.log("Execute command is not implemented yet.");
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
if (arg === "simulate") {
|
|
27
|
+
console.log("Simulate command is not implemented yet.");
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
break;
|
|
31
|
+
}
|
|
32
|
+
console.log("- serve [--env=<env file as path>] [--port=<port>] [--dev]");
|
|
33
|
+
console.log("- create <wasm file as path> [salt as hex]");
|
|
34
|
+
console.log("- execute <module as hex> <function name> [args as pack as hex]");
|
|
35
|
+
console.log("- simulate <module as hex> <function name> [args as pack as hex]");
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (import.meta.main) {
|
|
39
|
+
await main(process.argv.slice(2));
|
|
40
|
+
}
|
package/out/mods/server/bin.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export declare function main(args: string[]): Promise<void>;
|
package/out/mods/server/bin.js
CHANGED
|
@@ -1,34 +1,69 @@
|
|
|
1
1
|
import { readFileSync } from "node:fs";
|
|
2
2
|
import process from "node:process";
|
|
3
3
|
import { serveWithEnv } from "./mod.js";
|
|
4
|
-
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
4
|
+
export async function main(args) {
|
|
5
|
+
const config = {};
|
|
6
|
+
for (let i = 0; i < args.length; i++) {
|
|
7
|
+
const arg = args[i];
|
|
8
|
+
if (arg.startsWith("--env=")) {
|
|
9
|
+
process.loadEnvFile(arg.slice("--env=".length));
|
|
10
|
+
continue;
|
|
11
|
+
}
|
|
12
|
+
if (arg.startsWith("--port=")) {
|
|
13
|
+
config.port = Number(arg.slice("--port=".length));
|
|
14
|
+
continue;
|
|
15
|
+
}
|
|
16
|
+
if (arg.startsWith("--cert=")) {
|
|
17
|
+
config.cert = readFileSync(arg.slice("--cert=".length), "utf8");
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
if (arg.startsWith("--key=")) {
|
|
21
|
+
config.key = readFileSync(arg.slice("--key=".length), "utf8");
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
if (arg === "--dev=true") {
|
|
25
|
+
process.env.NODE_ENV = "development";
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
if (arg === "--dev=false") {
|
|
29
|
+
process.env.NODE_ENV = "production";
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
if (arg === "--dev") {
|
|
33
|
+
process.env.NODE_ENV = "development";
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
throw new Error(`Unknown argument: ${arg}`);
|
|
16
37
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
if (
|
|
38
|
+
const { port = Number(process.env.PORT) || 8080, cert = process.env.CERT != null ? readFileSync(process.env.CERT, "utf8") : undefined, key = process.env.KEY != null ? readFileSync(process.env.KEY, "utf8") : undefined, } = config;
|
|
39
|
+
const server = await serveWithEnv();
|
|
40
|
+
const route = async (request) => {
|
|
41
|
+
if (request.method === "OPTIONS")
|
|
42
|
+
return new Response(null, { status: 204 });
|
|
43
|
+
if (request.headers.get("Upgrade") === "websocket") {
|
|
44
|
+
const { socket, response } = Deno.upgradeWebSocket(request);
|
|
45
|
+
await server.onWebSocketRequest(request, socket);
|
|
23
46
|
return response;
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
47
|
+
}
|
|
48
|
+
return await server.onHttpRequest(request);
|
|
49
|
+
};
|
|
50
|
+
const onHttpRequest = async (request) => {
|
|
51
|
+
try {
|
|
52
|
+
const response = await route(request);
|
|
53
|
+
if (response.status === 101)
|
|
54
|
+
return response;
|
|
55
|
+
response.headers.set("Access-Control-Allow-Origin", "*");
|
|
56
|
+
response.headers.set("Access-Control-Allow-Methods", "*");
|
|
57
|
+
response.headers.set("Access-Control-Allow-Headers", "*");
|
|
58
|
+
return response;
|
|
59
|
+
}
|
|
60
|
+
catch (cause) {
|
|
61
|
+
console.error(cause);
|
|
62
|
+
return new Response("Error", { status: 500 });
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
Deno.serve({ hostname: "0.0.0.0", port, cert, key }, onHttpRequest);
|
|
66
|
+
}
|
|
67
|
+
if (import.meta.main) {
|
|
68
|
+
await main(process.argv.slice(2));
|
|
69
|
+
}
|
package/out/mods/server/mod.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Config } from "../config/mod.ts";
|
|
1
|
+
import type { Config } from "../config/mod.ts";
|
|
2
2
|
export declare function serveWithEnv(prefix?: string): Promise<{
|
|
3
3
|
onHttpRequest(request: Request): Promise<Response>;
|
|
4
4
|
onWebSocketRequest(request: Request, socket: WebSocket): Promise<void>;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@hazae41/bobine",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.7",
|
|
5
5
|
"description": "A blockchain in your garage",
|
|
6
6
|
"repository": "github:hazae41/bobine",
|
|
7
7
|
"author": "hazae41",
|
|
@@ -11,7 +11,8 @@
|
|
|
11
11
|
"version": "deno -RW ./x.vsync.ts && git add deno.json",
|
|
12
12
|
"prepare": "deno -RW ./x.dsync.ts && deno install",
|
|
13
13
|
"prepack": "rm -rf ./out && tsc && tscousin",
|
|
14
|
-
"
|
|
14
|
+
"produce": "deno run -A ./src/bin.ts serve --env=./.env.local",
|
|
15
|
+
"develop": "deno run -A ./src/bin.ts serve --env=./.env.local --dev"
|
|
15
16
|
},
|
|
16
17
|
"files": [
|
|
17
18
|
"./out"
|
|
@@ -20,18 +21,6 @@
|
|
|
20
21
|
".": {
|
|
21
22
|
"types": "./out/mod.d.ts",
|
|
22
23
|
"import": "./out/mod.js"
|
|
23
|
-
},
|
|
24
|
-
"./server": {
|
|
25
|
-
"types": "./out/mods/server/bin.d.ts",
|
|
26
|
-
"import": "./out/mods/server/bin.js"
|
|
27
|
-
},
|
|
28
|
-
"./worker": {
|
|
29
|
-
"types": "./out/mods/worker/bin.d.ts",
|
|
30
|
-
"import": "./out/mods/worker/bin.js"
|
|
31
|
-
},
|
|
32
|
-
"./helper": {
|
|
33
|
-
"types": "./out/mods/helper/bin.d.ts",
|
|
34
|
-
"import": "./out/mods/helper/bin.js"
|
|
35
24
|
}
|
|
36
25
|
},
|
|
37
26
|
"dependencies": {
|
|
@@ -45,7 +34,7 @@
|
|
|
45
34
|
"devDependencies": {
|
|
46
35
|
"@hazae41/phobos": "^2.0.16",
|
|
47
36
|
"@hazae41/tscousin": "^1.0.28",
|
|
48
|
-
"@types/node": "^
|
|
37
|
+
"@types/node": "^25.0.2",
|
|
49
38
|
"typescript": "^5.9.3"
|
|
50
39
|
},
|
|
51
40
|
"keywords": [
|
|
@@ -57,6 +46,6 @@
|
|
|
57
46
|
"unit-tested"
|
|
58
47
|
],
|
|
59
48
|
"bin": {
|
|
60
|
-
"bobine": "./out/
|
|
49
|
+
"bobine": "./out/bin.js"
|
|
61
50
|
}
|
|
62
51
|
}
|