horizontalsystems / BitcoinCore.Swift

Comprehensive Bitcoin development library for iOS, implemented on Swift.
MIT License
24 stars 22 forks source link

Add support of Watch only account #16

Closed ArtemZinkov closed 1 year ago

ArtemZinkov commented 1 year ago

As of now - .bip32 mentioned in BitcoinKit readme for watch only accounts - is skipped in build phase of bitcoinCore. It is not clear - should it be .bip32, which is not handled (as shown on screenshot), or it is not necessary, thus making readme file for bitcoinKit - outdated.

Screenshot 2023-08-07 at 13 10 04
ArtemZinkov commented 1 year ago

Tested on this piece of code. For zprv (bip84) - it's downloading transactions, but not recognising old transactions (history for such wallet is empty) For xprv (bip32) - it doesn't download transactions at all.

image
ArtemZinkov commented 1 year ago

Same seedData used to initialise bitcoinKit works as expected

image
ArtemZinkov commented 1 year ago

All tested on .testNet .newWallet

esen commented 1 year ago

hey @ArtemZinkov ,

.newWallet is considered to sync transactions only after the last checkpoint block. It assumes that the wallet is new and it has no transactions. You can check with ".api" or ".full" to sync historical transactions.

full // Sync from bip44Checkpoint. Api restore disabled api // Sync from lastCheckpoint. Api restore enabled newWallet // Sync from lastCheckpoint. Api restore enabled

lastCheckpoint is the last block of the last difficulty adjustment and it's updated before each release of the app.

esen commented 1 year ago

Tested on this piece of code. For zprv (bip84) - it's downloading transactions, but not recognising old transactions (history for such wallet is empty) For xprv (bip32) - it doesn't download transactions at all.

image

As of watch accounts, we only support account derivations which have "m/purpose'/coin_type'/account'" derivations. You can get an account Public extended key as following:

let keychain = HDKeychain(privateKey: rootKey) // rootKey is an instance of HDPrivateKey
let publicKey = try! keychain.derivedKey(path: "m/84'/0'/0'").publicKey()
let extendedKey = HDExtendedKey.public(key: publicKey)

bip32 derivations are the generic name of all HD wallets and it may be custom for each type of wallets.

ArtemZinkov commented 1 year ago

Hello @esen thank you for answering!

I tried to generate pubKey the way you mentioned, but for some reason - old transactions was still not recognised as "ours"

Screenshot 2023-08-08 at 15 10 13

BUT if i init wallet with Seed - it fetches and see transactions properly

Screenshot 2023-08-08 at 15 11 53

For more context - i still use .newWallet, due to it's testNet, transactions in it is quite recent and they're shown in history, for seed initialisation. I clear Tx (BitcoinKit.Kit.clear()) every time when i change init version (with seed, or derived pubKey), to replicate initial launch.

Sorry if i missing some important detail, please ask if more context is required here

ArtemZinkov commented 1 year ago

Hello @esen i would really appreciate any help or suggestion here, due to i faced road block here and not sure where to move forward, to enable watch only mode for wallets.

i also checked syncMode == .full, and still had no history for watch only mode, while bitcoinKit with seedData initialiser was capable to see old transactions for wallet i used

ArtemZinkov commented 1 year ago

UPDATE:

Found what was the issue! Derived path ("m/84'/0'/0'") you provided - consists of: Purpose - 84 coinType - 0 (bitcoin) chain - 0

I was testing this all on testNet, thus coinType should be 1 as mentioned here

i changed derivation path from "m/84'/0'/0'" to "m/84'/1'/0'" and it worked! Thanks!!

ArtemZinkov commented 1 year ago

I would suggest to add this as a check to compare with networkType, during initialisation of bitcoinKit