STAS 3.0 v0.1 §7 unlocking-script witness assembly (slots 1-20).
A STAS 3.0 unlock script is built from three concatenated regions:
witness_bytes (slots 1-20, this module)
‖ authz (§10 — `<sig> <pubkey>`, OP_0/<sigs>/<redeem>, or
OP_FALSE for no-auth) — emitted by
`BSV.Tokens.Template.Stas3.sign/3`.
‖ trailing_params (§9.5 atomic-swap counterparty pieces, or
§8.1 merge piece array) — emitted by
`BSV.Tokens.Script.Stas3Pieces` when txType > 0.This module is responsible for the FIRST region only — slots 1 through 20
pushed in spec order. The structure carries everything required to build
those bytes; the encoder is to_script_bytes/1.
Slot layout (spec §7, in stack-push order)
| # | Slot | Type | Absence rule |
|---|---|---|---|
| 1 | out1_amount | minimal LE up to 8 B | empty push if no STAS out 1 |
| 2 | out1_addr | 20 B owner PKH | empty push |
| 3 | out1_var2 | single push | (always pushed; can be empty) |
| 4-6 | out2_* | same as out1 triplet | SKIPPED entirely if absent |
| 7-9 | out3_* | same as out1 triplet | SKIPPED entirely if absent |
| 10-12 | out4_* | same as out1 triplet | SKIPPED entirely if absent |
| 13 | change_amount | minimal LE | OP_FALSE (<<0x00>>) |
| 14 | change_addr | 20 B raw P2PKH-PKH | OP_FALSE |
| 15 | noteData | payload (max 65 533 B) | OP_FALSE |
| 16 | fundIdx | 4 B LE uint32 | OP_FALSE |
| 17 | fundTxid | 32 B raw | OP_FALSE |
| 18 | txType | 1 B (0..7) | always present |
| 19 | sighashPreimage | variable | always present |
| 20 | spendType | 1 B (1..4) | always present |
Slots 4-6, 7-9, 10-12 are SKIPPED entirely (no opcode at all) when the matching STAS output is not produced. Slots 13-17 always emit a single push: either the value or OP_FALSE per the absence column above.
This split between "skip vs OP_FALSE" mirrors the spec verbatim (§7 footnotes ) and *).
Summary
Types
A change output (P2PKH satoshi remainder).
Funding-input identification.
A single STAS output triplet for the witness (slots 1-3, 4-6, 7-9, 10-12).
Functions
Maximum permitted note-data payload length (spec §11).
Encode a Stas3UnlockWitness to its raw witness-script bytes (slots 1-20)
per spec §7.
Types
@type change() :: %{amount: non_neg_integer(), addr_pkh: <<_::160>>}
A change output (P2PKH satoshi remainder).
@type funding_input() :: %{txid: <<_::256>>, vout: non_neg_integer()}
Funding-input identification.
@type stas_output() :: %{ amount: non_neg_integer(), owner_pkh: <<_::160>>, var2: binary() }
A single STAS output triplet for the witness (slots 1-3, 4-6, 7-9, 10-12).
@type t() :: %BSV.Tokens.Stas3UnlockWitness{ change: change() | nil, funding_input: funding_input() | nil, note_data: binary() | nil, sighash_preimage: binary(), spend_type: BSV.Tokens.SpendType.t(), stas_outputs: [stas_output()], tx_type: BSV.Tokens.TxType.t() | non_neg_integer() }
Functions
@spec max_note_bytes() :: pos_integer()
Maximum permitted note-data payload length (spec §11).
Encode a Stas3UnlockWitness to its raw witness-script bytes (slots 1-20)
per spec §7.
Returns {:ok, bytes} on success or {:error, reason} on validation
failure:
{:error, :note_data_too_large}— note payload exceeds 65 533 B.{:error, {:too_many_stas_outputs, n}}— more than 4 STAS outputs.{:error, :invalid_sighash_preimage}— preimage is not a binary.
The output of this function is meant to be concatenated with the authz bytes (and any txType-trailing piece-array bytes) to form the complete unlocking script.