Obtener saldo/descargar blockchain con bitcoinj

Estoy jugando con bitoinj y parece que ni siquiera puedo ejecutar la funcionalidad más básica.

Lo que quiero hacer: tengo una billetera con una dirección. Quiero descargar blockchain y, a partir de ahí, obtener el saldo de la billetera.

Lo que hice fue seguir el código (en scala, pero es más o menos lo mismo que en Java), la billetera está en address.walet, quiero que el bloqueo se guarde en saved.blockchain:

val params = NetworkParameters.prodNet
val walletFile = new java.io.File("address.wallet");
val wallet = Wallet.loadFromFile(walletFile)

val key = wallet.keychain.get(0)
val address:String = key.toAddress(params).toString
println("ADDRESS IS : "+address)

val blockStore = new BoundedOverheadBlockStore(params, new java.io.File("saved.blockchain"))
val chain = new BlockChain(params, wallet, blockStore)
val peerGroup = new PeerGroup(params, chain)
peerGroup.setUserAgent("BitToy", "0.1")

peerGroup.addPeerDiscovery(new DnsDiscovery(params))
peerGroup.addWallet(wallet)
println("START DOWNLOADING BLOCKCHAIN")

peerGroup.start()
peerGroup.downloadBlockChain()
peerGroup.stop()
println("DONE; BALANCE IS :")
println(wallet.getBalance)

Tengo saldo en la dirección en la billetera.

Ahora, cuando lo ejecuto por primera vez, la cadena de bloques (o, mejor dicho, los encabezados) se descarga y veo el saldo correcto. Sin embargo , cuando lo ejecuto por segunda vez, solo veo:

ADDRESS IS : [correct address here]
Aug 19, 2012 8:06:00 AM com.google.bitcoin.store.BoundedOverheadBlockStore load
INFO: Reading block store from saved.blockchain
Aug 19, 2012 8:06:00 AM com.google.bitcoin.store.BoundedOverheadBlockStore load
INFO: Read chain head from disk: 00000000000001b10c347b5ec05f9a1910d541905c5cd8827784a5c3e0695c95
Aug 19, 2012 8:06:00 AM com.google.bitcoin.core.BlockChain <init>
INFO: chain head is at height 194575:
v1 block: 
   previous block: 00000000000005ac50dc06021362cd4c284fafd4a1bdb7bad2849c978a875bb1
   merkle root: 158aedd0bc3386c7686f85ab933fd9e3ecb38e348b121ed0e61e2e776eda04a1
   time: [1345356028] Sun Aug 19 08:00:28 CEST 2012
   difficulty target (nBits): 436709470
   nonce: 4238997601

START DOWNLOADING BLOCKCHAIN
Aug 19, 2012 8:06:31 AM com.google.bitcoin.discovery.DnsDiscovery getPeers
INFO: DNS lookup for dnsseed.bitcoin.dashjr.org failed.
Aug 19, 2012 8:06:36 AM com.google.bitcoin.core.TCPNetworkConnection$NetworkHandler channelConnected
INFO: Announcing ourselves as: /BitCoinJ:0.6-SNAPSHOT/BitMessage:0.1/
Aug 19, 2012 8:06:41 AM com.google.bitcoin.core.Peer$PeerHandler exceptionCaught
INFO: com.google.bitcoin.core.Peer$PeerHandler@193f6e2 - No route to host
Aug 19, 2012 8:06:46 AM com.google.bitcoin.core.Peer$PeerHandler exceptionCaught
INFO: com.google.bitcoin.core.Peer$PeerHandler@61736e - No route to host
Aug 19, 2012 8:06:52 AM com.google.bitcoin.core.TCPNetworkConnection$NetworkHandler channelConnected
INFO: Announcing ourselves as: /BitCoinJ:0.6-SNAPSHOT/BitMessage:0.1/
Aug 19, 2012 8:06:52 AM com.google.bitcoin.core.PeerGroup handleNewPeer
INFO: Peer(seed.bitcoin.sipa.be/50.130.4.89:8333): New peer
Aug 19, 2012 8:06:52 AM com.google.bitcoin.core.PeerGroup handleNewPeer
INFO:   starting block chain download
Aug 19, 2012 8:06:52 AM com.google.bitcoin.core.PeerGroup setDownloadPeer
INFO: Setting download peer: Peer(seed.bitcoin.sipa.be/50.130.4.89:8333)
Downloading block chain of size 0. 
Done downloading block chain
Aug 19, 2012 8:06:52 AM com.google.bitcoin.core.Peer blockChainDownload
INFO: Peer(seed.bitcoin.sipa.be/50.130.4.89:8333): blockChainDownload(0000000000000000000000000000000000000000000000000000000000000000) current head = 00000000000001b10c347b5ec05f9a1910d541905c5cd8827784a5c3e0695c95
DONE; BALANCE IS :
0
Aug 19, 2012 8:06:52 AM com.google.bitcoin.core.PeerGroup$PeerGroupThread run
INFO: shutdown start

y el saldo es cero. Si elimino la cadena de bloques guardada y dejo que se vuelva a descargar, vuelve a funcionar, pero solo por una vez.

¿Qué estoy haciendo mal?

Respuestas (3)

Bien, ahora lo entiendo.

No puedo.

Bitcoinj guarda solo los encabezados. Y, lo que no sabía, no se puede obtener el equilibrio solo con encabezados.

Para obtener más información, puede ver la descripción exacta de lo que está en los encabezados aquí https://en.bitcoin.it/wiki/Block_hashing_algorithm

Sin embargo, lo que puedo hacer es guardar la billetera inmediatamente después. que haré.


"respuesta" anterior/pensar en voz alta:

Estoy hurgando en el código fuente.

Parece que la parte importante es cuándo sendTransactionsToWalletse llama BlockChain.java, pero solo se llama durante connectBlocky nada más.

connectBlockse llama sólo durante add. Y los únicos addbloques ed son los nuevos bloques de la red, no los de BlockStore.

Pero miraré el código un poco más.


No estoy seguro de lo terrible que sucedería si reescribiera el constructor de BlockChain.javafrom:

/**
 * Constructs a BlockChain connected to the given list of wallets and a store.
 */
public BlockChain(NetworkParameters params, List<Wallet> wallets,
                  BlockStore blockStore) throws BlockStoreException {
    this.blockStore = blockStore;
    chainHead = blockStore.getChainHead();
    log.info("chain head is at height {}:\n{}", chainHead.getHeight(), chainHead.getHeader());
    this.params = params;
    this.wallets = new ArrayList<Wallet>(wallets);
}

a (escribiendo desde mi cabeza, getters/setters pueden no ser correctos, etc.)

/**
 * Constructs a BlockChain connected to the given list of wallets and a store.
 */
public BlockChain(NetworkParameters params, List<Wallet> wallets,
                  BlockStore blockStore) throws BlockStoreException {
    this.blockStore = blockStore;
    chainHead = blockStore.getChainHead();
    log.info("chain head is at height {}:\n{}", chainHead.getHeight(), chainHead.getHeader());
    this.params = params;
    this.wallets = new ArrayList<Wallet>(wallets);
    StoredBlock sBlock = blockStore.getChainHead();
    Sha256Hash prevHash = sBlock.header.prevBlockHash();
    while (prevHash!=Sha256Hash.ZERO_HASH) {
        for (Wallet wallet:wallets){
            sendTransactionsToWallet(sBlock, NewBlockType.SIDE_CHAIN, wallet, sBlock.transactions); 
        }
        sBlock = blockStore.get(hash);
        prevHash = sBlock.header.prevBlockHash();
    }
}

pero de nuevo, no quiero reinventar la rueda ni nada.

Es posible hacer lo que quiera simplemente usando la clase PostgresFullPrunedBlockStore para el almacenamiento y luego solo tendrá que llamar Address.calculateBalanceForAddress()para obtener el saldo de la dirección deseada.

Desafortunadamente, es una pregunta un poco antigua y ya no estoy experimentando con bitcoinj, así que no puedo aceptarte, pero dejaré que la comunidad decida votando, supongo.
No se preocupe, solo sentí que respondí porque recientemente hubo actualizaciones con bitcoinj y pensé que otros podrían querer saber esto.
¿Qué tan grande será la base de datos postgress? Más de 100 GB y creciendo rápidamente, ¿verdad?
Je, la respuesta sigue ahí, incluso en 2017... No tengo idea de cómo se ve bitcoinj ahora.

Pensé en mencionar que (principalmente para ahorrar ancho de banda) he agregado una opción de almacenamiento en caché simple en MultiBit donde simplemente guarda los bloques recibidos en un directorio, cada bloque se llama [hash of block].block

Puede usar esto para tomar las transacciones, etc. como desee más tarde. ¡Claro que ocupa espacio! Está en la rama MultiBit v0.5. La principal clase de control es CacheManager. Podría ser útil para usted.

El trabajo de filtro de floración que Matt Corrallo está haciendo para filtrar el tx en el lado del servidor es, en mi humilde opinión, la forma correcta de administrar el tamaño de la cadena de bloques; esto es solo una brecha hasta que entra en bitcoinj.