Address `TransactionRequest` design decisions
- 主要語言
- Rust
- 星號
- 78
- 分支
- 129
- 平均合併
- 4 天 14 小時
- 30 天內合併 PR
- 52
描述
### Should we bind `TransactionRequest` to a specific `Account`?
(Reference: https://github.com/0xMiden/miden-client/issues/822)
Currently, a transaction can get executed in the `Client` by any `Account`: the API takes the `TransactionRequest` and a specific `AccountId`. However, `TransactionRequest` is not fully sender-agnostic today. “Own notes”, if the request object contains them, effectively embed the sender because certain note types need the sender account ID to be computed. Concretely, swaps derive payback note details inside the swap via `NoteInputs`, which requires the sender ID; faucet mints cannot prevriously declare specific `NoteAssets` because the final assets depend on which faucet actually executes. By contrast, non-own outputs only need a `NoteRecipient` to be complete (`OutputNote::Full`). The current API doesn’t let us build “everything except the sender,” so client code would need to end up duplicating some code from `miden-base`.
We could attempt to make it fully agnostic if we move sender resolution into an explicit binding step. Instead of “own notes,” the request would carry output templates. There are two kinds: (a) external outputs, where a `NoteRecipient` is enough and the note is already full; and (b) own outputs, where we store a template describing what will be emitted via the sender’s `AccountInterface`, and we only materialize it once the sender is known. To make this ergonomic, we introduce a small trait that can be implemented by P2ID, swap, etc., so we can construct notes without duplicating `miden-base` logic. An attempt was done in https://github.com/0xMiden/miden-client/pull/811.
Alternatively, we could decide to bind `TransactionRequest` to a specific account ID. In this sense, the object will already be consistent with all other behaviors.
Or we could explore something in the middle where the request can be "bound" to a specific account ID (eg, by calling a specific `bind()` step, maybe on the builder). Here, sender-dependent validation happens: resolve own-note templates, compute swap payback “future notes,” check faucet constraints, etc. This could be optional and there could be two different request types to have a more explicit separation and the client APIs could support both.
### Remove "leaky" fields
(note: there was an issue/discussion `miden-base` about this that I could not find after a quick search)
The `expected_output_recipients` field exists to support public note creation, because the VM host needs to unhash all recipients related to the public notes that were created during the transaction execution. There are a number of alternatives that we could do to avoid this, like fetching output notes-related data from `DataStore`.
### Input notes as `InputNote`
We could decide to track all inputs as `InputNote` instead of `NoteId`. `InputNote` already describes whether the note gets used as authenticated or unauthenticated so we can merge `input_notes` and `unauthenticated_input_notes` into a single `inputs: Vec`.
There are some implications here. For example, if we do this, we can no longer express the transaction request as a function of something that only the executor knows (if a server somehow sends a `TransactionRequest` for a user to execute, the server is expected to know the details about the notes themselves).
### Revisit `foreign_accounts`
This should be fairly straightforward. Once lazy loading lands, we should be able to remove the foreign accounts description from `TransactionRequest`. We could also decide to keep it only for private accounts, since there is otherwise no other external way to communicate a specific private account state. This is also somewhat related to the account state endpoints refactors, since the client will need to be able to sync specific accounts, and store relevant data so that it can be fetched on transaction runtime.
### Mutators on `TransactionRequest`
https://github.com/0xMiden/miden-client/pull/1254 adds a mutable getter for the advice map that a user may want to set for the transaction to use. This is currently the only way to mutate a `TransactionRequest` object, which breaks a bit with the builder convention of having a static object be created by its builder (ie, `TransactionRequestBuilder`). Is this enough/OK in relation to being able to mutate a request? Are there any more general alternatives that would make sense here? Or we could make mutators even more specific as suggested [here](https://github.com/0xMiden/miden-client/pull/1254#discussion_r2323498876).
---
Some of these are more concrete to address than others, so we can make separate issues as we see fit to track each part accordingly.
貢獻指南
評估
這個 Issue 還沒有評估資料。