Skip to main content

Core API

The supported Core API consists of four methods. Use them to create private state, derive public witnesses and check forward transitions.

Create an instance​

import UldaSign from 'ulda-core';

const core = new UldaSign();

The default profile uses mode S, a five-block window, SHA-256, 256-bit origin blocks, the compactV1 codec and hexadecimal output. See modes and formats before changing the profile.

The package is ESM-only and requires Node.js 22 or later, or a browser with Web Crypto. Core 1.0.x does not ship TypeScript declarations.

New​

New(index = 0n) synchronously creates a new encoded origin with fresh random blocks.

const origin = core.New();

The default return value is a lowercase hexadecimal string. It contains private state and must not be published or logged.

The optional unsigned index is metadata. Starting a new random origin at index 10n does not connect it to another chain at that index.

stepUp​

stepUp(originPackage) synchronously returns the next encoded origin.

const nextOrigin = core.stepUp(origin);

It removes the oldest block, appends fresh randomness and increments the index. It does not mutate the supplied package.

Persist the returned origin if the producer will continue from it. Advancing the same old origin more than once can produce competing branches, so writer coordination belongs to the application.

sign​

sign(originPackage) asynchronously derives the public witness for that origin.

const witness = await core.sign(origin);

The result uses the configured export representation. The method name refers to witness generation: it does not accept or sign an arbitrary application payload.

verify​

verify(previousWitness, candidateWitness) asynchronously checks a directed transition.

const acceptedWitness = await core.sign(origin);
const candidateWitness = await core.sign(nextOrigin);
const valid = await core.verify(acceptedWitness, candidateWitness);

For well-formed packages, the result is a boolean. A transition is rejected when its age does not advance, its gap is not allowed, relevant profile metadata differs, or an overlapping commitment does not match.

The argument order matters. Reversing an otherwise valid pair returns false. A malformed package or unavailable hash implementation can throw instead of returning false.

Own the accepted state​

verify() does not remember an accepted witness or update storage. An integrating verifier must:

  1. Read the currently accepted witness.
  2. Validate and verify the candidate against that exact state.
  3. Atomically replace accepted state only if it has not changed in the meantime.

A separate successful check followed by an unguarded write is not enough when concurrent requests can update the same resource. ULDA Server supplies that coordination for its stored resources.

The first witness needs a trust decision outside Core. Successful chain verification also does not establish a user's identity or authenticate a separate payload.

Stay within the public API​

Internal composition objects and compatibility facades are not stable public API, even when they are visible on an instance. Import the package root and depend on the four methods documented here.

Use the integration requirements and manifest conformance rules when accepting externally supplied packages.