User Wallet
In this section we sketch how a user wallet could work, i.e., what kind of state would it need to store, how to retrieve the state and how to make new transactions. We assume Deterministic Secret Management is used.
Current State and Creating Transactions
The current state of the user consists of:
seed
-- the master seed used to derive all secretsid
-- the ZK-ID of the userCurrent note:
trapdoor
nullifier
account
-- the current account state
Given all the above it's possible to update the state with the update_note
transaction, as explained in Notes and Accounts (or the adjusted version in Anonymity Revokers) indeed the reader is encouraged to check that all the proofs necessary to craft a new transactions can be generated using the data listed above.
Restoring the State from the master seed
The whole premise behind using a single master seed
is that the user can recover the entire state as above just from the seed
and the on-chain data. Of course the recovery process might be lengthy, but should be possible. On the other hand, for everyday operation the user is supposed to keep its current state, and preserve it, for efficiency.
Recovering the current state of a user consists of several steps:
Generate the ZK-ID
id
of the user deterministically fromseed
Compute the key
key=key(id)
Obtain the chronological list of all transactions
tx_1, tx_2, ... tx_n
that were finalized on chain:To this end filter the list of all transactions sent to the shielder from all users. The filtering rule is as follows:
let
tx
be a transactionlet
mac = (m_0, m_1)
be the mac oftx
If
m_1 = hash(m_0, key)
then keep thetx
as it means it belongs to the user
(Note that this step is quite inefficient as written, below we explain how one can go about improving the efficiency).
tx_1
is thenew_note
transaction and can be thus ignored. For the remaining ones perform the following procedure to recover the currentaccount
.Set
account := Account::new()
For
tx
in[tx_2, tx_3, ..., tx_n]
do:Extract
op_pub
out oftx
Extract
op_priv
out ofe_op
using the keykey
to decrypt itCombine
op = combine(op_pub, op_priv)
Update the account
account = Account::update(account, op)
Derive the
trapdoor
andnullifier
of the last note deterministically fromseed
Improving the collection phase
To collect all transactions relevant to the account one has to filter all shielder transactions which is quite slow. There are several ideas on how to improve upon that:
To the
n
th shielder transaction of a user attach an encrypted (usingSymEnc
with keykey(id)
) numberk
being the block number where then-1
th transation landed. This way the only thing the user needs to do is: find its last transaction, and scann
blocks in total.Use fuzzy message detection techniques.
Last updated