posl docs
poslProtocol reference

The ext data hash

The one value that ties a proof to everything the user controls. The program computes it itself; it never accepts one from the user.

Definition#

struct PoslExtData {            // borsh encoding, in this order
    kind: u8,                   // 1 transact, 2 lock, 3 unlock, 4 claim stake, 5 claim volume
    recipient: Pubkey,
    ext_amount: i64,
    fee: u64,
    fee_recipient: Pubkey,
    mint: Pubkey,
    encrypted_output1: Vec<u8>,
    encrypted_output2: Vec<u8>,
    extra: [u8; 64],
}
extDataHash = sha256(borsh(PoslExtData)) read little-endian, reduced mod r (BN254),
              passed big-endian as a public input

What each instruction puts in it#

Instructionrecipientext_amount / feefee_recipientoutputsextra
transactrecipient token accountas givenfee recipient accountboth encrypted outputscredit pubkey | credit blinding
lockdefault0 / feefee recipient accountchange, lockedzero
unlockdefault0 / feefee recipient accountoutput, emptyzero
claim stake, claim volumedefault0 / 0defaultreward, emptyzero

Why it matters#

  • The kind stops a proof made for one instruction from being replayed on another.
  • Recipient and fee recipient are the accounts actually passed to the instruction. A relayer that swaps either one makes the proof fail (InvalidProof, tested).
  • The mint is the pool's, from its state: a proof cannot be moved to another pool.
  • Encrypted outputs are bound too, so nobody can replace the copy a wallet needs to find its note.
  • Credit key and blinding (transact) are bound, so a relayer cannot redirect the volume credit to itself.

The SDK computes the same value in extDataHash() (sdk/src/posl.mjs) to build the proof.