Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

zcash_client_sqlite: Make it easy to write data-migration tests #1507

Open
str4d opened this issue Aug 21, 2024 · 0 comments
Open

zcash_client_sqlite: Make it easy to write data-migration tests #1507

str4d opened this issue Aug 21, 2024 · 0 comments
Labels

Comments

@str4d
Copy link
Contributor

str4d commented Aug 21, 2024

We have a suite of increasingly-comprehensive tests for applying migrations to empty databases:

  • Each migration has a test migrating from an empty wallet DB to itself.
  • zcash_client_sqlite: Fix migration DAG edges #1506 adds a test that migrates incrementally through each publicly-released terminal migration state (i.e. to the set of leaf migration nodes exposed in a given crate release).

This does a pretty good job of testing schema migrations. What we don't have is good tests of data migrations that are conditional on some data being in the wallet. Some migrations have targeted tests covering some or all of their data migration (e.g. #1506 adds one), but particularly for transaction-involving data migrations doing so is laborious to set up comprehensively.

I propose that we add a test-only module somewhere to zcash_client_sqlite containing hard-coded transactions involving a hard-coded wallet seed phrase, that span every possible transaction type we expect to find in the wallet along multiple axes:

  • Single-pool (fully-shielded or fully transparent) vs pool-crossing
  • Spends from Orchard vs Sapling vs transparent
  • Received into Orchard vs Sapling vs transparent
  • Received from one pool vs multiple
  • Spends from one pool vs multiple
  • Receives to / spends from ephemeral (the two ZIP 320 transaction kinds)
  • Mined vs unmined
  • Anything else we come up with

For ease of both preparation and management, the module should be structured something like this (actual sub-modules should be one-per-file, as transactions with shielded components will be very large when hard-coded due to proofs):

// Somewhere inside a #[cfg(test)] module

pub(crate) mod baked {
    pub(crate) const MNEMONIC: &str = "...";

    pub(crate) const RAW_TXS: &[&[u8]] = &[
        orchard_only_rx::TX,
        sapling_only_rx::TX,
        transparent_only_rx::TX,
        ...
    ];

    pub(crate) fn seed() -> Vec<u8> {
        // Derive seed from MNEMONIC; returned as Vec<u8> for ease of cloning in tests.
    }

    pub(crate) fn all_txs() -> Vec<Transaction> {
        RAW_TXS.iter()
            .map(|raw_tx| Transaction::read(raw_tx).expect("valid"))
            .collect()
    }

    // Maybe useful depending on how much boilerplate we need.
    pub(crate) fn add_all_txs_to_wallet(db_data: &WalletDb<..>) {
        let add_tx_to_wallet = db_data.conn.prepare(...);
        for raw_tx in raw_txs {
            let tx = Transaction::read(raw_tx).expect("valid");
            let txid = tx.txid();
            add_tx_to_wallet.execute(...);
        }
    }

    mod orchard_only_rx {
        //! Documentation about the structure of this transaction.

        const TX: &[u8] = &[...];
    }

    mod sapling_only_rx {
        //! Documentation about the structure of this transaction.

        const TX: &[u8] = &[...];
    }

    mod transparent_only_rx {
        //! Documentation about the structure of this transaction.

        const TX: &[u8] = &[...];
    }
}

Then in each migration we can add tests similar to #1506 that:

  • Create a wallet using the baked seed.
  • Apply the declared dependencies of the migration.
  • Add the baked transactions to the wallet.
    • Some migrations may require adding a subset of the migrations depending on what capabilities were present at that point in the database history.
  • Apply the migration.

As we come up with new kinds of transactions the wallet can support, we'd add new baked transactions to the module.

@str4d str4d added the testing label Aug 21, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant