*Update builds

This commit is contained in:
Derrick Hammer 2022-07-20 13:51:16 -04:00
parent 6d15e76560
commit baf1fa7695
6 changed files with 238 additions and 16450 deletions

2
bin/sandbox.d.ts vendored Normal file
View File

@ -0,0 +1,2 @@
#!/usr/bin/env node
export {};

16
bin/sandbox.js Normal file
View File

@ -0,0 +1,16 @@
#!/usr/bin/env node
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
// @ts-ignore
const index_js_1 = require("../dist/index.js");
const puppeteer_1 = require("puppeteer");
let browser;
(async () => {
browser = await puppeteer_1.default.launch({ headless: false, devtools: true });
const page = (await browser.pages()).pop();
await (0, index_js_1.login)(page);
await (0, index_js_1.loadTester)(page);
})();
process.on("SIGTERM", async () => {
await browser.close();
});

2
dist/index.d.ts vendored
View File

@ -2,7 +2,7 @@ import { Page } from "puppeteer";
import { errTuple } from "libskynet/dist"; import { errTuple } from "libskynet/dist";
export declare const KERNEL_TEST_SUITE = "AQCPJ9WRzMpKQHIsPo8no3XJpUydcDCjw7VJy8lG1MCZ3g"; export declare const KERNEL_TEST_SUITE = "AQCPJ9WRzMpKQHIsPo8no3XJpUydcDCjw7VJy8lG1MCZ3g";
export declare const KERNEL_HELPER_MODULE = "AQCoaLP6JexdZshDDZRQaIwN3B7DqFjlY7byMikR7u1IEA"; export declare const KERNEL_HELPER_MODULE = "AQCoaLP6JexdZshDDZRQaIwN3B7DqFjlY7byMikR7u1IEA";
export declare const TEST_KERNEL_SKLINK = "AQCw2_9rg0Fxuy8ky3pvLiDhcJTmAqthy1Buc7Frl2v2fA"; export declare const TEST_KERNEL_SKLINK = "AQDJDoXMJiiEMBxXodQvUV89qtQHsnXWyV1ViQ9M1pMjUg";
export declare function generateSeedPhrase(): string; export declare function generateSeedPhrase(): string;
export declare function login(page: Page, seed?: string): Promise<void>; export declare function login(page: Page, seed?: string): Promise<void>;
export declare function loadTester(page: Page, port?: number): Promise<void>; export declare function loadTester(page: Page, port?: number): Promise<void>;

16353
dist/index.js vendored

File diff suppressed because it is too large Load Diff

1
dist/tester.d.ts vendored
View File

@ -1 +0,0 @@
export {};

View File

@ -37,108 +37,109 @@
console.error("[libkernel]", ...inputs); console.error("[libkernel]", ...inputs);
} }
// tryStringify will try to turn the provided input into a string. If the input // objAsString will try to return the provided object as a string. If the
// object is already a string, the input object will be returned. If the input // object is already a string, it will be returned without modification. If the
// object has a toString method, the toString method will be called. If that // object is an 'Error', the message of the error will be returned. If the object
// fails, we try to call JSON.stringify on the object. And if that fails, we // has a toString method, the toString method will be called and the result
// set the return value to "[stringify failed]". // will be returned. If the object is null or undefined, a special string will
function tryStringify$1(obj) { // be returned indicating that the undefined/null object cannot be converted to
// a string. In all other cases, JSON.stringify is used. If JSON.stringify
// throws an exception, a message "[could not provide object as string]" will
// be returned.
//
// NOTE: objAsString is intended to produce human readable output. It is lossy,
// and it is not intended to be used for serialization.
function objAsString(obj) {
// Check for undefined input. // Check for undefined input.
if (obj === undefined || obj === null) { if (obj === undefined) {
return "[cannot stringify undefined input]"; return "[cannot convert undefined to string]";
}
if (obj === null) {
return "[cannot convert null to string]";
} }
// Parse the error into a string. // Parse the error into a string.
if (typeof obj === "string") { if (typeof obj === "string") {
return obj; return obj;
} }
// Check if the object has a custom toString and use that if so. // Check if the object is an error, and return the message of the error if
let hasToString = typeof obj.toString === "function"; // so.
if (hasToString && obj.toString !== Object.prototype.toString) { if (obj instanceof Error) {
return obj.toString(); return obj.message;
}
// Check if the object has a 'toString' method defined on it. To ensure
// that we don't crash or throw, check that the toString is a function, and
// also that the return value of toString is a string.
if (Object.prototype.hasOwnProperty.call(obj, "toString")) {
if (typeof obj.toString === "function") {
const str = obj.toString();
if (typeof str === "string") {
return str;
}
}
} }
// If the object does not have a custom toString, attempt to perform a // If the object does not have a custom toString, attempt to perform a
// JSON.stringify. // JSON.stringify. We use a lot of bigints in libskynet, and calling
// JSON.stringify on an object with a bigint will cause a throw, so we add
// some custom handling to allow bigint objects to still be encoded.
try { try {
return JSON.stringify(obj); return JSON.stringify(obj, (_, v) => {
if (typeof v === "bigint") {
return v.toString();
}
return v;
});
}
catch (err) {
if (err !== undefined && typeof err.message === "string") {
return `[stringify failed]: ${err.message}`;
} }
catch {
return "[stringify failed]"; return "[stringify failed]";
} }
} }
// addContextToErr is a helper function that standardizes the formatting of // addContextToErr is a helper function that standardizes the formatting of
// adding context to an error. Within the world of go we discovered that being // adding context to an error.
// persistent about layering context onto errors is helpful when debugging,
// even though it often creates rather verbose error messages.
//
// addContextToErr will return null if the input err is null.
// //
// NOTE: To protect against accidental situations where an Error type or some // NOTE: To protect against accidental situations where an Error type or some
// other type is provided instead of a string, we wrap both of the inputs with // other type is provided instead of a string, we wrap both of the inputs with
// tryStringify before returning them. This prevents runtime failures. // objAsString before returning them. This prevents runtime failures.
function addContextToErr$1(err, context) { function addContextToErr$1(err, context) {
if (err === null) { if (err === null || err === undefined) {
err = "[no error provided]"; err = "[no error provided]";
} }
return tryStringify$1(context) + ": " + tryStringify$1(err); return objAsString(context) + ": " + objAsString(err);
}
// composeErr takes a series of inputs and composes them into a single string.
// Each element will be separated by a newline. If the input is not a string,
// it will be transformed into a string with JSON.stringify.
//
// Any object that cannot be stringified will be skipped, though an error will
// be logged.
function composeErr$1(...inputs) {
let result = "";
let resultEmpty = true;
for (let i = 0; i < inputs.length; i++) {
if (inputs[i] === null) {
continue;
}
if (resultEmpty) {
resultEmpty = false;
}
else {
result += "\n";
}
result += tryStringify$1(inputs[i]);
}
if (resultEmpty) {
return null;
}
return result;
} }
// Helper consts to make it easy to return empty values alongside errors. const MAX_UINT_64 = 18446744073709551615n;
const nu8$7 = new Uint8Array(0);
// bufToB64 will convert a Uint8Array to a base64 string with URL encoding and // bufToB64 will convert a Uint8Array to a base64 string with URL encoding and
// no padding characters. // no padding characters.
function bufToB64$1(buf) { function bufToB64$1(buf) {
let b64Str = btoa(String.fromCharCode.apply(null, buf)); const b64Str = btoa(String.fromCharCode(...buf));
return b64Str.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, ""); return b64Str.replaceAll("+", "-").replaceAll("/", "_").replaceAll("=", "");
} }
// encodeU64 will encode a bigint in the range of a uint64 to an 8 byte // encodeU64 will encode a bigint in the range of a uint64 to an 8 byte
// Uint8Array. // Uint8Array.
function encodeU64$1(num) { function encodeU64$1(num) {
// Check the bounds on the bigint. // Check the bounds on the bigint.
if (num < 0) { if (num < 0) {
return [nu8$7, "expected a positive integer"]; return [new Uint8Array(0), "expected a positive integer"];
} }
if (num > 18446744073709551615n) { if (num > MAX_UINT_64) {
return [nu8$7, "expected a number no larger than a uint64"]; return [new Uint8Array(0), "expected a number no larger than a uint64"];
} }
// Encode the bigint into a Uint8Array. // Encode the bigint into a Uint8Array.
let encoded = new Uint8Array(8); const encoded = new Uint8Array(8);
for (let i = 0; i < encoded.length; i++) { for (let i = 0; i < encoded.length; i++) {
let byte = Number(num & 0xffn); const byte = Number(num & 0xffn);
encoded[i] = byte; encoded[i] = byte;
num = num >> 8n; num = num >> 8n;
} }
return [encoded, null]; return [encoded, null];
} }
let gfi$1 = function (init) { const gfi$1 = function (init) {
let i, r = new Float64Array(16); let i;
const r = new Float64Array(16);
if (init) if (init)
for (i = 0; i < init.length; i++) for (i = 0; i < init.length; i++)
r[i] = init[i]; r[i] = init[i];
@ -161,6 +162,38 @@
0x2480, 0x2b83, 0x2480, 0x2b83,
]); ]);
// checkObj take an untrusted object and a list of typechecks to perform and
// will check that the object adheres to the typechecks. If a type is missing
// or has the wrong type, an error will be returned. This is intended to be
// used to check untrusted objects after they get decoded from JSON. This is
// particularly useful when receiving objects from untrusted entities over the
// network or over postMessage.
//
// Below is an example object, followed by the call that you would make to
// checkObj to verify the object.
//
// const expectedObj = {
// aNum: 35,
// aStr: "hi",
// aBig: 10n,
// };
//
// const err = checkObj(expectedObj, [
// ["aNum", "number"],
// ["aStr", "string"],
// ["aBig", "bigint"],
// ]);
function checkObj(obj, checks) {
for (let i = 0; i < checks.length; i++) {
const check = checks[i];
const type = typeof obj[check[0]];
if (type !== check[1]) {
return "check failed, expecting " + check[1] + " got " + type;
}
}
return null;
}
// Create the queryMap. // Create the queryMap.
let queries = {}; let queries = {};
// Define the nonce handling. nonceSeed is 16 random bytes that get generated // Define the nonce handling. nonceSeed is 16 random bytes that get generated
@ -236,7 +269,12 @@
// at a minimum is working. // at a minimum is working.
if (initResolved === false) { if (initResolved === false) {
initResolved = true; initResolved = true;
// We can't actually establish that init is complete until the
// kernel source has been set. This happens async and might happen
// after we receive the auth message.
sourcePromise.then(() => {
initResolve(); initResolve();
});
} }
// If the auth status message says that login is complete, it means // If the auth status message says that login is complete, it means
// that the user is logged in. // that the user is logged in.
@ -314,6 +352,7 @@
kernelSource = iframe.contentWindow; kernelSource = iframe.contentWindow;
kernelOrigin = "https://skt.us"; kernelOrigin = "https://skt.us";
kernelAuthLocation = "https://skt.us/auth.html"; kernelAuthLocation = "https://skt.us/auth.html";
sourceResolve();
// Set a timer to fail the login process if the kernel doesn't load in // Set a timer to fail the login process if the kernel doesn't load in
// time. // time.
setTimeout(() => { setTimeout(() => {
@ -355,6 +394,7 @@
kernelOrigin = window.origin; kernelOrigin = window.origin;
kernelAuthLocation = "http://kernel.skynet/auth.html"; kernelAuthLocation = "http://kernel.skynet/auth.html";
console.log("established connection to bridge, using browser extension for kernel"); console.log("established connection to bridge, using browser extension for kernel");
sourceResolve();
}); });
// Add the handler to the queries map. // Add the handler to the queries map.
let nonce = nextNonce(); let nonce = nextNonce();
@ -399,6 +439,8 @@
let kernelLoadedPromise; let kernelLoadedPromise;
let logoutResolve; let logoutResolve;
let logoutPromise; let logoutPromise;
let sourceResolve;
let sourcePromise; // resolves when the source is known and set
function init() { function init() {
// If init has already been called, just return the init promise. // If init has already been called, just return the init promise.
if (initialized === true) { if (initialized === true) {
@ -422,6 +464,9 @@
logoutPromise = new Promise((resolve) => { logoutPromise = new Promise((resolve) => {
logoutResolve = resolve; logoutResolve = resolve;
}); });
sourcePromise = new Promise((resolve) => {
sourceResolve = resolve;
});
// Return the initPromise, which will resolve when bootloader init is // Return the initPromise, which will resolve when bootloader init is
// complete. // complete.
return initPromise; return initPromise;
@ -430,7 +475,7 @@
// module identifier (typically a skylink), the second input is the method // module identifier (typically a skylink), the second input is the method
// being called on the module, and the final input is optional and contains // being called on the module, and the final input is optional and contains
// input data to be passed to the module. The input data will depend on the // input data to be passed to the module. The input data will depend on the
// module and the method that is being called. The return value is an errTuple // module and the method that is being called. The return value is an ErrTuple
// that contains the module's response. The format of the response is an // that contains the module's response. The format of the response is an
// arbitrary object whose fields depend on the module and method being called. // arbitrary object whose fields depend on the module and method being called.
// //
@ -461,7 +506,7 @@
// as the receiveUpdate function, it's an arbitrary object whose fields depend // as the receiveUpdate function, it's an arbitrary object whose fields depend
// on the module and method being queried. // on the module and method being queried.
// //
// The second return value is a promise that returns an errTuple. It will // The second return value is a promise that returns an ErrTuple. It will
// resolve when the module sends a response message, and works the same as the // resolve when the module sends a response message, and works the same as the
// return value of callModule. // return value of callModule.
function connectModule(module, method, data, receiveUpdate) { function connectModule(module, method, data, receiveUpdate) {
@ -540,16 +585,14 @@
// kernel provides a 'response' message. The other is for internal use and // kernel provides a 'response' message. The other is for internal use and
// will resolve once the query has been created. // will resolve once the query has been created.
let p; let p;
let queryCreated; let haveQueryCreated = new Promise((queryCreatedResolve) => {
let haveQueryCreated = new Promise((resolve) => {
queryCreated = resolve;
p = new Promise((resolve) => { p = new Promise((resolve) => {
getNonce.then((nonce) => { getNonce.then((nonce) => {
queries[nonce] = { resolve }; queries[nonce] = { resolve };
if (receiveUpdate !== null && receiveUpdate !== undefined) { if (receiveUpdate !== null && receiveUpdate !== undefined) {
queries[nonce]["receiveUpdate"] = receiveUpdate; queries[nonce]["receiveUpdate"] = receiveUpdate;
} }
queryCreated(nonce); queryCreatedResolve(nonce);
}); });
}); });
}); });
@ -653,6 +696,10 @@
// logoutComplete() will block until auth has reached stage 4. libkernel does // logoutComplete() will block until auth has reached stage 4. libkernel does
// not support resetting the auth stages, once stage 4 has been reached the app // not support resetting the auth stages, once stage 4 has been reached the app
// needs to refresh. // needs to refresh.
// loginComplete will resolve when the user has successfully logged in.
function loginComplete() {
return loginPromise;
}
// kernelLoaded will resolve when the user has successfully loaded the kernel. // kernelLoaded will resolve when the user has successfully loaded the kernel.
// If there was an error in loading the kernel, the error will be returned. // If there was an error in loading the kernel, the error will be returned.
// //
@ -660,10 +707,6 @@
function kernelLoaded() { function kernelLoaded() {
return kernelLoadedPromise; return kernelLoadedPromise;
} }
// loginComplete will resolve when the user has successfully logged in.
function loginComplete() {
return loginPromise;
}
// logoutComplete will resolve when the user has logged out. Note that // logoutComplete will resolve when the user has logged out. Note that
// logoutComplete will only resolve if the user logged in first - if the user // logoutComplete will only resolve if the user logged in first - if the user
// was not logged in to begin with, this promise will not resolve. // was not logged in to begin with, this promise will not resolve.
@ -718,12 +761,27 @@
// because the object is relatively complex and all of the fields are more or // because the object is relatively complex and all of the fields are more or
// less required. // less required.
function registryRead(publicKey, dataKey) { function registryRead(publicKey, dataKey) {
return new Promise((resolve) => {
let registryModule = "AQCovesg1AXUzKXLeRzQFILbjYMKr_rvNLsNhdq5GbYb2Q"; let registryModule = "AQCovesg1AXUzKXLeRzQFILbjYMKr_rvNLsNhdq5GbYb2Q";
let data = { let data = {
publicKey, publicKey,
dataKey, dataKey,
}; };
return callModule(registryModule, "readEntry", data); callModule(registryModule, "readEntry", data).then(([result, err]) => {
if (err !== null) {
resolve([{}, addContextToErr$1(err, "readEntry module call failed")]);
return;
}
resolve([
{
exists: result.exists,
entryData: result.entryData,
revision: result.revision,
},
null,
]);
});
});
} }
// registryWrite will perform a registry write on a portal. // registryWrite will perform a registry write on a portal.
// //
@ -807,7 +865,7 @@
init: init, init: init,
newKernelQuery: newKernelQuery, newKernelQuery: newKernelQuery,
addContextToErr: addContextToErr$1, addContextToErr: addContextToErr$1,
composeErr: composeErr$1 checkObj: checkObj
}); });
var require$$0 = /*@__PURE__*/getAugmentedNamespace(dist$1); var require$$0 = /*@__PURE__*/getAugmentedNamespace(dist$1);