Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Accumulate

Wrappers available during the accumulate entry point.

AccumulateContext

Parses arguments and provides accumulate-specific convenience methods. It also serves as the entry point for creating all accumulate-context helpers via factory methods — prefer ctx.*() over standalone *.create().

import { AccumulateContext, Bytes32, BytesBlob, Memo } from "@fluffylabs/as-lan";

export function accumulate(ptr: u32, len: u32): u64 {
  const ctx = AccumulateContext.create();
  const args = ctx.parseArgs(ptr, len);
  // args.slot, args.serviceId, args.argsLength

  const gasLeft = ctx.remainingGas();    // i64 — ecalli 0
  const gas = ctx.checkpoint();          // i64 — commit state, return remaining gas

  // ecalli 25 — publish the accumulation result hash (side effect, no return).
  ctx.yieldResult(Bytes32.zero());

  // Create helpers via the context
  const fetcher = ctx.fetcher();         // AccumulateFetcher
  const preimages = ctx.preimages();     // AccumulatePreimages
  const storage = ctx.serviceData();     // CurrentServiceData
  const admin = ctx.admin();             // Admin
  const cs = ctx.childServices();        // ChildServices
  const self = ctx.selfService();        // SelfService

  // Schedule a transfer (executes after accumulation completes)
  const r1 = ctx.scheduleTransfer(42, 1000, 100);  // ResultN<bool, TransferError>

  // Transfer with explicit memo
  const memo = Memo.create(BytesBlob.encodeAscii("hello"));
  const r2 = ctx.scheduleTransfer(42, 1000, 100, memo);

  // Encode the entry-point return value: Optional<CodeHash> (null = no upgrade).
  return ctx.yieldHash(null);
}

ctx.remainingGas() — return the remaining gas (ecalli 0).

ctx.fetcher(bufSize?) — create an AccumulateFetcher (fetch kinds 0-1, 14-15).

ctx.preimages(bufSize?) — create an AccumulatePreimages helper (lookup + lifecycle).

ctx.serviceData(bufSize?) — create a CurrentServiceData helper for storage read/write.

ctx.admin() — create an Admin helper for privileged governance.

ctx.childServices() — create a ChildServices helper for child service lifecycle.

ctx.selfService() — create a SelfService helper for self-management.

AccumulateFetcher

Fetches context data (fetch kinds 0-1, 14-15): protocol constants, entropy, and accumulate items (operands and transfers).

const fetcher = ctx.fetcher();
const items = fetcher.allTransfersAndOperands();
const one = fetcher.oneTransferOrOperand(0);  // Optional<AccumulateItem>

AccumulatePreimages

Extends base Preimages with preimage lifecycle management (ecalli 22-26).

const preimages = ctx.preimages();

// Look up
const data = preimages.lookup(hash);  // Optional<BytesBlob>

// Query status of a solicited preimage
const status = preimages.query(hash, 64);  // Optional<PreimageStatus>
if (status.isSome) {
  const s = status.val!;
  if (s.kind === PreimageStatusKind.Available) {
    // s.slot0 = timeslot when it became available
  }
}

// Solicit a preimage (request it be made available)
const r1 = preimages.solicit(hash, 64);  // ResultN<bool, SolicitError>

// Forget a solicitation
const r2 = preimages.forget(hash, 64);   // ResultN<bool, ForgetError>

// Provide a preimage to a service
const r3 = preimages.provide(BytesBlob.wrap(data));  // ResultN<bool, ProvideError>

PreimageStatus — returned by query(). A tagged value with kind and up to 3 timeslot fields:

KindFieldsMeaning
RequestedSolicited but not yet available
Availableslot0Currently available (added at slot0)
Unavailableslot0, slot1Was available, now removed
Reavailableslot0, slot1, slot2Removed then re-added

Admin (Privileged Governance)

High-level wrappers for ecallis 14-16 (bless, assign, designate). Only callable by privileged services (manager, delegator, registrar, core assigners).

const admin = ctx.admin();

// Full bless — only the manager can set all fields
admin.bless(
  managerServiceId,
  [assigner1, assigner2],       // one ServiceId per core
  delegatorServiceId,
  registrarServiceId,
  [AutoAccumulateEntry.create(100, 5000)],
);  // ResultN<bool, BlessError>

// Partial bless — delegator/registrar can transfer their own role
admin.blessDelegator(newDelegatorId);   // ResultN<bool, BlessError>
admin.blessRegistrar(newRegistrarId);   // ResultN<bool, BlessError>

// Assign auth queue for a core (only that core's assigner)
admin.assign(coreIndex, [codeHash1, codeHash2]);  // ResultN<bool, AssignError>

// Transfer assigner permission to another service
admin.assign(coreIndex, authQueue, newAssignerServiceId);

// Designate next epoch validators
const key = ValidatorKey.create(ed25519, bandersnatch, bls, metadata);
admin.designate([key]);  // ResultN<bool, DesignateError>

Child Services

Create and eject child services (ecallis 18, 21).

const cs = ctx.childServices();

// Create a child service
const result = cs.newChild(codeHash, codeLen, gas, allowance);
// ResultN<ServiceId, NewChildError>
if (result.isOkay) {
  const childId = result.okay;  // the new ServiceId
}

// Eject a child service (it must have called requestEjection first)
cs.ejectChild(childServiceId, prevCodeHash);  // ResultN<bool, EjectChildError>

Self-Service

Upgrade the current service’s code or request ejection (ecalli 19).

const self = ctx.selfService();

// Upgrade to new code (ensure preimage is available first!)
self.upgradeCode(newCodeHash, minGas, allowance);

// Request ejection by a parent service
// WARNING: clear all storage before calling this!
self.requestEjection(parentServiceId);