# `zmigrate`/`zewif`: Progress Report and Call for Participation
Wolf McNally
Blockchain Commons
March 11, 2025
## Progress Report
I have now reached the point where the `zmigrate` crate [(repo here)](https://github.com/BlockchainCommons/zmigrate) can parse both zcashd and zingo wallet formats into memory. The route to do this was different for each format:
- zcashd is a Berkeley DB database, and the original code is a mix of C++ and Rust. To gain access to the data, the `zmigrate` command line tool invokes the `db_dump` tool to dump the database to text, then parses the text. I mostly parse the dump into my own original Rust structures, which capture the data but don't provide all the functionality of the original C++ or Rust code.
- zingo is a monolithic binary format, and the original code is in Rust. `zingolib` is the library that provides the functionality to read and write the zingo format. I have leveraged a good chunk of that original code, primarily by copying and then modifying the high-level functions to work within the `zmigrate` crate, and relying on the original code and its dependencies to do the heavy lifting. Unfortunately, `zingolib` exists only as a GitHub repo and is not currently published to `crates.io` as a versioned library. In addition, many of its dependencies are pinned to specific commits in GitHub. Hopefully this will be a non-issue down the road, as wallet format-specific code as frontends or backends to `zmigrate` will eventually be in their own crates, while the core `zmigrate` crate/framework/library/tool will remain format-agnostic and its only dependencies, where necessary, will be officially released crates.
I am now taking another pass over the zcashd wallet parsing code to discover Rust structures in the zingolib dependencies that both in-memory formats can share. There are certain small but obvious overlaps like `TxId` and `CompactSize` that are widely used in the Zcash and crypto community. I will also be looking for other overlaps like keys and addresses, but this is where the subtleties of specific wallet formats start to enter, where nearly identical structures might be used in semantically differing ways, so I'm being quite conservative. I expect to complete this in a couple days.
## Call for Participation
Now I want to turn to finding the core abstractions that these two (and by extension many) wallet formats share. I am thinking of things like `Wallet`, `Account`, `Address`, `Transaction`, `TxIn`, `TxOut`, `TxOutPoint`, etc (see the expanded rough outline in Rust below). In support of this, I want to directly enlist the expertise of the Zcash community, particularly experts in the zcashd and zingo formats at this time. The participation of experts in other wallet formats is also very welcome because this is where the rubber meets the road in terms of generalizing the wallet abstractions.
Sometime soon, probably Friday or early next week, I would like to have an approximately two-hour meeting with interested parties to review my work in detail and create an outline of the core abstractions that the `zmigrate` crate will provide. I expect the Zoom meeting will be complemented with a collaborative HackMD.io markdown document into which all participants are invited to add real-time enhancements.
These abstractions will then lead to the definition of the zewif wallet interchange format, which will include attachment points for more esoteric and wallet format-specific auxiliary data that this working group will also help identify.
Please contact us ASAP with your interest and availability.
## Rough Outline of Interchange Wallet
*Note:* In the following code `Blob<N>` is a fixed-sized binary object and `Data` is a variable-sized binary object. For brevity, all the other usual boilerplate has been elided.
If you spot deficiencies or inaccuracies, good! You should come to the meeting.
```rust
/// Represents an entire wallet, including multiple accounts,
/// a global transaction history, and optionally a BIP-39
/// mnemonic for seed-based key derivation.
struct InterchangeWallet {
mnemonic: Option<Mnemonic>,
accounts: Vec<Account>,
transactions: Vec<Transaction>,
}
/// A BIP-39 mnemonic phrase used for wallet seed generation and recovery.
struct Mnemonic {
phrase: String,
}
/// Logical grouping within a wallet. Each account can have its own set of addresses.
struct Account {
name: String,
addresses: Vec<Address>,
}
/// A wallet address can be either a transparent address or one of several shielded types.
enum Address {
/// A transparent (T-address) similar to Bitcoin's.
Transparent(String),
/// A shielded address (Z-address). This can include Sapling, Sprout, or Orchard formats.
Shielded(ShieldedAddress),
}
/// Details specific to shielded addresses.
struct ShieldedAddress {
/// The actual address string (could encode Sapling, Orchard, etc.).
address: String,
/// Optional diversifier or other Zcash-specific metadata.
diversifier: Option<Data>,
}
/// A transaction that can combine both transparent and shielded components.
struct Transaction {
txid: TxId,
inputs: Vec<TxIn>,
outputs: Vec<TxOut>,
/// Optional data for shielded spends (e.g., Sapling/Orchard spends).
shielded_spends: Option<Vec<ShieldedSpendData>>,
/// Optional data for shielded outputs (e.g., Sapling/Orchard outputs).
shielded_outputs: Option<Vec<ShieldedOutputData>>,
/// For legacy Sprout transactions that use JoinSplit descriptions.
joinsplit: Option<JoinSplitData>,
// Additional metadata such as block height, confirmations, or timestamp may be added here.
}
/// A 32-byte transaction identifier.
struct TxId(Blob<32>);
/// A reference to a previous transaction output.
struct TxOutPoint {
txid: TxId,
index: u32,
}
/// A transparent transaction input.
struct TxIn {
previous_output: TxOutPoint,
/// Script signature for unlocking the previous output.
script_sig: Data,
sequence: u32,
}
/// A transparent transaction output.
struct TxOut {
value: Amount,
script_pubkey: Data,
}
/// Data specific to shielded spends (applicable to Sapling/Orchard).
struct ShieldedSpendData {
/// The anchor of the current commitment tree.
anchor: Blob<32>,
/// A nullifier to ensure the note is spent only once.
nullifier: Blob<32>,
/// A zero-knowledge proof that the spend is valid.
zkproof: Data,
// Additional fields (e.g., spending key components) may be required.
}
/// Data specific to shielded outputs.
struct ShieldedOutputData {
/// The note commitment.
commitment: Blob<32>,
/// Ephemeral key for the encrypted note.
ephemeral_key: Blob<32>,
/// Encrypted ciphertext containing the note details.
enc_ciphertext: Data,
/// An optional memo field.
memo: Option<Data>,
}
/// For legacy Sprout transactions: JoinSplit descriptions that mix transparent and shielded values.
struct JoinSplitData {
anchor: Blob<32>,
nullifiers: Vec<Blob<32>>,
commitments: Vec<Blob<32>>,
/// A zero-knowledge proof to validate the JoinSplit operation.
zkproof: Data,
// Further fields may be added as necessary.
}
```