mirror of
https://github.com/logos-blockchain/logos-execution-zone.git
synced 2026-05-27 02:19:25 +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.
|
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
|
### Validity windows
|
||||||
|
|
||||||
Programs can constrain when their outputs are accepted by the sequencer:
|
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.
|
- Private update: verify membership proof; compute update nullifier; increment nonce via `nonce_increment`; encrypt post-state.
|
||||||
5. Emit `PrivacyPreservingCircuitOutput`.
|
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
|
### Circuit input
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user