wao 0.29.3 → 0.30.2
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/cjs/ao.js +33 -10
- package/cjs/hb.js +500 -367
- package/cjs/hyperbeam.js +14 -8
- package/cjs/id.js +260 -24
- package/cjs/signer.js +14 -5
- package/cjs/utils.js +22 -3
- package/cjs/workspace/test/hyperbeam.js +8 -5
- package/esm/ao.js +1 -1
- package/esm/hb.js +51 -10
- package/esm/hyperbeam.js +22 -11
- package/esm/id.js +258 -21
- package/esm/signer.js +5 -4
- package/esm/utils.js +1 -7
- package/esm/workspace/test/hyperbeam.js +8 -5
- package/package.json +5 -1
package/cjs/hyperbeam.js
CHANGED
|
@@ -43,9 +43,10 @@ var HyperBEAM = exports["default"] = /*#__PURE__*/function () {
|
|
|
43
43
|
c = _ref.c,
|
|
44
44
|
cmake = _ref.cmake,
|
|
45
45
|
faff = _ref.faff,
|
|
46
|
-
_ref$
|
|
47
|
-
|
|
48
|
-
|
|
46
|
+
_ref$simple_pay = _ref.simple_pay,
|
|
47
|
+
simple_pay = _ref$simple_pay === void 0 ? false : _ref$simple_pay,
|
|
48
|
+
simple_pay_price = _ref.simple_pay_price,
|
|
49
|
+
p4_non_chargable_routes = _ref.p4_non_chargable_routes,
|
|
49
50
|
p4_lua = _ref.p4_lua,
|
|
50
51
|
store_prefix = _ref.store_prefix,
|
|
51
52
|
operator = _ref.operator,
|
|
@@ -56,6 +57,7 @@ var HyperBEAM = exports["default"] = /*#__PURE__*/function () {
|
|
|
56
57
|
devices = _ref.devices;
|
|
57
58
|
_classCallCheck(this, HyperBEAM);
|
|
58
59
|
this.devices = devices;
|
|
60
|
+
this.p4_non_chargable_routes = p4_non_chargable_routes;
|
|
59
61
|
(_as2 = as) !== null && _as2 !== void 0 ? _as2 : as = shell ? [] : ["genesis_wasm"];
|
|
60
62
|
this.console = console;
|
|
61
63
|
if (clearCache) {
|
|
@@ -85,8 +87,8 @@ var HyperBEAM = exports["default"] = /*#__PURE__*/function () {
|
|
|
85
87
|
this.cu = cu;
|
|
86
88
|
this.store_prefix = store_prefix ? "cache-mainnet-" + Math.floor(Math.random() * 10000000) : "cache-mainnet";
|
|
87
89
|
this.p4_lua = p4_lua;
|
|
88
|
-
this.
|
|
89
|
-
this.spp =
|
|
90
|
+
this.simple_pay = simple_pay;
|
|
91
|
+
this.spp = simple_pay_price;
|
|
90
92
|
this.operator = operator;
|
|
91
93
|
this.faff = faff;
|
|
92
94
|
this.c = c;
|
|
@@ -311,7 +313,9 @@ var HyperBEAM = exports["default"] = /*#__PURE__*/function () {
|
|
|
311
313
|
try {
|
|
312
314
|
for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
|
|
313
315
|
var v = _step4.value;
|
|
314
|
-
if (
|
|
316
|
+
if (_typeof(v) === "object") {
|
|
317
|
+
_devs.push("#{<<\"name\">> => <<\"".concat(v.name, "\">>, <<\"module\">> => ").concat(v.module, "}"));
|
|
318
|
+
} else if (_devs2["default"][v]) _devs.push("#{<<\"name\">> => <<\"".concat(_devs2["default"][v].name, "\">>, <<\"module\">> => ").concat(_devs2["default"][v].module, "}"));
|
|
315
319
|
}
|
|
316
320
|
} catch (err) {
|
|
317
321
|
_iterator4.e(err);
|
|
@@ -329,7 +333,9 @@ var HyperBEAM = exports["default"] = /*#__PURE__*/function () {
|
|
|
329
333
|
/*
|
|
330
334
|
const _routes = `, routes => [#{ <<"template">> => <<"/result/.*">>, <<"node">> => #{ <<"prefix">> => <<"http://localhost:${this.cu}">> } }, #{ <<\"template\">> => <<\"/dry-run\">>, <<\"node\">> => #{ <<\"prefix\">> => <<\"http://localhost:${this.cu}\">> } }, #{ <<"template">> => <<"/graphql">>, <<"nodes">> => [#{ <<"prefix">> => <<"http://localhost:${gateway}">>, <<"opts">> => #{ http_client => httpc, protocol => http2 } }, #{ <<"prefix">> => <<"http://localhost:${gateway}">>, <<"opts">> => #{ http_client => gun, protocol => http2 } }] }, #{ <<"template">> => <<"/raw">>, <<"node">> => #{ <<"prefix">> => <<"http://localhost:${gateway}">>, <<"opts">> => #{ http_client => gun, protocol => http2 } } }]`
|
|
331
335
|
*/
|
|
332
|
-
var _p4_non_chargable = this.
|
|
336
|
+
var _p4_non_chargable = this.p4_non_chargable ? ", p4_non_chargable_routes => [".concat(this.p4_non_chargable_routes.map(function () {
|
|
337
|
+
return "#{ <<\"template\">> => <<\"/*~node-process@1.0/*\">> }";
|
|
338
|
+
}).join(", "), "]") : this.p4_lua ? ", p4_non_chargable_routes => [#{ <<\"template\">> => <<\"/*~node-process@1.0/*\">> }, #{ <<\"template\">> => <<\"/~wao@1.0/*\">> }, #{ <<\"template\">> => <<\"/~p4@1.0/balance\">> }, #{ <<\"template\">> => <<\"/~meta@1.0/*\">> }]" : !this.simple_pay ? "" : ", p4_non_chargable_routes => [#{ <<\"template\">> => <<\"/~simple-pay@1.0/topup\">> }, #{ <<\"template\">> => <<\"/~meta@1.0/*\">> }, #{ <<\"template\">> => <<\"/~simple-pay@1.0/balance\">> }]";
|
|
333
339
|
var _operator = this.operator ? ", operator => <<\"".concat(this.operator, "\">>") : "";
|
|
334
340
|
var _spp = this.spp ? ", simple_pay_price => ".concat(this.spp) : "";
|
|
335
341
|
var _node_processes = this.p4_lua ? ", node_processes => #{ <<\"ledger\">> => #{ <<\"device\">> => <<\"process@1.0\">>, <<\"execution-device\">> => <<\"lua@5.3a\">>, <<\"scheduler-device\">> => <<\"scheduler@1.0\">>, <<\"module\">> => <<\"".concat(this.p4_lua.processor, "\">>, <<\"operator\">> => <<\"").concat(this.operator, "\">> } }") : "";
|
|
@@ -338,7 +344,7 @@ var HyperBEAM = exports["default"] = /*#__PURE__*/function () {
|
|
|
338
344
|
var _faff = (0, _ramda.isNil)(this.faff) ? "" : ", faff_allow_list => [ ".concat((0, _ramda.map)(function (addr) {
|
|
339
345
|
return "<<\"".concat(addr, "\">>");
|
|
340
346
|
})(this.faff).join(", "), " ]");
|
|
341
|
-
var _on = this.p4_lua ? ", on => #{ <<\"request\">> => ".concat(processor, ", <<\"response\">> => ").concat(processor, " }") : this.
|
|
347
|
+
var _on = this.p4_lua ? ", on => #{ <<\"request\">> => ".concat(processor, ", <<\"response\">> => ").concat(processor, " }") : this.simple_pay ? ", on => #{ <<\"request\">> => #{ <<\"device\">> => <<\"p4@1.0\">>, <<\"pricing-device\">> => <<\"simple-pay@1.0\">>, <<\"ledger-device\">> => <<\"simple-pay@1.0\">> }, <<\"response\">> => #{ <<\"device\">> => <<\"p4@1.0\">>, <<\"pricing-device\">> => <<\"simple-pay@1.0\">>, <<\"ledger-device\">> => <<\"simple-pay@1.0\">> } }" : !(0, _ramda.isNil)(this.faff) ? ", on => #{ <<\"request\">> => #{ <<\"device\">> => <<\"p4@1.0\">>, <<\"pricing-device\">> => <<\"faff@1.0\">>, <<\"ledger-device\">> => <<\"faff@1.0\">> }, <<\"response\">> => #{ <<\"device\">> => <<\"p4@1.0\">>, <<\"pricing-device\">> => <<\"faff@1.0\">>, <<\"ledger-device\">> => <<\"faff@1.0\">> } }" : "";
|
|
342
348
|
var start = "hb:start_mainnet(#{ ".concat(_port).concat(_gateway).concat(_wallet).concat(_faff).concat(_bundler).concat(_on).concat(_p4_non_chargable).concat(_operator).concat(_spp).concat(_devices).concat(_node_processes, "}).");
|
|
343
349
|
console.log(start);
|
|
344
350
|
return start;
|
package/cjs/id.js
CHANGED
|
@@ -3,13 +3,17 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
+
exports.base = base;
|
|
6
7
|
exports.extractCommitmentIds = extractCommitmentIds;
|
|
7
8
|
exports.generateCommitmentId = generateCommitmentId;
|
|
8
|
-
exports.
|
|
9
|
-
exports.
|
|
9
|
+
exports.hashpath = hashpath;
|
|
10
|
+
exports.hmacid = hmacid;
|
|
11
|
+
exports.id = id;
|
|
10
12
|
exports.parseStructuredFieldDictionary = parseStructuredFieldDictionary;
|
|
13
|
+
exports.rsaid = rsaid;
|
|
11
14
|
exports.verifyCommitmentId = verifyCommitmentId;
|
|
12
15
|
var _fastSha = require("fast-sha256");
|
|
16
|
+
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
|
|
13
17
|
function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); }
|
|
14
18
|
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
15
19
|
function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); }
|
|
@@ -69,21 +73,6 @@ function base64urlToBase64(str) {
|
|
|
69
73
|
return str.replace(/-/g, "+").replace(/_/g, "/");
|
|
70
74
|
}
|
|
71
75
|
|
|
72
|
-
/**
|
|
73
|
-
* Convert Uint8Array to base64url string
|
|
74
|
-
*/
|
|
75
|
-
function uint8ArrayToBase64url(bytes) {
|
|
76
|
-
// Convert to base64
|
|
77
|
-
var binary = "";
|
|
78
|
-
for (var i = 0; i < bytes.length; i++) {
|
|
79
|
-
binary += String.fromCharCode(bytes[i]);
|
|
80
|
-
}
|
|
81
|
-
var base64 = btoa(binary);
|
|
82
|
-
|
|
83
|
-
// Convert to base64url
|
|
84
|
-
return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
|
|
85
|
-
}
|
|
86
|
-
|
|
87
76
|
/**
|
|
88
77
|
* Generate commitment ID for RSA-PSS and ECDSA signatures
|
|
89
78
|
* The ID is the SHA256 hash of the raw signature bytes
|
|
@@ -91,7 +80,7 @@ function uint8ArrayToBase64url(bytes) {
|
|
|
91
80
|
* @param {Object} commitment - The commitment object containing signature
|
|
92
81
|
* @returns {string} The commitment ID in base64url format
|
|
93
82
|
*/
|
|
94
|
-
function
|
|
83
|
+
function rsaid(commitment) {
|
|
95
84
|
// Extract the base64 signature from structured field format
|
|
96
85
|
// Format: "signature-name=:BASE64_SIGNATURE:"
|
|
97
86
|
var match = commitment.signature.match(/^[^=]+=:([^:]+):/);
|
|
@@ -120,7 +109,7 @@ function generateRsaCommitmentId(commitment) {
|
|
|
120
109
|
* @param {Object} message - The message with signature and signature-input
|
|
121
110
|
* @returns {string} The commitment ID in base64url format
|
|
122
111
|
*/
|
|
123
|
-
function
|
|
112
|
+
function hmacid(message) {
|
|
124
113
|
// Parse signature-input to get components
|
|
125
114
|
var parsed = parseStructuredFieldDictionary(message["signature-input"]);
|
|
126
115
|
if (!parsed || !parsed.components) {
|
|
@@ -177,12 +166,12 @@ function generateCommitmentId(commitment) {
|
|
|
177
166
|
switch (commitment.alg) {
|
|
178
167
|
case "rsa-pss-sha512":
|
|
179
168
|
case "ecdsa-p256-sha256":
|
|
180
|
-
return
|
|
169
|
+
return rsaid(commitment);
|
|
181
170
|
case "hmac-sha256":
|
|
182
171
|
if (!fullMessage) {
|
|
183
172
|
throw new Error("HMAC commitment IDs require full message context");
|
|
184
173
|
}
|
|
185
|
-
return
|
|
174
|
+
return hmacid(fullMessage);
|
|
186
175
|
default:
|
|
187
176
|
throw new Error("Unsupported algorithm: ".concat(commitment.alg));
|
|
188
177
|
}
|
|
@@ -201,9 +190,9 @@ function extractCommitmentIds(message) {
|
|
|
201
190
|
}
|
|
202
191
|
for (var _i = 0, _Object$entries = Object.entries(message.commitments); _i < _Object$entries.length; _i++) {
|
|
203
192
|
var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),
|
|
204
|
-
|
|
193
|
+
_id = _Object$entries$_i[0],
|
|
205
194
|
commitment = _Object$entries$_i[1];
|
|
206
|
-
ids[
|
|
195
|
+
ids[_id] = {
|
|
207
196
|
alg: commitment.alg,
|
|
208
197
|
committer: commitment.committer,
|
|
209
198
|
device: commitment["commitment-device"]
|
|
@@ -231,4 +220,251 @@ function verifyCommitmentId(commitment, expectedId) {
|
|
|
231
220
|
}
|
|
232
221
|
}
|
|
233
222
|
|
|
234
|
-
|
|
223
|
+
/**
|
|
224
|
+
* Convert Uint8Array to base64url string
|
|
225
|
+
*/
|
|
226
|
+
function uint8ArrayToBase64url(bytes) {
|
|
227
|
+
var binary = "";
|
|
228
|
+
for (var i = 0; i < bytes.length; i++) {
|
|
229
|
+
binary += String.fromCharCode(bytes[i]);
|
|
230
|
+
}
|
|
231
|
+
var base64 = btoa(binary);
|
|
232
|
+
return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Parse structured field dictionary to extract components
|
|
237
|
+
* Handles format: name=(components);params
|
|
238
|
+
*/
|
|
239
|
+
function parseSignatureInput(sigInput) {
|
|
240
|
+
// Extract components from format: name=(components);params
|
|
241
|
+
var match = sigInput.match(/[^=]+=\(([^)]+)\)/);
|
|
242
|
+
if (!match) return [];
|
|
243
|
+
|
|
244
|
+
// Split components and clean quotes
|
|
245
|
+
return match[1].split(" ").map(function (c) {
|
|
246
|
+
return c.replace(/"/g, "");
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Calculate HMAC commitment ID for HyperBEAM messages
|
|
252
|
+
*/
|
|
253
|
+
function calculateHmacId(message) {
|
|
254
|
+
if (!message["signature-input"]) {
|
|
255
|
+
throw new Error("HMAC calculation requires signature-input");
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// Parse components from signature-input
|
|
259
|
+
var components = parseSignatureInput(message["signature-input"]);
|
|
260
|
+
|
|
261
|
+
// Sort components AS-IS (with @ prefix)
|
|
262
|
+
var sortedComponents = _toConsumableArray(components).sort();
|
|
263
|
+
|
|
264
|
+
// Build signature base in sorted order
|
|
265
|
+
var lines = [];
|
|
266
|
+
var _iterator = _createForOfIteratorHelper(sortedComponents),
|
|
267
|
+
_step;
|
|
268
|
+
try {
|
|
269
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
270
|
+
var component = _step.value;
|
|
271
|
+
var fieldName = component;
|
|
272
|
+
var value = void 0;
|
|
273
|
+
|
|
274
|
+
// For derived components (starting with @), remove @ in the signature base
|
|
275
|
+
if (component.startsWith("@")) {
|
|
276
|
+
fieldName = component.substring(1);
|
|
277
|
+
value = message[fieldName];
|
|
278
|
+
} else {
|
|
279
|
+
value = message[component];
|
|
280
|
+
}
|
|
281
|
+
if (value === undefined || value === null) {
|
|
282
|
+
value = "";
|
|
283
|
+
} else if (typeof value === "number") {
|
|
284
|
+
value = value.toString();
|
|
285
|
+
}
|
|
286
|
+
lines.push("\"".concat(fieldName, "\": ").concat(value));
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// Add signature-params line with sorted components (keeping @ prefix)
|
|
290
|
+
} catch (err) {
|
|
291
|
+
_iterator.e(err);
|
|
292
|
+
} finally {
|
|
293
|
+
_iterator.f();
|
|
294
|
+
}
|
|
295
|
+
var paramsComponents = sortedComponents.join(" ");
|
|
296
|
+
lines.push("\"@signature-params\": (".concat(paramsComponents, ");alg=\"hmac-sha256\";keyid=\"ao\""));
|
|
297
|
+
var signatureBase = lines.join("\n");
|
|
298
|
+
|
|
299
|
+
// Generate HMAC with key "ao"
|
|
300
|
+
var messageBytes = new TextEncoder().encode(signatureBase);
|
|
301
|
+
var keyBytes = new TextEncoder().encode("ao");
|
|
302
|
+
var hmacResult = (0, _fastSha.hmac)(keyBytes, messageBytes);
|
|
303
|
+
return uint8ArrayToBase64url(hmacResult);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Calculate unsigned message ID following the exact Erlang flow
|
|
308
|
+
*/
|
|
309
|
+
function calculateUnsignedId(message) {
|
|
310
|
+
// Derived components from Erlang ?DERIVED_COMPONENTS
|
|
311
|
+
var DERIVED_COMPONENTS = ["method", "target-uri", "authority", "scheme", "request-target", "path", "query", "query-param", "status"];
|
|
312
|
+
|
|
313
|
+
// Convert message for httpsig format
|
|
314
|
+
var httpsigMsg = {};
|
|
315
|
+
for (var _i2 = 0, _Object$entries2 = Object.entries(message); _i2 < _Object$entries2.length; _i2++) {
|
|
316
|
+
var _Object$entries2$_i = _slicedToArray(_Object$entries2[_i2], 2),
|
|
317
|
+
key = _Object$entries2$_i[0],
|
|
318
|
+
value = _Object$entries2$_i[1];
|
|
319
|
+
httpsigMsg[key.toLowerCase()] = value;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// Get keys and add @ to derived components
|
|
323
|
+
var keys = Object.keys(httpsigMsg);
|
|
324
|
+
var componentsWithPrefix = keys.map(function (key) {
|
|
325
|
+
// Check if this is a derived component
|
|
326
|
+
if (DERIVED_COMPONENTS.includes(key.replace(/_/g, "-"))) {
|
|
327
|
+
return "@" + key;
|
|
328
|
+
}
|
|
329
|
+
return key;
|
|
330
|
+
}).sort(); // Sort AFTER adding @ prefix
|
|
331
|
+
|
|
332
|
+
// Build signature base - use the components in order
|
|
333
|
+
var lines = [];
|
|
334
|
+
var _iterator2 = _createForOfIteratorHelper(componentsWithPrefix),
|
|
335
|
+
_step2;
|
|
336
|
+
try {
|
|
337
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
338
|
+
var component = _step2.value;
|
|
339
|
+
var _key = component.replace("@", "");
|
|
340
|
+
var _value = httpsigMsg[_key];
|
|
341
|
+
var valueStr = typeof _value === "string" ? _value : String(_value);
|
|
342
|
+
lines.push("\"".concat(_key, "\": ").concat(valueStr));
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// Add signature-params line with the @ prefixes
|
|
346
|
+
} catch (err) {
|
|
347
|
+
_iterator2.e(err);
|
|
348
|
+
} finally {
|
|
349
|
+
_iterator2.f();
|
|
350
|
+
}
|
|
351
|
+
var componentsList = componentsWithPrefix.map(function (k) {
|
|
352
|
+
return "\"".concat(k, "\"");
|
|
353
|
+
}).join(" ");
|
|
354
|
+
lines.push("\"@signature-params\": (".concat(componentsList, ");alg=\"hmac-sha256\";keyid=\"ao\""));
|
|
355
|
+
var signatureBase = lines.join("\n");
|
|
356
|
+
|
|
357
|
+
// HMAC with key "ao"
|
|
358
|
+
var messageBytes = new TextEncoder().encode(signatureBase);
|
|
359
|
+
var keyBytes = new TextEncoder().encode("ao");
|
|
360
|
+
var hmacResult = (0, _fastSha.hmac)(keyBytes, messageBytes);
|
|
361
|
+
return uint8ArrayToBase64url(hmacResult);
|
|
362
|
+
}
|
|
363
|
+
function id(message) {
|
|
364
|
+
// Get commitment IDs
|
|
365
|
+
var commitmentIds = Object.keys(message.commitments || {});
|
|
366
|
+
if (commitmentIds.length === 0) {
|
|
367
|
+
// No commitments - calculate unsigned ID using HMAC
|
|
368
|
+
return calculateUnsignedId(message);
|
|
369
|
+
} else if (commitmentIds.length === 1) {
|
|
370
|
+
// Single commitment - the ID is just the commitment ID
|
|
371
|
+
return commitmentIds[0];
|
|
372
|
+
} else {
|
|
373
|
+
// Multiple commitments - sort, join with ", ", and hash
|
|
374
|
+
var sortedIds = commitmentIds.sort();
|
|
375
|
+
var idsLine = sortedIds.join(", ");
|
|
376
|
+
|
|
377
|
+
// Calculate SHA-256 hash using fast-sha256
|
|
378
|
+
var encoder = new TextEncoder();
|
|
379
|
+
var data = encoder.encode(idsLine);
|
|
380
|
+
var hashArray = (0, _fastSha.hash)(data);
|
|
381
|
+
|
|
382
|
+
// Convert to base64url
|
|
383
|
+
return uint8ArrayToBase64url(hashArray);
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
// Export all functions
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* Calculate the next base from a hashpath
|
|
390
|
+
* A hashpath has the format: base/request
|
|
391
|
+
* The next base is calculated as: sha256(base + request)
|
|
392
|
+
*
|
|
393
|
+
* @param {string} hashpath - The current hashpath in format "base/request"
|
|
394
|
+
* @returns {string} The next base in base64url format
|
|
395
|
+
*/
|
|
396
|
+
function base(hashpath) {
|
|
397
|
+
// Split the hashpath into base and request
|
|
398
|
+
var parts = hashpath.split("/");
|
|
399
|
+
if (parts.length !== 2) {
|
|
400
|
+
throw new Error("Invalid hashpath format. Expected 'base/request'");
|
|
401
|
+
}
|
|
402
|
+
var _parts = _slicedToArray(parts, 2),
|
|
403
|
+
base = _parts[0],
|
|
404
|
+
request = _parts[1];
|
|
405
|
+
|
|
406
|
+
// Convert base64url to native binary (Uint8Array)
|
|
407
|
+
var baseBinary = base64urlToUint8Array(base);
|
|
408
|
+
var requestBinary = base64urlToUint8Array(request);
|
|
409
|
+
|
|
410
|
+
// Concatenate base and request
|
|
411
|
+
var combined = new Uint8Array(baseBinary.length + requestBinary.length);
|
|
412
|
+
combined.set(baseBinary, 0);
|
|
413
|
+
combined.set(requestBinary, baseBinary.length);
|
|
414
|
+
|
|
415
|
+
// Calculate SHA256 of the combined data
|
|
416
|
+
var nextBaseHash = (0, _fastSha.hash)(combined);
|
|
417
|
+
|
|
418
|
+
// Convert to base64url
|
|
419
|
+
return uint8ArrayToBase64url(nextBaseHash);
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
/**
|
|
423
|
+
* Calculate the next hashpath given the current hashpath and a new message
|
|
424
|
+
*
|
|
425
|
+
* @param {string} currentHashpath - The current hashpath (or null for first operation)
|
|
426
|
+
* @param {Object} newMessage - The new message/request
|
|
427
|
+
* @returns {string} The next hashpath in format "nextBase/newMessageId"
|
|
428
|
+
*/
|
|
429
|
+
function hashpath(currentHashpath, newMessage) {
|
|
430
|
+
// Calculate the ID of the new message
|
|
431
|
+
var newMessageId = id(newMessage);
|
|
432
|
+
if (!currentHashpath) {
|
|
433
|
+
// First operation: the hashpath is just the message ID
|
|
434
|
+
// In the Erlang code, the first hashpath is "baseId/requestId"
|
|
435
|
+
// where baseId is the ID of the initial message
|
|
436
|
+
throw new Error("For first operation, provide the base message ID as currentHashpath");
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
// Check if this is the first operation (currentHashpath is just an ID, not a path)
|
|
440
|
+
if (!currentHashpath.includes("/")) {
|
|
441
|
+
// First operation: currentHashpath is the base message ID
|
|
442
|
+
return "".concat(currentHashpath, "/").concat(newMessageId);
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
// Subsequent operations: calculate the next base from current hashpath
|
|
446
|
+
var nextBase = base(currentHashpath);
|
|
447
|
+
|
|
448
|
+
// Return the new hashpath
|
|
449
|
+
return "".concat(nextBase, "/").concat(newMessageId);
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
/**
|
|
453
|
+
* Helper function to convert base64url string to Uint8Array
|
|
454
|
+
*/
|
|
455
|
+
function base64urlToUint8Array(base64url) {
|
|
456
|
+
// Convert base64url to base64
|
|
457
|
+
var base64 = base64urlToBase64(base64url);
|
|
458
|
+
|
|
459
|
+
// Decode base64 to binary string
|
|
460
|
+
var binaryString = atob(base64);
|
|
461
|
+
|
|
462
|
+
// Convert binary string to Uint8Array
|
|
463
|
+
var bytes = new Uint8Array(binaryString.length);
|
|
464
|
+
for (var i = 0; i < binaryString.length; i++) {
|
|
465
|
+
bytes[i] = binaryString.charCodeAt(i);
|
|
466
|
+
}
|
|
467
|
+
return bytes;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
// Export the new functions
|
package/cjs/signer.js
CHANGED
|
@@ -6,9 +6,16 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
});
|
|
7
7
|
exports.sign = sign;
|
|
8
8
|
exports.signer = signer;
|
|
9
|
+
Object.defineProperty(exports, "verify", {
|
|
10
|
+
enumerable: true,
|
|
11
|
+
get: function get() {
|
|
12
|
+
return _signerUtils.verify;
|
|
13
|
+
}
|
|
14
|
+
});
|
|
9
15
|
var _send = require("./send.js");
|
|
10
16
|
var _encode = require("./encode.js");
|
|
11
17
|
var _aoconnect = require("@permaweb/aoconnect");
|
|
18
|
+
var _signerUtils = require("./signer-utils.js");
|
|
12
19
|
var _excluded = ["path", "method"],
|
|
13
20
|
_excluded2 = ["body"];
|
|
14
21
|
function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
|
|
@@ -96,11 +103,13 @@ function _sign3() {
|
|
|
96
103
|
return key !== "body-keys" && key !== "path" && !bodyKeys.includes(key);
|
|
97
104
|
});
|
|
98
105
|
if (_path) signingFields.push("path");
|
|
106
|
+
/*
|
|
99
107
|
if (signingFields.length === 0 && !body) {
|
|
100
|
-
lowercaseHeaders["content-length"] = "0"
|
|
101
|
-
signingFields.push("content-length")
|
|
108
|
+
//lowercaseHeaders["content-length"] = "0"
|
|
109
|
+
//signingFields.push("content-length")
|
|
102
110
|
}
|
|
103
|
-
|
|
111
|
+
*/
|
|
112
|
+
_context3.next = 13;
|
|
104
113
|
return (0, _send.toHttpSigner)(signer)({
|
|
105
114
|
request: {
|
|
106
115
|
url: _url,
|
|
@@ -109,7 +118,7 @@ function _sign3() {
|
|
|
109
118
|
},
|
|
110
119
|
fields: signingFields
|
|
111
120
|
});
|
|
112
|
-
case
|
|
121
|
+
case 13:
|
|
113
122
|
signedRequest = _context3.sent;
|
|
114
123
|
finalHeaders = {};
|
|
115
124
|
for (_i2 = 0, _Object$entries2 = Object.entries(headersObj); _i2 < _Object$entries2.length; _i2++) {
|
|
@@ -128,7 +137,7 @@ function _sign3() {
|
|
|
128
137
|
};
|
|
129
138
|
if (body) result.body = body;
|
|
130
139
|
return _context3.abrupt("return", result);
|
|
131
|
-
case
|
|
140
|
+
case 22:
|
|
132
141
|
case "end":
|
|
133
142
|
return _context3.stop();
|
|
134
143
|
}
|
package/cjs/utils.js
CHANGED
|
@@ -3,11 +3,30 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.
|
|
6
|
+
exports.allChecked = exports.action = void 0;
|
|
7
|
+
Object.defineProperty(exports, "base", {
|
|
8
|
+
enumerable: true,
|
|
9
|
+
get: function get() {
|
|
10
|
+
return _id.base;
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
exports.getTagVal = exports.getTag = exports.dirname = exports.checkTag = exports.buildTags = void 0;
|
|
14
|
+
Object.defineProperty(exports, "hashpath", {
|
|
15
|
+
enumerable: true,
|
|
16
|
+
get: function get() {
|
|
17
|
+
return _id.hashpath;
|
|
18
|
+
}
|
|
19
|
+
});
|
|
7
20
|
Object.defineProperty(exports, "hmacid", {
|
|
8
21
|
enumerable: true,
|
|
9
22
|
get: function get() {
|
|
10
|
-
return _id.
|
|
23
|
+
return _id.hmacid;
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
Object.defineProperty(exports, "id", {
|
|
27
|
+
enumerable: true,
|
|
28
|
+
get: function get() {
|
|
29
|
+
return _id.id;
|
|
11
30
|
}
|
|
12
31
|
});
|
|
13
32
|
exports.isData = exports.isCheckComplete = void 0;
|
|
@@ -17,7 +36,7 @@ exports.parseSignatureInput = parseSignatureInput;
|
|
|
17
36
|
Object.defineProperty(exports, "rsaid", {
|
|
18
37
|
enumerable: true,
|
|
19
38
|
get: function get() {
|
|
20
|
-
return _id.
|
|
39
|
+
return _id.rsaid;
|
|
21
40
|
}
|
|
22
41
|
});
|
|
23
42
|
exports.tags = exports.tagEq = exports.tag = exports.srcs = exports.searchTag = void 0;
|
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
import assert from "assert"
|
|
2
2
|
import { describe, it, before, after, beforeEach } from "node:test"
|
|
3
|
-
import { HyperBEAM,
|
|
3
|
+
import { HyperBEAM, toAddr } from "wao/test"
|
|
4
4
|
import { HB } from "wao"
|
|
5
5
|
import { resolve } from "path"
|
|
6
6
|
import { readFileSync } from "fs"
|
|
7
7
|
|
|
8
8
|
const cwd = "../../HyperBEAM"
|
|
9
|
-
const wallet = ".wallet.json"
|
|
9
|
+
const wallet = resolve(process.cwd(), cwd, ".wallet.json")
|
|
10
|
+
|
|
11
|
+
const jwk = JSON.parse(readFileSync(wallet, "utf8"))
|
|
12
|
+
const addr = toAddr(jwk.n)
|
|
10
13
|
|
|
11
14
|
describe("HyperBEAM", function () {
|
|
12
15
|
let hbeam, hb, jwk
|
|
13
16
|
|
|
14
17
|
before(async () => {
|
|
15
|
-
hbeam = await new HyperBEAM({
|
|
18
|
+
hbeam = await new HyperBEAM({ cwd }).ready()
|
|
16
19
|
jwk = JSON.parse(readFileSync(resolve(process.cwd(), cwd, wallet), "utf8"))
|
|
17
20
|
})
|
|
18
21
|
|
|
@@ -21,7 +24,7 @@ describe("HyperBEAM", function () {
|
|
|
21
24
|
after(async () => hbeam.kill())
|
|
22
25
|
|
|
23
26
|
it("should run a HyperBEAM node", async () => {
|
|
24
|
-
const
|
|
25
|
-
assert.equal(
|
|
27
|
+
const { out } = await hb.getJSON({ path: "/~meta@1.0/build" })
|
|
28
|
+
assert.equal(out.node, "HyperBEAM")
|
|
26
29
|
})
|
|
27
30
|
})
|
package/esm/ao.js
CHANGED
package/esm/hb.js
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { connect, createSigner } from "@permaweb/aoconnect"
|
|
2
2
|
import { isEmpty, last, isNotNil, mergeLeft } from "ramda"
|
|
3
|
-
import { toAddr, buildTags } from "./utils.js"
|
|
4
|
-
import { signer } from "./signer.js"
|
|
3
|
+
import { rsaid, hmacid, toAddr, buildTags } from "./utils.js"
|
|
4
|
+
import { sign, signer } from "./signer.js"
|
|
5
5
|
import { send as _send } from "./send.js"
|
|
6
6
|
import hyper_aos from "./lua/hyper-aos.js"
|
|
7
7
|
import aos_wamr from "./lua/aos_wamr.js"
|
|
8
8
|
import { from } from "./httpsig.js"
|
|
9
9
|
|
|
10
10
|
const seed = num => {
|
|
11
|
-
const array = new
|
|
12
|
-
|
|
11
|
+
const array = new Array(num)
|
|
12
|
+
for (let i = 0; i < num; i++) array[i] = Math.floor(Math.random() * 256)
|
|
13
|
+
return Buffer.from(array).toString("base64")
|
|
13
14
|
}
|
|
14
15
|
|
|
15
16
|
class HB {
|
|
@@ -71,8 +72,17 @@ class HB {
|
|
|
71
72
|
}
|
|
72
73
|
if (jwk) this._init(jwk)
|
|
73
74
|
}
|
|
74
|
-
|
|
75
|
+
async signEncoded(encoded) {
|
|
76
|
+
const { path, ...msg } = encoded
|
|
77
|
+
return await sign({
|
|
78
|
+
jwk: this.jwk,
|
|
79
|
+
msg,
|
|
80
|
+
path,
|
|
81
|
+
url: this.url,
|
|
82
|
+
})
|
|
83
|
+
}
|
|
75
84
|
_init(jwk) {
|
|
85
|
+
this.jwk = jwk
|
|
76
86
|
this.signer = createSigner(jwk, this.url)
|
|
77
87
|
this.addr = toAddr(jwk.n)
|
|
78
88
|
this.sign = signer({ signer: this.signer, url: this.url })
|
|
@@ -108,7 +118,7 @@ class HB {
|
|
|
108
118
|
|
|
109
119
|
async getLua() {
|
|
110
120
|
const lua = Buffer.from(hyper_aos, "base64")
|
|
111
|
-
const id = await this.
|
|
121
|
+
const id = await this.cacheScript(lua, "application/lua")
|
|
112
122
|
this.lua ??= id
|
|
113
123
|
return id
|
|
114
124
|
}
|
|
@@ -132,7 +142,11 @@ class HB {
|
|
|
132
142
|
const { slot, pid } = await this.scheduleAOS(args)
|
|
133
143
|
return { slot, outbox: await this.computeAOS({ pid, slot }) }
|
|
134
144
|
}
|
|
135
|
-
|
|
145
|
+
async messageLegacy(args) {
|
|
146
|
+
const { slot, pid } = await this.scheduleLegacy(args)
|
|
147
|
+
console.log(slot, pid, args)
|
|
148
|
+
return { slot, res: await this.computeLegacy({ pid, slot }) }
|
|
149
|
+
}
|
|
136
150
|
path({
|
|
137
151
|
dev = "message",
|
|
138
152
|
path,
|
|
@@ -214,7 +228,7 @@ class HB {
|
|
|
214
228
|
return { res, pid: res.headers.process }
|
|
215
229
|
}
|
|
216
230
|
|
|
217
|
-
async
|
|
231
|
+
async cacheScript(data, type = "application/lua") {
|
|
218
232
|
if (!this.cache) {
|
|
219
233
|
const { pid } = await this.spawn({})
|
|
220
234
|
this.cache = pid
|
|
@@ -261,7 +275,7 @@ class HB {
|
|
|
261
275
|
})
|
|
262
276
|
if (data) _tags.data = data
|
|
263
277
|
let res = await this.post(_tags)
|
|
264
|
-
return { slot: res.headers.slot, res }
|
|
278
|
+
return { slot: res.headers.slot, res, pid }
|
|
265
279
|
}
|
|
266
280
|
|
|
267
281
|
async spawnAOS(image) {
|
|
@@ -368,13 +382,21 @@ class HB {
|
|
|
368
382
|
if (isNotNil(from)) params += `&from=${from}`
|
|
369
383
|
if (isNotNil(to)) params += `&to=${to}`
|
|
370
384
|
params += `&accept=application/aos-2`
|
|
385
|
+
const {
|
|
386
|
+
out: { body },
|
|
387
|
+
} = await this.get({
|
|
388
|
+
path: "/~scheduler@1.0/schedule",
|
|
389
|
+
target: pid,
|
|
390
|
+
from,
|
|
391
|
+
accept: "application/aos-2",
|
|
392
|
+
})
|
|
371
393
|
let res = await fetch(`${this.url}/~scheduler@1.0/schedule?${params}`).then(
|
|
372
394
|
r => r.json()
|
|
373
395
|
)
|
|
374
396
|
if (res.page_info.has_next_page) {
|
|
375
397
|
res.next = async () => {
|
|
376
398
|
const from2 = last(res.edges).cursor + 1
|
|
377
|
-
return await this.
|
|
399
|
+
return await this.messages({ pid, from: from2, to, limit })
|
|
378
400
|
}
|
|
379
401
|
}
|
|
380
402
|
return res
|
|
@@ -433,7 +455,26 @@ class HB {
|
|
|
433
455
|
})
|
|
434
456
|
return JSON.parse(res.body)
|
|
435
457
|
}
|
|
458
|
+
async commit(obj, opts) {
|
|
459
|
+
const msg = await this.sign(obj, opts)
|
|
460
|
+
const hmacId = hmacid(msg.headers)
|
|
461
|
+
const rsaId = rsaid(msg.headers)
|
|
462
|
+
const committer = this.addr
|
|
463
|
+
const meta = { alg: "rsa-pss-sha512", "commitment-device": "httpsig@1.0" }
|
|
464
|
+
const meta2 = { alg: "hmac-sha256", "commitment-device": "httpsig@1.0" }
|
|
436
465
|
|
|
466
|
+
const sigs = {
|
|
467
|
+
signature: msg.headers.signature,
|
|
468
|
+
"signature-input": msg.headers["signature-input"],
|
|
469
|
+
}
|
|
470
|
+
return {
|
|
471
|
+
commitments: {
|
|
472
|
+
[rsaId]: { ...meta, committer, ...sigs },
|
|
473
|
+
[hmacId]: { ...meta2, ...sigs },
|
|
474
|
+
},
|
|
475
|
+
...obj,
|
|
476
|
+
}
|
|
477
|
+
}
|
|
437
478
|
async post(obj, json) {
|
|
438
479
|
const _json = json ? "/~json@1.0/serialize" : ""
|
|
439
480
|
obj.path += _json
|