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?
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 sendTransactionsToWallet
se llama BlockChain.java
, pero solo se llama durante connectBlock
y nada más.
connectBlock
se llama sólo durante add
. Y los únicos add
bloques 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.java
from:
/**
* 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.
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.
Karel Bilek
Bitfácil.com
Pavel Niedoba
Karel Bilek