npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

runar-testing

v0.4.4

Published

Rúnar test framework: Bitcoin Script VM, reference interpreter, and fuzzer

Downloads

1,325

Readme

runar-testing

Test infrastructure for Rúnar: Bitcoin Script VM, reference interpreter, program fuzzer, and test helpers.

This package provides everything needed to verify that compiled Rúnar contracts behave correctly. It contains four major components: a Bitcoin Script virtual machine, a definitional interpreter that serves as a correctness oracle, a program fuzzer for differential testing, and utility helpers for writing contract tests.


Installation

pnpm add runar-testing

Exports

The package exports the following from runar-testing:

| Export | Kind | Description | |---|---|---| | ScriptVM | class | Bitcoin Script virtual machine | | Opcode | enum | Opcode constants | | opcodeName | function | Opcode byte → name | | encodeScriptNumber | function | BigInt → Script number bytes | | decodeScriptNumber | function | Script number bytes → BigInt | | isTruthy | function | Check if a stack element is truthy | | hexToBytes | function | Hex string → Uint8Array | | bytesToHex | function | Uint8Array → hex string | | disassemble | function | Script hex → ASM string | | RunarInterpreter | class | Reference definitional interpreter | | arbContract | fast-check Arbitrary | Generate random valid Rúnar contracts | | arbStatelessContract | fast-check Arbitrary | Generate random stateless contracts | | arbArithmeticContract | fast-check Arbitrary | Generate random arithmetic-focused contracts | | arbCryptoContract | fast-check Arbitrary | Generate random crypto-focused contracts | | TestSmartContract | class | Test wrapper around compiled artifacts (VM-based) | | TestContract | class | Test wrapper using the interpreter (no compilation needed) | | ScriptExecutionContract | class | Script execution via BSV SDK | | expectScriptSuccess | function | Assert script executes successfully | | expectScriptFailure | function | Assert script fails | | expectStackTop | function | Assert specific value on stack top | | expectStackTopNum | function | Assert specific numeric value on stack top | | VMResult | type | VM execution result (success, stack, altStack, error, opsExecuted, maxStackDepth) | | VMOptions | type | VM configuration options (maxOps, maxStackSize, maxScriptSize, flags, checkSigCallback) | | VMFlags | type | VM behavioural flags (enableSighashForkId, enableOpCodes, strictEncoding) | | RunarValue | type | Interpreter value type | | InterpreterResult | type | Interpreter execution result | | TestCallResult | type | Result from TestContract.call() | | OutputSnapshot | type | Snapshot of a transaction output | | MockPreimage | type | Mock sighash preimage for testing | | ScriptExecResult | type | Result from ScriptExecutionContract execution |


Bitcoin Script VM

The ScriptVM executes raw Bitcoin Script bytecode. It implements the BSV instruction set including all re-enabled opcodes (post-Genesis).

Basic Usage

import { ScriptVM, hexToBytes } from 'runar-testing';

const vm = new ScriptVM();
const result = vm.execute(hexToBytes(unlockingScriptHex), hexToBytes(lockingScriptHex));

console.log(result.success);        // true if stack top is truthy
console.log(result.stack);          // stack state after execution (Uint8Array[])
console.log(result.error);          // error message if script failed
console.log(result.altStack);       // alt stack state after execution (Uint8Array[])
console.log(result.opsExecuted);    // number of non-push opcodes executed
console.log(result.maxStackDepth);  // peak stack depth during execution

VM Options

import { ScriptVM } from 'runar-testing';
import type { VMOptions, VMFlags } from 'runar-testing';

const vm = new ScriptVM({
  maxOps: 500_000,              // max non-push opcodes (default 500_000)
  maxStackSize: 800,            // max main + alt stack items (default 1_000)
  maxScriptSize: 10_000_000,   // max script size in bytes (default unlimited)
  flags: {                      // behavioural flags
    enableSighashForkId: false,
    enableOpCodes: true,        // BSV re-enabled opcodes (default true)
    strictEncoding: false,
  },
  checkSigCallback: (sig, pubkey) => true,  // optional; mock mode by default
});

Reference Interpreter

The RunarInterpreter is a definitional interpreter that evaluates Rúnar contracts by walking the AST directly, without compiling to Bitcoin Script. It serves as a correctness oracle.

import { RunarInterpreter } from 'runar-testing';

const interpreter = new RunarInterpreter(initialProperties);
interpreter.setContract(contractNode);

const result = interpreter.executeMethod(contractNode, 'unlock', {
  sig: { kind: 'bytes', value: sigBytes },
  pubKey: { kind: 'bytes', value: pubKeyBytes },
});

console.log(result.success);

TestContract API

The recommended way to test contracts. Uses the interpreter (not the VM), with mocked crypto (checkSig always true, checkPreimage always true).

import { TestContract } from 'runar-testing';

// From source string (TypeScript format by default)
const counter = TestContract.fromSource(source, { count: 0n });
counter.call('increment');
expect(counter.state.count).toBe(1n);

// Multi-format: pass fileName to select parser
const solCounter = TestContract.fromSource(solSource, { count: 0n }, 'Counter.runar.sol');

// From file path
const contract = TestContract.fromFile('./contracts/Counter.runar.ts', { count: 0n });

Mock Preimage

For testing time-locked or amount-constrained stateful contracts, use setMockPreimage to override the sighash preimage fields seen by checkPreimage:

import { TestContract } from 'runar-testing';

const contract = TestContract.fromSource(source, { deadline: 1000n });

// Override mock preimage fields (all fields are bigint)
contract.setMockPreimage({
  locktime: 500n,
  amount: 10000n,
});

// Subsequent calls will see the overridden preimage values
const result = contract.call('withdraw');
expect(result.success).toBe(true);

The MockPreimage type has four optional fields:

interface MockPreimage {
  locktime: bigint;
  amount: bigint;
  version: bigint;
  sequence: bigint;
}

setMockPreimage accepts a Partial<MockPreimage> -- only the fields you provide are overridden; the rest keep their defaults.


Program Fuzzer

The fuzzer generates random valid Rúnar programs using fast-check Arbitrary combinators. Inspired by CSmith (Yang et al., PLDI 2011).

Usage with fast-check

import { arbContract, arbStatelessContract, arbArithmeticContract, arbCryptoContract } from 'runar-testing';
import fc from 'fast-check';
import { compile } from 'runar-compiler';

// Property test: every generated contract compiles without errors
fc.assert(
  fc.property(arbContract, (source) => {
    const result = compile(source);
    return result.success;
  }),
  { numRuns: 1000 },
);

Available Arbitraries

| Arbitrary | Description | |---|---| | arbContract | Contracts extending SmartContract with 1-3 readonly properties of mixed types, 1-3 methods | | arbStatelessContract | Contracts with no properties, methods use only parameters | | arbArithmeticContract | Contracts focused on bigint arithmetic expressions | | arbCryptoContract | Contracts using checkSig and sha256 with PubKey/Sig types |


Test Helpers

TestSmartContract

A test wrapper around compiled artifacts that executes them in the Script VM:

import { TestSmartContract } from 'runar-testing';

const contract = TestSmartContract.fromArtifact(artifact, constructorArgs);
const result = contract.call('unlock', [sigHex, pubKeyHex]);

expect(result.success).toBe(true);

Assertion Utilities

All assertion helpers take a VMResult (as returned by vm.execute()) rather than raw script hex:

import { ScriptVM, hexToBytes, encodeScriptNumber } from 'runar-testing';
import { expectScriptSuccess, expectScriptFailure, expectStackTop, expectStackTopNum } from 'runar-testing';

const vm = new ScriptVM();
const result = vm.execute(hexToBytes(unlockingHex), hexToBytes(lockingHex));

// Assert script succeeds (top of stack is truthy)
expectScriptSuccess(result);

// Assert script fails
expectScriptFailure(result);

// Assert specific bytes on stack top
expectStackTop(result, new Uint8Array([0x01, 0x02]));

// Assert specific numeric value on stack top
expectStackTopNum(result, 42n);

Crypto Reference Implementations

The package includes reference implementations of post-quantum signature schemes, exported for use in tests and applications:

| Export | Description | |--------|-------------| | wotsKeygen, wotsSign, wotsVerify, WOTS_PARAMS | WOTS+ (Winternitz One-Time Signature) keygen, sign, verify | | WOTSKeyPair | Type for WOTS+ key pairs | | slhKeygen, slhSign, slhVerify, slhVerifyVerbose | SLH-DSA (SPHINCS+, FIPS 205) keygen, sign, verify | | SLH_SHA2_128s, SLH_SHA2_128f, SLH_SHA2_192s, SLH_SHA2_192f, SLH_SHA2_256s, SLH_SHA2_256f | Parameter sets for all 6 FIPS 205 SHA-2 variants | | ALL_SHA2_PARAMS | Array of all SHA-2 parameter sets | | SLHParams, SLHKeyPair | Types for SLH-DSA parameters and key pairs |

import { wotsKeygen, wotsSign, wotsVerify, WOTS_PARAMS } from 'runar-testing';
import { slhKeygen, slhSign, slhVerify, SLH_SHA2_128s } from 'runar-testing';