mirror of
https://github.com/logos-blockchain/logos-execution-zone.git
synced 2026-05-25 09:29:33 +00:00
add section explaining pda family bindings
This commit is contained in:
parent
ce0b892ce3
commit
d5ea3e6517
@ -631,6 +631,7 @@ After execution, the runtime processes each post-state's optional `claim`:
|
||||
|
||||
Authorization for private PDAs in chained calls is established by the caller including the PDA seed in `pda_seeds`. In privacy-preserving transactions, the ZK proof additionally verifies that the address matches `AccountId::for_private_pda` using the NPK supplied for that pre-state.
|
||||
|
||||
|
||||
### Validity windows
|
||||
|
||||
Programs can constrain when their outputs are accepted by the sequencer:
|
||||
@ -817,6 +818,34 @@ The circuit takes as private inputs a `PrivacyPreservingCircuitInput`: the seque
|
||||
- Private update: verify membership proof; compute update nullifier; increment nonce via `nonce_increment`; encrypt post-state.
|
||||
5. Emit `PrivacyPreservingCircuitOutput`.
|
||||
|
||||
**Transaction-wide private PDA family binding.** The same `(program_id, seed)` pair can produce different program-derived account IDs for different `npk` and `identifier`. This creates a subtle authorization hazard: a caller that places seed `S` in `pda_seeds` intends to authorize exactly one account to the callee. Without an additional constraint, however, a callee could present two private PDA pre-states that both derive from `(caller_program_id, S)` and the single seed entry would authorize both.
|
||||
|
||||
To close this, the circuit enforces the following rule across an entire transaction:
|
||||
|
||||
> Each `(program_id, seed)` pair may resolve to **at most one** account ID for the duration of the transaction.
|
||||
|
||||
The rule applies to both the `Claim::Pda(seed)` path and the `pda_seeds` authorization path. Every time either path resolves an account under a given `(program_id, seed)`, the resolved account ID is recorded. A later resolution of the same pair must agree with the recorded account ID, or the transaction is rejected.
|
||||
|
||||
In pseudocode:
|
||||
|
||||
```rust
|
||||
// Checked at every Claim::Pda(seed) and at every pda_seeds match, for both public and private PDAs.
|
||||
fn record_or_assert_pda_binding(
|
||||
bindings: &mut Map<(ProgramId, Seed), AccountId>,
|
||||
program_id: ProgramId,
|
||||
seed: Seed,
|
||||
resolved_account_id: AccountId,
|
||||
) {
|
||||
match bindings.get((program_id, seed)) {
|
||||
None => bindings.insert((program_id, seed), resolved_account_id),
|
||||
Some(existing) => assert_eq!(
|
||||
existing, resolved_account_id,
|
||||
"two different accounts resolved under (program_id, seed) in one transaction",
|
||||
),
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Circuit input
|
||||
|
||||
```rust
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user