Skip to content

SCv2 Transition Linkage v1

Status: frozen for TKT-P3-37.

Purpose: define the exact mapping from pre/post SCv2 roots to state_in and state_out for prover/verifier v1.

1. Canonical linkage contract

For one confidential transition:

  • SCv2_pre = encodeStateCellV2(poolId32, shardId32, noteRoot_pre, nullRoot_pre)
  • SCv2_post = encodeStateCellV2(poolId32, shardId32, noteRoot_post, nullRoot_post)

Then:

  • state_in = HASH256(SCv2_pre)
  • state_out = HASH256(SCv2_post)

state_in and state_out are the exact 32-byte values carried in PIv1.

2. Field ordering and encoding

SCv2 encoding order is frozen as:

  1. version = "SCv2" (ASCII, 4 bytes)
  2. poolId32
  3. shardId32
  4. noteRoot32
  5. nullRoot32

No alternate field orderings are valid.

3. Pre/post mapping rules

  • poolId32 MUST match between pre and post state cells.
  • shardId32 MUST match between pre and post state cells.
  • noteRoot32/nullRoot32 are the only transition-varying SCv2 root fields.
  • Any linkage check must reject pool/shard mismatches.

4. Host and covenant parity

Host-side and covenant-side checks are in parity when they consume the same PIv1 and derive/verify the same (state_in, state_out) pair from the same SCv2 pre/post roots.

Canonical shared fixture:

  • packages/pool-state/test-vectors/state_transition_linkage_v1.json (vectorA)
  • Source scenario: fixtures/phase3/alice_bob_pool_internal_send_v1.json

This fixture is consumed by:

  • pool-state linkage tests
  • host evaluation tests
  • covenant/kernel mock backend evaluation tests

5. Scope limits

This v1 freeze intentionally covers only one-state-cell pre/post linkage and does not introduce batching/aggregation linkage semantics.