bitcoin-s/docs/wallet/wallet-sync.md
2021-07-01 06:34:10 -05:00

4.8 KiB

title id
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

import akka.actor.ActorSystem

import scala.concurrent._

import java.io._

import org.bitcoins.core.api.feeprovider._
import org.bitcoins.rpc.client.common._

import org.bitcoins.crypto._

import org.bitcoins.feeprovider._

import org.bitcoins.keymanager.config._
import org.bitcoins.keymanager.bip39._

import org.bitcoins.wallet._
import org.bitcoins.wallet.config._
import org.bitcoins.wallet.sync._

import scala.concurrent.duration._


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) }

//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()
implicit val kmAppConfig = KeyManagerAppConfig.fromDefaultDatadir()
val keyManager: BIP39KeyManager = {
  BIP39KeyManager.fromParams(walletAppConfig.kmParams,None,None).right.get
}
val feeRateProvider: FeeRateApi = MempoolSpaceProvider.fromBlockTarget(6)
val wallet = Wallet(keyManager, bitcoind, bitcoind, feeRateProvider, keyManager.creationTime)

//yay! we have a synced wallet
val syncedWalletF = WalletSync.syncFullBlocks(wallet,
                                                  getBlockHeaderFunc,
                                                  getBestBlockHashFunc,
                                                  getBlockFunc)