bitcoin-s/website/versioned_docs/version-1.9.5/wallet/wallet-sync.md
2022-10-03 10:24:12 -05:00

4.1 KiB

title id original_id
Wallet Sync version-1.9.5-wallet-sync wallet-sync

High level wallet state

Our wallet infrastructure has a specific table called state_descriptors. This tracks chain state for our wallet. Here is an example of the contents of this table

sqlite> select * from state_descriptors; SyncHeight|0000000000000000000134aa9e949ea1d053042b8dfa59bdc73b0322a88f009e 665741

If you look carefully in the second column, you will see a string encoding indicating what the wallet state is. In this case, the last block hash seen by the wallet is

0000000000000000000134aa9e949ea1d053042b8dfa59bdc73b0322a88f009e

and height

665741

If you have access to a wallet, you can call

wallet.getSyncDescriptorOpt to get access to this information

Wallet state from the cli

Alternatively, you can retrieve this information with bitcoin-s-cli

 ./bitcoin-s-cli walletinfo
{
  "wallet": {
    "keymanager": {
      "rootXpub": "..."
    },
    "xpub": "...",
    "hdPath": "...",
    "height": 1906239,
    "blockHash": "00000000dcf1066b8cd764a6104a9b5e95a55cd31adf9107974b2581ac90fdb9"
  }
}

Syncing a wallet

Bitcoin-s provides a utility object called WalletSync that provides useful utilities for syncing a bitcoin-s wallet.

Syncing wallet for with access to full blocks

Inside of WalletSync we have a method called WalletSync.syncFullBlocks This method takes 4 parameters

  • a Wallet to sync
  • getBlockHeaderFunc is a function to retrieve a block header based on a blockHash
  • getBestBlockHashFunc is a function to retrieve the best block hash for our blockchain
  • getBlockFunc is a function to retrieve a full Block that corresponds to a block hash

Given these for things, we can use WalletSync.syncFullBlocks to sync our entire wallet.

Here is a code example

implicit val system: ActorSystem = ActorSystem(s"wallet-sync-example")
implicit val ec: ExecutionContext = system.dispatcher

// this reads authentication credentials and
// connection details from the default data
// directory on your platform
val client = BitcoindRpcClient.fromDatadir(binary=new File("/path/to/bitcoind"), datadir=new File("/path/to/bitcoind-datadir"))

//yay! Now we have a started bitcoind.
//We will use this as our datasource for syncing our wallet
val bitcoindRpcClientF: Future[BitcoindRpcClient] = client.start()


//wait for bitcoind to get started
val bitcoind = Await.result(bitcoindRpcClientF, 10.seconds)

val getBestBlockHashFunc = () => bitcoind.getBestBlockHash

val getBlockHeaderFunc = { hash: DoubleSha256DigestBE => bitcoind.getBlockHeaderRaw(hash) }

val getBlockFunc = {hash: DoubleSha256DigestBE => bitcoind.getBlockRaw(hash) }

val genesisHashBEF = bitcoind.getBlockHash(0)

//yay! We are now all setup. Using our 3 functions above and a wallet, we can now sync
//a fresh wallet
implicit val walletAppConfig = WalletAppConfig.fromDefaultDatadir()

val feeRateProvider: FeeRateApi = MempoolSpaceProvider.fromBlockTarget(6, proxyParams = None)
val wallet = Wallet(bitcoind, bitcoind, feeRateProvider)

//yay! we have a synced wallet
val syncedWalletF = genesisHashBEF.flatMap { genesisHash => 
  WalletSync.syncFullBlocks(wallet,
      getBlockHeaderFunc,
      getBestBlockHashFunc,
      getBlockFunc, 
      genesisHash)
}