Replies: 3 comments 5 replies
-
I think your proposal makes a lot of sense and exemplifies the power of account abstraction.
Maybe something to consider here is that code logic may change over time as improved versions emerge as we gain more experience. This could result in a different code root. I wonder if it would be beneficial to include some metadata / a tag which does not change as code logic changes and can be easily indexed and searched for. For example you could have a "recipient" tag as you mention. I'm not sure if this should be embedded in the state tree or if instead it should be emitted as part of an event that is included in a block and then dropped e.g. "NoteCreated(CodeRoot, Recipient, ...)". |
Beta Was this translation helpful? Give feedback.
-
I also agree on the upgradability. Once people are seriously using the system there's going to be a demand for some upgradeability pattern, so it's better if we provide it by design. I think supporting some kind of events / logging is important as well. It probably does make sense to have some default events to minimize overhead for users in common scenarios like public asset transfers, although I don't feel as strongly about this. |
Beta Was this translation helpful? Give feedback.
-
Some thoughts about the case with the simple wallet. In this post I'll cover only public transactions because there is much more complexity around private transactions, and I'd rather handle the simple case first. Receiving assetsThe
The above assumes that I'm also assuming that transaction kernel enforces the following rule:
Technically, this rule is not needed for receiving assets, but it will be handy for sending and swapping assets. The
The above assumes that the sender includes the specified asset in the note's vault and nothing else. While the above works, it makes the script asset-specific: meaning, any time the asset changes (e.g., same fungible asset but with a different amount), the root of the script changes. We can make the script more generic like so:
Now, regardless of which asset is sent, the script of the note is the same. This is convenient because, as the recipient, I can just scan the chain looking for this script to see if anything was sent to me. To make this task simpler, we could require that each note includes a tag. In case of the note above, the tag could be just the root of the script. The full flow for sending-receiving funds could then look as follows:
Sending assetsWhen sending assets we need to make sure that whoever is trying to initiate the transfer has the permission to do so. Let's assume that this is done by verifying a Falcon signature against a public key stored in the account. The procedure for sending assets out of an account could look like so:
In the above, we sign the message which consists of hashing asset, recipient, account ID, and nonce to make sure that the same signature could not be used again in a different context. Also, While the above works, it is actually quite inefficient. Specifically, if we wanted to send assets to multiple recipients within the same transaction, we'd have to verify signature multiple times. A better approach would be to split authentication and note creation into different procedures. For example:
This way, if we wanted to send assets to multiple recipients, a tx script included with a transaction could look like so:
Thus, we only need to call Summary of supporting proceduresI've assumed that we have quite a few procedures available to us in the scripts above. Below I've put them all into a single list.
All of the above will need to make kernel calls. I've omitted such procedures as Lastly, I've oversimplified how notes are created. Specifically, we probably want to have a way of creating notes with multiple assets, and also be able to specify what type of a note it is (e.g., how to set the tag). |
Beta Was this translation helpful? Give feedback.
-
I think it would be beneficial to sketch out (even if in pseudocode for now) some simple contracts, and a basic wallet could be a good one to start with. My intention is that by going through this we could identify any gaps in the current design that need to be filled in.
This first post in the discussion describes requirements of what I think could be interesting to support, and then we can figure out how to support it in the comments.
A simple wallet
The simplest wallet could have just two external interface procedures:
receive_asset(Asset)
which would add the specified asset to the account's vault.send_asset(Asset, Recipient)
which would remove the specified asset from the account's vault and create a note sending the asset to the specified recipient.Within the
send_asset
procedure, we need to make sure that whoever is trying to invoke it, has the permission to do so, and that a transaction cannot be replayed. To support the former, the contract probably will need to store a public key of the user who owns the wallet.Variations on the simple wallet
We could also extend the wallet with the following variations:
set_owner(PubKey)
procedure.A wallet with atomic swaps
Another interesting variation on a simple wallet could be a wallet which support exchanging one asset for another. Thus, in addition to
receive_asset
andsend_asset
, the contract could have an additional external interface procedure:swap_assets(a: Asset, b: Asset, Recipient)
- this procedure would add asseta
to the account's vault, remove assetb
from the account's vault and create a note sending assetb
to the specified recipient.It might also be good to sketch out how a note invoking this procedure could look like. My initial thinking is that it is the note which will need to specify what is asset
a
and what is assetb
, and then it would be up to the owner of the wallet to decided whether they want to take this "trade".A safe wallet
Given the recent private key hacks, it would be good to come up with a wallet design which would be as safe as possible while still being easily usable. Maybe this could be a reference wallet design for Miden right from the start. Here are my very preliminary thoughts on how this could work:
There are 3 keys which control the wallet: a hot key, a cold key, and an external key. Public keys for these are stored in the account. The expectations is that these keys have different levels of protection/accessibility. Specifically:
These keys can be used for different actions within the wallet. Specifically:
receive_asset
send_asset
freeze_account
reset_hot_key
set_send_limit
reset_cold_key
Outgoing transfer throttling
Sending funds out of the account would be throttled based on the spending limits for each asset. The limit could be set for some period of time - e.g., weekly spending limit (it would be interesting to see if there could be an overall spending limit, but that would require somehow figuring out relative worths of different assets). Once the asset reaches its spending limit, no more of this asset can be transferred out from the account until the period expires.
Reseting a hot key exhausts spending limit for the current period. That is, if the hot key is reset, no assets can be sent out of the account until the period expires.
Benefits of this setup
Basically, catastrophic loss of account funds is possible only under the following scenarios:
There could also be a variation on the above where there is only a hot key and an external key. This probably would simplify the design quite a bit without giving up much safety.
Beta Was this translation helpful? Give feedback.
All reactions