diff --git a/libs/as-sdk/assembly/index.ts b/libs/as-sdk/assembly/index.ts index 36cf575..ae3bc03 100644 --- a/libs/as-sdk/assembly/index.ts +++ b/libs/as-sdk/assembly/index.ts @@ -1,5 +1,13 @@ import Process from './process'; +import Tally from './tally'; + +export { + httpFetch, + HttpFetchMethod, + HttpFetchOptions, + HttpResponse, +} from './http'; -export { httpFetch, HttpFetchMethod, HttpFetchOptions, HttpResponse } from './http'; export { PromiseStatus } from './promise'; -export { Process }; +export { Process, Tally }; +export { RevealBody } from './tally'; diff --git a/libs/as-sdk/assembly/process.ts b/libs/as-sdk/assembly/process.ts index b54ca88..521e256 100644 --- a/libs/as-sdk/assembly/process.ts +++ b/libs/as-sdk/assembly/process.ts @@ -1,3 +1,4 @@ +import { VM_MODE_TALLY, VM_MODE_DR, VM_MODE_ENV_KEY } from './vm-modes'; import { Process as WasiProcess, CommandLine, Environ } from 'as-wasi/assembly'; import { execution_result } from './bindings/seda_v1'; @@ -39,6 +40,35 @@ export default class Process { return result; } + /** + * Gets the mode of the VM instance. + * + * @returns {string} The mode of the VM, either 'dr' or 'tally'. + */ + static getVmMode(): string { + const env = Process.envs(); + + return env.get(VM_MODE_ENV_KEY); + } + + /** + * Returns true when the VM instance is in 'tally' mode. + * + * @returns {boolean} + */ + static isTallyVmMode(): boolean { + return Process.getVmMode() === VM_MODE_TALLY; + } + + /** + * Returns true when the VM instance is in 'dr' mode. + * + * @returns {boolean} + */ + static isDrVmMode(): boolean { + return Process.getVmMode() === VM_MODE_DR; + } + /** * Exits the process with a message * This sets the result of the Data Request execution to the message diff --git a/libs/as-sdk/assembly/tally.ts b/libs/as-sdk/assembly/tally.ts new file mode 100644 index 0000000..b0cb4cc --- /dev/null +++ b/libs/as-sdk/assembly/tally.ts @@ -0,0 +1,63 @@ +import { JSON } from "json-as/assembly"; +import Process from "./process"; + +const REVEALS_ARGUMENT_POSITION = 2; +const CONSENSUS_ARGUMENT_POSITION = 3; + +@json +export class RevealBody { + salt!: u8[]; + exit_code!: u8; + gas_used!: string; + reveal!: u8[]; +} + +@json +export class RevealResult { + salt!: u8[]; + exit_code!: u8; + gas_used!: string; + reveal!: u8[]; + inConsensus!: u8; +} + +export default class Tally { + static getReveals(): RevealResult[] { + const encodedReveals = Process.args().at(REVEALS_ARGUMENT_POSITION); + const reveals = JSON.parse(encodedReveals); + + const encodedConsensus = Process.args().at(CONSENSUS_ARGUMENT_POSITION); + const consensus = JSON.parse(encodedConsensus); + + const revealsAmount = reveals.length; + const consensusAmount = consensus.length; + if (revealsAmount !== consensusAmount) { + throw new Error( + `Number of reveals (${revealsAmount}) does not equal number of consensus reports (${consensusAmount}).` + ); + } + + const revealResults: RevealResult[] = []; + for (let index = 0; index < reveals.length; index++) { + const reveal = reveals[index]; + + revealResults.push({ + exit_code: reveal.exit_code, + gas_used: reveal.gas_used, + reveal: reveal.reveal, + salt: reveal.salt, + inConsensus: consensus.at(index), + }); + } + + return revealResults; + } + + static getConsensusReveals(): RevealResult[] { + const revealResults = Tally.getReveals(); + + return revealResults.filter( + (revealResult) => revealResult.inConsensus === 0 + ); + } +} diff --git a/libs/as-sdk/assembly/vm-modes.ts b/libs/as-sdk/assembly/vm-modes.ts new file mode 100644 index 0000000..a0acf4d --- /dev/null +++ b/libs/as-sdk/assembly/vm-modes.ts @@ -0,0 +1,3 @@ +export const VM_MODE_ENV_KEY = "VM_MODE"; +export const VM_MODE_TALLY = "tally"; +export const VM_MODE_DR = "dr";