pub fn token_pool_output_only_extra_sighash_data(
action_type: TokenTransitionActionType,
token_id: &[u8; 32],
owner_id: &[u8; 32],
platform_version: &PlatformVersion,
) -> Result<Vec<u8>, ProtocolError>Expand description
Extra sighash data of an outputs-only token pool bundle — TokenShield, TokenMintToPool,
TokenClaimToPool and TokenDirectPurchaseToPool: the bundle’s domain tag, the token id
and the identity the bundle is attributed to.
These bundles have no spends, so nothing pins them to a pool: their anchor is never checked against one — the client builds it against the empty tree — and the proof and binding signature verify against any pool. Without this data the authorized bundle bytes are a free-standing, self-verifying object that anybody can lift out of the mempool into a transition of their own. Each of the three fields closes one direction of that:
- The token id keeps a bundle out of every other token’s pool. That pool has its own
nullifier tree, so a copy there would leave both notes spendable; the harm is that the
recipient would hold notes derived from one
rhoin two pools, which links their spends across pools. - The tag keeps the kinds’ preimages disjoint in the same pool. Bundles of different kinds are otherwise indistinguishable to the proof — same flags, same empty-tree anchor, and the same value balance whenever the amounts match. A same-pool reuse is also caught by the nullifier record described below.
- The owner keeps it out of every other identity’s transition of the same kind into the same pool. Without it a copier could take a bundle from the mempool and land it ahead of its author, funding the notes the author built with its own tokens, credits or claim, or minting them with its own authority. The author’s own transition would then be refused on its recorded dummy nullifier and charged its fee.
owner_id is the batch owner, except for a group action mint, where it is the group
action’s proposer: a group action pins the digest of the bundle’s actions, so every other
signer submits the proposer’s bundle unchanged and the preimage must not depend on whose
batch carries it. TokenShield, TokenClaimToPool and TokenDirectPurchaseToPool are
never group actions.
The preimage does not stop the owner from submitting its own bundle twice. That, and any
other repeat of a bundle into the same pool, consensus refuses on the state side: every
token pool write that takes an outputs-only bundle records the bundle’s dummy nullifiers in
the pool’s nullifier tree, and a bundle whose dummy nullifier is already there is refused
with NullifierAlreadySpentError. A repeat that got through would land a second note with
the same commitment and the same rho, hence the same nullifier, of which only one could
ever be spent.