Adding vectors
Golden vectors are the source of truth in Strata.
They define what is correct behavior across all implementations. Code exists to satisfy vectors, never the other way around.
This page explains when, why, and how to add vectors.
What vectors are
A vector is a fully specified test case that defines:
Input representation (
.stor raw bytes)Canonical binary output (
.scb.hex)Canonical hash (
.hash.hex)Or a required failure (
.error.json)
Vectors are language-agnostic. They are consumed directly by Rust, JavaScript, and any future implementations.
When vectors must be added
Vectors MUST be added in the following situations:
Introducing a new Northstar
Adding a new invariant
Extending canonical behavior
Adding new error cases
Locking down edge cases
Preventing a regression
If behavior matters, it must be vectorized.
When vectors must NOT be added
Vectors must NOT be added to:
Patch over a broken implementation
“Fix” failing tests without an invariant
Encode undocumented behavior
Introduce ambiguity
Change existing truth silently
If a vector contradicts existing vectors, the change requires a new version and a new Northstar.
Vector categories
Strata vectors are grouped by purpose.
Positive vectors
Define valid inputs and their canonical outputs.
They include:
.stsource.scb.hexcanonical binary.hash.hexcanonical hash
These vectors prove correct behavior.
Negative vectors
Define invalid inputs and required failures.
They include:
.hexraw input bytes.error.jsonexpected error kind and offset
Negative vectors prove strictness.
Semantic vectors
Define higher-level invariants such as:
Decode → encode round-trips
Non-canonical input normalization
Structural equivalence
Cross-version behavior
These vectors prove meaning, not just bytes.
Directory structure
Vectors are versioned and never overwritten.
Example:
Rules:
New vectors go into a new version directory
Existing vectors are immutable
Version directories correspond to Northstars
Naming rules
Vector names must be:
Stable
Descriptive
Ordered when possible
Examples:
01-basic02-map-order03-bigint-bytesneg-01-invalid-tagneg-02-truncated-string
Do not rename vectors once published.
Writing a positive vector
A positive vector must include:
A clear
.stsourceThe exact canonical
.scb.hexThe exact canonical
.hash.hex
All three must agree.
The .st file is human-facing. The .scb.hex and .hash.hex are law.
Writing a negative vector
A negative vector must include:
A
.hexfile with raw bytesA
.error.jsonfile describing:Error kind
Error offset
Errors must be precise. Offsets matter.
Example .error.json:
Validation requirements
Every added vector MUST:
Be consumed by Rust tests
Be consumed by JavaScript tests
Fail loudly if behavior diverges
Run in CI
A vector that is not enforced does not exist.
Never modify existing vectors
This rule is absolute.
Do not edit
Do not reformat
Do not regenerate
Do not “fix” old vectors
If existing vectors are wrong, the fix is:
A new version
New vectors
A new Northstar
History is immutable.
Vectors over opinions
If there is disagreement about behavior:
Write a vector
Encode the invariant
Let CI decide
Discussions end where vectors begin.
Summary
Adding vectors means:
Encoding truth, not convenience
Freezing behavior permanently
Enforcing invariants across languages
If something matters, add a vector. If it does not have a vector, it is not guaranteed.
Last updated
Was this helpful?