fix(register): align live sentinel flow with successful HAR
This commit is contained in:
600
src/sentinel_vm.js
Normal file
600
src/sentinel_vm.js
Normal file
@@ -0,0 +1,600 @@
|
||||
'use strict';
|
||||
|
||||
const carrierSecrets = new WeakMap();
|
||||
|
||||
const OPCODES = Object.freeze({
|
||||
RUN_ENCODED_PROGRAM: 0,
|
||||
XOR_IN_PLACE: 1,
|
||||
SET_LITERAL: 2,
|
||||
RESOLVE: 3,
|
||||
REJECT: 4,
|
||||
APPEND_OR_ADD: 5,
|
||||
READ_PROPERTY: 6,
|
||||
CALL_WITH_REGISTER_ARGS: 7,
|
||||
COPY_REGISTER: 8,
|
||||
INSTRUCTION_QUEUE: 9,
|
||||
WINDOW_OBJECT: 10,
|
||||
FIND_SCRIPT_SRC_BY_REGEX: 11,
|
||||
STORE_REGISTER_MAP: 12,
|
||||
CALL_WITH_RAW_ARGS: 13,
|
||||
JSON_PARSE: 14,
|
||||
JSON_STRINGIFY: 15,
|
||||
SECRET_KEY: 16,
|
||||
CALL_AND_STORE_RESULT: 17,
|
||||
BASE64_DECODE_IN_PLACE: 18,
|
||||
BASE64_ENCODE_IN_PLACE: 19,
|
||||
CALL_IF_EQUAL: 20,
|
||||
CALL_IF_DELTA_EXCEEDS: 21,
|
||||
RUN_BLOCK: 22,
|
||||
CALL_IF_DEFINED: 23,
|
||||
BIND_METHOD: 24,
|
||||
NOOP_25: 25,
|
||||
NOOP_26: 26,
|
||||
REMOVE_OR_SUBTRACT: 27,
|
||||
NOOP_28: 28,
|
||||
LESS_THAN: 29,
|
||||
DEFINE_VM_FUNCTION: 30,
|
||||
MULTIPLY: 33,
|
||||
AWAIT_VALUE: 34,
|
||||
DIVIDE: 35,
|
||||
});
|
||||
|
||||
function bindSecretToCarrier(carrier, secret) {
|
||||
if (carrier && (typeof carrier === 'object' || typeof carrier === 'function')) {
|
||||
carrierSecrets.set(carrier, String(secret ?? ''));
|
||||
}
|
||||
return carrier;
|
||||
}
|
||||
|
||||
function createSecretCarrier(secret) {
|
||||
return bindSecretToCarrier({}, secret);
|
||||
}
|
||||
|
||||
function resolveSecretInput(secretInput) {
|
||||
if (secretInput && (typeof secretInput === 'object' || typeof secretInput === 'function')) {
|
||||
return carrierSecrets.get(secretInput) ?? '';
|
||||
}
|
||||
return String(secretInput ?? '');
|
||||
}
|
||||
|
||||
function xorCipher(text, secret) {
|
||||
const source = String(text ?? '');
|
||||
const key = String(secret ?? '');
|
||||
if (key.length === 0) {
|
||||
return source;
|
||||
}
|
||||
|
||||
let output = '';
|
||||
for (let index = 0; index < source.length; index += 1) {
|
||||
output += String.fromCharCode(
|
||||
source.charCodeAt(index) ^ key.charCodeAt(index % key.length),
|
||||
);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
function defaultAtob(value) {
|
||||
if (typeof atob === 'function') {
|
||||
return atob(value);
|
||||
}
|
||||
return Buffer.from(String(value), 'base64').toString('binary');
|
||||
}
|
||||
|
||||
function defaultBtoa(value) {
|
||||
if (typeof btoa === 'function') {
|
||||
return btoa(value);
|
||||
}
|
||||
return Buffer.from(String(value), 'binary').toString('base64');
|
||||
}
|
||||
|
||||
function isPromiseLike(value) {
|
||||
return Boolean(value) && typeof value.then === 'function';
|
||||
}
|
||||
|
||||
function toErrorText(error) {
|
||||
return String(error);
|
||||
}
|
||||
|
||||
function isBase64Like(value, atobImpl, btoaImpl) {
|
||||
if (typeof value !== 'string' || value.length === 0 || value.length % 4 !== 0) {
|
||||
return false;
|
||||
}
|
||||
if (!/^[A-Za-z0-9+/]+=*$/.test(value)) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
return btoaImpl(atobImpl(value)) === value;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
class ReadableSssdkInterpreter {
|
||||
constructor(options = {}) {
|
||||
this.windowRef = options.windowRef ?? globalThis.window ?? globalThis;
|
||||
this.documentRef = options.documentRef ?? globalThis.document ?? { scripts: [] };
|
||||
this.atob = options.atobImpl ?? defaultAtob;
|
||||
this.btoa = options.btoaImpl ?? defaultBtoa;
|
||||
this.defaultTimeoutMs = options.timeoutMs ?? 500;
|
||||
this.hooks = options.hooks ?? {};
|
||||
|
||||
this.registers = new Map();
|
||||
this.stepCount = 0;
|
||||
this.executionTail = Promise.resolve();
|
||||
}
|
||||
|
||||
static bindSecretToCarrier(carrier, secret) {
|
||||
return bindSecretToCarrier(carrier, secret);
|
||||
}
|
||||
|
||||
static createSecretCarrier(secret) {
|
||||
return createSecretCarrier(secret);
|
||||
}
|
||||
|
||||
resetMachine(secret) {
|
||||
this.registers.clear();
|
||||
this.stepCount = 0;
|
||||
|
||||
this.registers.set(OPCODES.RUN_ENCODED_PROGRAM, encodedProgram => {
|
||||
return this._runEncodedProgramLikeOriginalDirect(
|
||||
encodedProgram,
|
||||
{ secret: String(this.getRegister(OPCODES.SECRET_KEY) ?? '') },
|
||||
false,
|
||||
);
|
||||
});
|
||||
|
||||
this.registers.set(OPCODES.XOR_IN_PLACE, (targetRegister, keyRegister) => {
|
||||
const currentValue = String(this.getRegister(targetRegister) ?? '');
|
||||
const keyValue = String(this.getRegister(keyRegister) ?? '');
|
||||
this.setRegister(targetRegister, xorCipher(currentValue, keyValue));
|
||||
});
|
||||
|
||||
this.registers.set(OPCODES.SET_LITERAL, (targetRegister, literalValue) => {
|
||||
this.setRegister(targetRegister, literalValue);
|
||||
});
|
||||
|
||||
this.registers.set(OPCODES.APPEND_OR_ADD, (targetRegister, sourceRegister) => {
|
||||
const currentValue = this.getRegister(targetRegister);
|
||||
const sourceValue = this.getRegister(sourceRegister);
|
||||
|
||||
if (Array.isArray(currentValue)) {
|
||||
currentValue.push(sourceValue);
|
||||
return;
|
||||
}
|
||||
|
||||
this.setRegister(targetRegister, currentValue + sourceValue);
|
||||
});
|
||||
|
||||
this.registers.set(OPCODES.REMOVE_OR_SUBTRACT, (targetRegister, sourceRegister) => {
|
||||
const currentValue = this.getRegister(targetRegister);
|
||||
const sourceValue = this.getRegister(sourceRegister);
|
||||
|
||||
if (Array.isArray(currentValue)) {
|
||||
const position = currentValue.indexOf(sourceValue);
|
||||
if (position >= 0) {
|
||||
currentValue.splice(position, 1);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
this.setRegister(targetRegister, currentValue - sourceValue);
|
||||
});
|
||||
|
||||
this.registers.set(OPCODES.LESS_THAN, (targetRegister, leftRegister, rightRegister) => {
|
||||
this.setRegister(
|
||||
targetRegister,
|
||||
this.getRegister(leftRegister) < this.getRegister(rightRegister),
|
||||
);
|
||||
});
|
||||
|
||||
this.registers.set(OPCODES.MULTIPLY, (targetRegister, leftRegister, rightRegister) => {
|
||||
const leftValue = Number(this.getRegister(leftRegister));
|
||||
const rightValue = Number(this.getRegister(rightRegister));
|
||||
this.setRegister(targetRegister, leftValue * rightValue);
|
||||
});
|
||||
|
||||
this.registers.set(OPCODES.DIVIDE, (targetRegister, leftRegister, rightRegister) => {
|
||||
const leftValue = Number(this.getRegister(leftRegister));
|
||||
const rightValue = Number(this.getRegister(rightRegister));
|
||||
this.setRegister(targetRegister, rightValue === 0 ? 0 : leftValue / rightValue);
|
||||
});
|
||||
|
||||
this.registers.set(OPCODES.READ_PROPERTY, (targetRegister, objectRegister, keyRegister) => {
|
||||
const objectValue = this.getRegister(objectRegister);
|
||||
const propertyKey = this.getRegister(keyRegister);
|
||||
this.setRegister(targetRegister, objectValue[propertyKey]);
|
||||
});
|
||||
|
||||
this.registers.set(OPCODES.CALL_WITH_REGISTER_ARGS, (functionRegister, ...argumentRegisters) => {
|
||||
const callable = this.getRegister(functionRegister);
|
||||
const resolvedArgs = argumentRegisters.map(registerId => this.getRegister(registerId));
|
||||
return callable(...resolvedArgs);
|
||||
});
|
||||
|
||||
this.registers.set(
|
||||
OPCODES.CALL_AND_STORE_RESULT,
|
||||
(targetRegister, functionRegister, ...argumentRegisters) => {
|
||||
try {
|
||||
const callable = this.getRegister(functionRegister);
|
||||
const resolvedArgs = argumentRegisters.map(registerId => this.getRegister(registerId));
|
||||
const returnValue = callable(...resolvedArgs);
|
||||
|
||||
if (isPromiseLike(returnValue)) {
|
||||
return returnValue
|
||||
.then(value => {
|
||||
this.setRegister(targetRegister, value);
|
||||
})
|
||||
.catch(error => {
|
||||
this.setRegister(targetRegister, toErrorText(error));
|
||||
});
|
||||
}
|
||||
|
||||
this.setRegister(targetRegister, returnValue);
|
||||
} catch (error) {
|
||||
this.setRegister(targetRegister, toErrorText(error));
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
this.registers.set(OPCODES.CALL_WITH_RAW_ARGS, (targetRegister, functionRegister, ...rawArgs) => {
|
||||
try {
|
||||
const callable = this.getRegister(functionRegister);
|
||||
callable(...rawArgs);
|
||||
} catch (error) {
|
||||
this.setRegister(targetRegister, toErrorText(error));
|
||||
}
|
||||
});
|
||||
|
||||
this.registers.set(OPCODES.COPY_REGISTER, (targetRegister, sourceRegister) => {
|
||||
this.setRegister(targetRegister, this.getRegister(sourceRegister));
|
||||
});
|
||||
|
||||
this.registers.set(OPCODES.WINDOW_OBJECT, this.windowRef);
|
||||
|
||||
this.registers.set(OPCODES.FIND_SCRIPT_SRC_BY_REGEX, (targetRegister, regexRegister) => {
|
||||
const regex = this.getRegister(regexRegister);
|
||||
const scripts = Array.from(this.documentRef.scripts || []);
|
||||
const firstMatch = scripts
|
||||
.map(script => script?.src?.match?.(regex))
|
||||
.filter(Boolean)[0];
|
||||
|
||||
this.setRegister(targetRegister, (firstMatch ?? [])[0] ?? null);
|
||||
});
|
||||
|
||||
this.registers.set(OPCODES.STORE_REGISTER_MAP, targetRegister => {
|
||||
this.setRegister(targetRegister, this.registers);
|
||||
});
|
||||
|
||||
this.registers.set(OPCODES.JSON_PARSE, (targetRegister, sourceRegister) => {
|
||||
this.setRegister(targetRegister, JSON.parse(String(this.getRegister(sourceRegister))));
|
||||
});
|
||||
|
||||
this.registers.set(OPCODES.JSON_STRINGIFY, (targetRegister, sourceRegister) => {
|
||||
this.setRegister(targetRegister, JSON.stringify(this.getRegister(sourceRegister)));
|
||||
});
|
||||
|
||||
this.registers.set(OPCODES.BASE64_DECODE_IN_PLACE, targetRegister => {
|
||||
this.setRegister(targetRegister, this.atob(String(this.getRegister(targetRegister))));
|
||||
});
|
||||
|
||||
this.registers.set(OPCODES.BASE64_ENCODE_IN_PLACE, targetRegister => {
|
||||
this.setRegister(targetRegister, this.btoa(String(this.getRegister(targetRegister))));
|
||||
});
|
||||
|
||||
this.registers.set(
|
||||
OPCODES.CALL_IF_EQUAL,
|
||||
(leftRegister, rightRegister, functionRegister, ...rawArgs) => {
|
||||
if (this.getRegister(leftRegister) === this.getRegister(rightRegister)) {
|
||||
return this.getRegister(functionRegister)(...rawArgs);
|
||||
}
|
||||
return null;
|
||||
},
|
||||
);
|
||||
|
||||
this.registers.set(
|
||||
OPCODES.CALL_IF_DELTA_EXCEEDS,
|
||||
(leftRegister, rightRegister, thresholdRegister, functionRegister, ...rawArgs) => {
|
||||
const delta = Math.abs(this.getRegister(leftRegister) - this.getRegister(rightRegister));
|
||||
if (delta > this.getRegister(thresholdRegister)) {
|
||||
return this.getRegister(functionRegister)(...rawArgs);
|
||||
}
|
||||
return null;
|
||||
},
|
||||
);
|
||||
|
||||
this.registers.set(OPCODES.CALL_IF_DEFINED, (guardRegister, functionRegister, ...rawArgs) => {
|
||||
if (this.getRegister(guardRegister) !== undefined) {
|
||||
return this.getRegister(functionRegister)(...rawArgs);
|
||||
}
|
||||
return null;
|
||||
});
|
||||
|
||||
this.registers.set(OPCODES.BIND_METHOD, (targetRegister, objectRegister, keyRegister) => {
|
||||
const objectValue = this.getRegister(objectRegister);
|
||||
const propertyKey = this.getRegister(keyRegister);
|
||||
this.setRegister(targetRegister, objectValue[propertyKey].bind(objectValue));
|
||||
});
|
||||
|
||||
this.registers.set(OPCODES.AWAIT_VALUE, (targetRegister, sourceRegister) => {
|
||||
try {
|
||||
return Promise.resolve(this.getRegister(sourceRegister)).then(value => {
|
||||
this.setRegister(targetRegister, value);
|
||||
});
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
});
|
||||
|
||||
this.registers.set(OPCODES.RUN_BLOCK, (targetRegister, nestedInstructions) => {
|
||||
const previousQueue = this.getQueueSnapshot();
|
||||
this.setQueue(this.cloneInstructionQueue(nestedInstructions));
|
||||
|
||||
return this.executeCurrentQueue()
|
||||
.catch(error => {
|
||||
this.setRegister(targetRegister, toErrorText(error));
|
||||
})
|
||||
.finally(() => {
|
||||
this.setQueue(previousQueue);
|
||||
});
|
||||
});
|
||||
|
||||
this.registers.set(OPCODES.NOOP_25, () => {});
|
||||
this.registers.set(OPCODES.NOOP_26, () => {});
|
||||
this.registers.set(OPCODES.NOOP_28, () => {});
|
||||
|
||||
this.setRegister(OPCODES.SECRET_KEY, String(secret ?? ''));
|
||||
}
|
||||
|
||||
getRegister(registerId) {
|
||||
return this.registers.get(registerId);
|
||||
}
|
||||
|
||||
setRegister(registerId, value) {
|
||||
if (typeof this.hooks.onSetRegister === 'function') {
|
||||
this.hooks.onSetRegister({
|
||||
registerId,
|
||||
value,
|
||||
stepCount: this.stepCount,
|
||||
});
|
||||
}
|
||||
this.registers.set(registerId, value);
|
||||
}
|
||||
|
||||
getQueueSnapshot() {
|
||||
return [...(this.getRegister(OPCODES.INSTRUCTION_QUEUE) ?? [])];
|
||||
}
|
||||
|
||||
setQueue(queue) {
|
||||
this.setRegister(OPCODES.INSTRUCTION_QUEUE, queue);
|
||||
}
|
||||
|
||||
cloneInstructionQueue(queue) {
|
||||
return Array.isArray(queue) ? [...queue] : [];
|
||||
}
|
||||
|
||||
resolveSecretInput(secretInput) {
|
||||
return resolveSecretInput(secretInput);
|
||||
}
|
||||
|
||||
decodeProgram(encodedProgram, secret) {
|
||||
const binary = this.atob(String(encodedProgram));
|
||||
const jsonText = xorCipher(binary, secret);
|
||||
return JSON.parse(jsonText);
|
||||
}
|
||||
|
||||
queueExclusive(task) {
|
||||
const next = this.executionTail.then(task, task);
|
||||
this.executionTail = next.then(
|
||||
() => undefined,
|
||||
() => undefined,
|
||||
);
|
||||
return next;
|
||||
}
|
||||
|
||||
withRunScope(scopeState, executor) {
|
||||
const previousResolve = this.getRegister(OPCODES.RESOLVE);
|
||||
const previousReject = this.getRegister(OPCODES.REJECT);
|
||||
const previousDefineFunction = this.getRegister(OPCODES.DEFINE_VM_FUNCTION);
|
||||
|
||||
this.setRegister(OPCODES.RESOLVE, rawValue => {
|
||||
scopeState.resolveWire(rawValue);
|
||||
});
|
||||
|
||||
this.setRegister(OPCODES.REJECT, rawValue => {
|
||||
scopeState.rejectWire(rawValue);
|
||||
});
|
||||
|
||||
this.setRegister(
|
||||
OPCODES.DEFINE_VM_FUNCTION,
|
||||
(targetRegister, returnRegister, parameterRegistersOrProgram, maybeProgram) => {
|
||||
const hasParameterRegisters = Array.isArray(maybeProgram);
|
||||
const parameterRegisters = hasParameterRegisters ? parameterRegistersOrProgram : [];
|
||||
const functionProgram = (hasParameterRegisters ? maybeProgram : parameterRegistersOrProgram) || [];
|
||||
|
||||
this.setRegister(targetRegister, (...runtimeArgs) => {
|
||||
if (scopeState.isSettled()) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const previousQueue = this.getQueueSnapshot();
|
||||
|
||||
if (hasParameterRegisters) {
|
||||
for (let index = 0; index < parameterRegisters.length; index += 1) {
|
||||
this.setRegister(parameterRegisters[index], runtimeArgs[index]);
|
||||
}
|
||||
}
|
||||
|
||||
this.setQueue(this.cloneInstructionQueue(functionProgram));
|
||||
|
||||
return this.executeCurrentQueue()
|
||||
.then(() => this.getRegister(returnRegister))
|
||||
.catch(error => toErrorText(error))
|
||||
.finally(() => {
|
||||
this.setQueue(previousQueue);
|
||||
});
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
return Promise.resolve()
|
||||
.then(executor)
|
||||
.finally(() => {
|
||||
this.setRegister(OPCODES.RESOLVE, previousResolve);
|
||||
this.setRegister(OPCODES.REJECT, previousReject);
|
||||
this.setRegister(OPCODES.DEFINE_VM_FUNCTION, previousDefineFunction);
|
||||
});
|
||||
}
|
||||
|
||||
async executeCurrentQueue() {
|
||||
while (this.getQueueSnapshot().length > 0) {
|
||||
const instruction = this.getRegister(OPCODES.INSTRUCTION_QUEUE).shift();
|
||||
const [opcode, ...args] = instruction;
|
||||
const handler = this.getRegister(opcode);
|
||||
|
||||
if (typeof handler !== 'function') {
|
||||
throw new Error(`Unknown opcode: ${opcode}`);
|
||||
}
|
||||
|
||||
const maybePromise = handler(...args);
|
||||
if (isPromiseLike(maybePromise)) {
|
||||
await maybePromise;
|
||||
}
|
||||
|
||||
this.stepCount += 1;
|
||||
}
|
||||
}
|
||||
|
||||
runEncodedProgramLikeOriginal(encodedProgram, options = {}) {
|
||||
return this.queueExclusive(() => {
|
||||
return this._runEncodedProgramLikeOriginalDirect(encodedProgram, options, true);
|
||||
});
|
||||
}
|
||||
|
||||
_runEncodedProgramLikeOriginalDirect(encodedProgram, options = {}, resetMachine = true) {
|
||||
const secret = String(options.secret ?? '');
|
||||
const timeoutMs = options.timeoutMs ?? this.defaultTimeoutMs;
|
||||
|
||||
if (resetMachine) {
|
||||
this.resetMachine(secret);
|
||||
}
|
||||
|
||||
try {
|
||||
return this.executeQueueLikeOriginal(
|
||||
this.decodeProgram(encodedProgram, secret),
|
||||
timeoutMs,
|
||||
);
|
||||
} catch (error) {
|
||||
return Promise.resolve(this.btoa(`${this.stepCount}: ${toErrorText(error)}`));
|
||||
}
|
||||
}
|
||||
|
||||
executeQueueLikeOriginal(instructions, timeoutMs) {
|
||||
const previousQueue = this.getQueueSnapshot();
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
let settled = false;
|
||||
|
||||
const finishResolve = wireValue => {
|
||||
if (settled) {
|
||||
return;
|
||||
}
|
||||
settled = true;
|
||||
clearTimeout(timer);
|
||||
resolve(wireValue);
|
||||
};
|
||||
|
||||
const finishReject = wireValue => {
|
||||
if (settled) {
|
||||
return;
|
||||
}
|
||||
settled = true;
|
||||
clearTimeout(timer);
|
||||
reject(wireValue);
|
||||
};
|
||||
|
||||
const timer = setTimeout(() => {
|
||||
finishResolve(String(this.stepCount));
|
||||
}, timeoutMs);
|
||||
|
||||
const scopeState = {
|
||||
isSettled: () => settled,
|
||||
resolveWire: rawValue => {
|
||||
finishResolve(this.btoa(String(rawValue)));
|
||||
},
|
||||
rejectWire: rawValue => {
|
||||
finishReject(this.btoa(String(rawValue)));
|
||||
},
|
||||
};
|
||||
|
||||
this.withRunScope(scopeState, async () => {
|
||||
this.setQueue(this.cloneInstructionQueue(instructions));
|
||||
|
||||
try {
|
||||
await this.executeCurrentQueue();
|
||||
} catch (error) {
|
||||
finishResolve(this.btoa(`${this.stepCount}: ${toErrorText(error)}`));
|
||||
} finally {
|
||||
this.setQueue(previousQueue);
|
||||
}
|
||||
}).catch(error => {
|
||||
finishResolve(this.btoa(`${this.stepCount}: ${toErrorText(error)}`));
|
||||
this.setQueue(previousQueue);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async runFromInputs(secretInput, encodedPayload, options = {}) {
|
||||
const secret = this.resolveSecretInput(secretInput);
|
||||
return this.normalizeLikeOriginalResult(
|
||||
() => this.runEncodedProgramLikeOriginal(encodedPayload, {
|
||||
...options,
|
||||
secret,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
normalizeLikeOriginalResult(runLikeOriginal) {
|
||||
return Promise.resolve()
|
||||
.then(async () => {
|
||||
try {
|
||||
const wireValue = await runLikeOriginal();
|
||||
return this.normalizeWireValue(wireValue, false);
|
||||
} catch (wireValue) {
|
||||
return this.normalizeWireValue(wireValue, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
normalizeWireValue(wireValue, rejected) {
|
||||
if (!isBase64Like(wireValue, this.atob, this.btoa)) {
|
||||
return {
|
||||
channel: 'timeout',
|
||||
encodedValue: null,
|
||||
value: String(wireValue),
|
||||
stepCount: Number(wireValue),
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
channel: rejected ? 'reject' : 'resolve',
|
||||
encodedValue: wireValue,
|
||||
value: this.atob(wireValue),
|
||||
stepCount: this.stepCount,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
async function runFromInputs(secretInput, encodedPayload, options = {}) {
|
||||
const interpreter = new ReadableSssdkInterpreter(options);
|
||||
return interpreter.runFromInputs(secretInput, encodedPayload, options);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
OPCODES,
|
||||
ReadableSssdkInterpreter,
|
||||
bindSecretToCarrier,
|
||||
createSecretCarrier,
|
||||
resolveSecretInput,
|
||||
runFromInputs,
|
||||
xorCipher,
|
||||
};
|
||||
Reference in New Issue
Block a user