We're currently working on exposing the get_pre_v1_wallet_keychains() method in the bindings, and after adding a test for it I realized that the function did not quite behave as I was expecting it to.
See attached db for an example of a wallet that was created using two descriptors, but where only the external keychain had revealed addresses (last revealed index is 7).
Running the get_pre_v1_wallet_keychains method with this db returns a vector of PreV1WalletKeychain with a single element, the external keychain.
I've got this buddy Claude who's good at quickly figuring out software stuff and he tells me that the behavior here is because the query uses an INNER JOIN between last_derivation_indices and checksums:
SELECT ... FROM last_derivation_indices AS idx
JOIN checksums AS chk ON idx.keychain = chk.keychain
A row only appears if the keychain exists in both tables. The last_derivation_indices table only gets a row for a keychain when at least one address has been derived from it. If the pre-v1 wallet was created with two descriptors but never derived any internal addresses, then the Internal keychain would have no row in last_derivation_indices, and the JOIN would only return External.
Solutions
This is fine if you know and understand that in cases where the user has not used their internal keychain the vector will not have it, but it feels not quite right either, since the migration workflow probably involves running the function and checking that the descriptors we're about to use indeed correspond to the ones used in the pre-v1 db (through the checksum field).
I think one fix would be to make the last_derivation_index field an Option<u32> to allow for None to exist there when the keychain hasn't revealed any addresses. Unfortunately this would be breaking, so only available in 4.0.
We're currently working on exposing the
get_pre_v1_wallet_keychains()method in the bindings, and after adding a test for it I realized that the function did not quite behave as I was expecting it to.See attached db for an example of a wallet that was created using two descriptors, but where only the external keychain had revealed addresses (last revealed index is 7).
Running the
get_pre_v1_wallet_keychainsmethod with this db returns a vector ofPreV1WalletKeychainwith a single element, the external keychain.I've got this buddy Claude who's good at quickly figuring out software stuff and he tells me that the behavior here is because the query uses an INNER JOIN between
last_derivation_indicesandchecksums:A row only appears if the keychain exists in both tables. The last_derivation_indices table only gets a row for a keychain when at least one address has been derived from it. If the pre-v1 wallet was created with two descriptors but never derived any internal addresses, then the Internal keychain would have no row in last_derivation_indices, and the JOIN would only return External.
Solutions
This is fine if you know and understand that in cases where the user has not used their internal keychain the vector will not have it, but it feels not quite right either, since the migration workflow probably involves running the function and checking that the descriptors we're about to use indeed correspond to the ones used in the pre-v1 db (through the checksum field).
I think one fix would be to make the
last_derivation_indexfield anOption<u32>to allow forNoneto exist there when the keychain hasn't revealed any addresses. Unfortunately this would be breaking, so only available in 4.0.