Query permissions (Visibility Control 1)
This makes sense even if transaction payloads are not encrypted, as long as:
- Access to the block streaming endpoint is restricted to certain IP addresses
- The permissions for querying blocks and transactions are a subset of those for querying world entities
One known requirement is that when querying transactions, permissions should filter transactions based on participants, not only by the authority -- for example, filtering by transfer sources and destinations.
This means validation should be performed post-execution to inspect query results.
Possible Designs
Let's consider restricting transaction queries -- a high-demand use case. A typical permission model allows users to query only transactions in which they're involved.
(Currently, the executor validates query requests. We should instead validate query results to inspect transaction payloads)
Option 1: Serialize and scan as a string
A last-resort, ad hoc solution:
let verdict = match query_result {
Transaction(transactions) => transactions
.iter()
.all(|txn| txn.to_string().contains(&account_str)),
_ => todo!(),
};
Option 2: Implement use-case-specific methods
Tailored to this use case but not extensible:
let verdict = match query_result {
Transaction(transactions) => transactions
.iter()
.all(|txn| txn.involves(&account)),
_ => todo!(),
};
impl Involves for TransactionLog {
fn involves(&self, account: &AccountId) -> bool {
self.iter().any(|instruction| instruction.involves(&account))
}
}
impl Involves for InstructionLog {
// TODO
}
Option 3: Fractal permission model
- A generic structure reduces use-case-specific code, easing maintenance.
- Offers maximal permission customization.
- No additional implementation needed for event-subscription permissions: #5439
Prerequisites:
- Permission must be registrable as part of the world: #5359
- Permission must represent an abstract world: #5355
- A trivial conversion from
ChangeSettoStateView.
let verdict = query_result.as_state_view().passes(&permission);