Skip to content

Tutorial 3 — Choose a Stock State Machine

Open a stock approval workflow in App-Chain Studio

  • Level: beginner for selection, advanced for wire integration
  • Outcome: choose the smallest built-in deterministic model that matches your application before writing a plugin.

Selecting a state machine is a consensus decision. Every member must use the same id and deterministic settings. For a new chain it is configuration; for an existing chain, changing semantics requires a governed/versioned profile activation or a new chain.

MachineUse it whenAuthorization modelProven state
ordered-logYou need immutable ordered opaque eventsAny admitted memberMessage by message ID
kv-registryYou need mutable named recordsFirst writer owns a keyCurrent owner/value per key
approvalsValidator members are the approversDistinct member keysStatus and decision trail
balancesYou need internal credits/nettingA member spends its own accountBalance per account
doc-trailYou need ordered history per product/caseAdmitted member appendsCount and chained trail head
role-approvalsBusiness actors differ from validator membersGoverned actors, organizations and rolesPayload hash and signed decision trail
evidence-v1-gatedApproval coordinates S3/IPFS/Kafka publicationStock composite workflowOne root across components/effects
role-evidenceBusiness actors differ from validator membersGoverned actors, organizations, rolesRegistry, policy, decisions, evidence

The local launcher reads app/config/application-appchain.yml. A standalone deployment can configure one machine directly:

yano:
app-chain:
chain-id: workflow-chain
state-machine: approvals
members: <comma-separated-member-public-keys>
threshold: 2
signing-key: <this-member-seed-from-a-secret-source>

The cluster launcher’s multi-chain form is:

yano:
app-chain:
chains[2]:
chain-id: workflow-chain
state-machine: approvals
block:
interval-ms: 1000

The launcher injects members, threshold, signing key, peers, and fixed proposer. Do not duplicate that injected material in the shared demo YAML.

Stock machines interpret bounded CBOR commands. Use their Java encoders or a compatible implementation; do not serialize arbitrary Java objects.

[0, itemId, payloadBytes, requiredApprovals, deadlineMillis] propose
[1, itemId] approve
[2, itemId] reject

The state key is UTF-8 i/<itemId>. Approvers are deduplicated by member key, one rejection is terminal, and deadlines use the finalized block timestamp. Use this only when consortium node members intentionally are the business approvers.

[0, destinationAccount, positiveAmount] mint
[1, destinationAccount, positiveAmount] transfer from sender's account

The state key is UTF-8 b/<account>. A configured minter can restrict minting; a transfer that would overdraw is a deterministic no-op.

[entityId, entryHashBytes, optionalReference]

The state key is UTF-8 e/<entityId>. The machine stores a count and running Blake2b-256 head over previous head, entry hash, and author. Documents remain off chain; retrieve event bodies from block history and prove the current head.

Configuration is not arbitrary workflow composition

Section titled “Configuration is not arbitrary workflow composition”

Configuration can select and parameterize already implemented semantics. It cannot safely express arbitrary component order or terminal transitions, because those affect every member’s state root.

Use:

  1. stock configuration when one machine/profile already matches;
  2. a small composite plugin when existing components need a new committed order or transition; or
  3. a custom state-machine plugin for new business state or rules.
  • Treating a REST API key as an approval identity.
  • Changing machine settings on one member only.
  • Considering an accepted envelope proof that the command changed state.
  • Putting large or secret documents in replicated command bodies.
  • Adding network, wall-clock, DNS, or random behavior inside apply().
  • Reusing a machine id after changing its deterministic behavior.