Cómo sincronizar con la cadena de bloques de bitcoin a través de bitcoinJ

Estoy escribiendo mi primera aplicación usando bitcoinJ api y me quedé un poco atascado. Tal vez alguien pueda decirme lo que me estoy perdiendo.

Mi aplicación de práctica quiere escribir un contrato de muestra en la cadena de bloques de bitcoin, pero parece que cuando trato de hacerlo. Recibo un mensaje de bitcoinJ que dice:

java.lang.IllegalStateException: no se puede llamar hasta que se complete el inicio

Creo que de alguna manera necesito esperar a que la cadena de bloques se sincronice, para poder enviarle cosas, ¿no?

Así es como se ve mi código java:

import org.bitcoinj.core.*;
import org.bitcoinj.kits.WalletAppKit;
import org.bitcoinj.params.RegTestParams;
import org.bitcoinj.script.ScriptBuilder;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class SimpleExample {

    private WalletAppKit bitcoin;
    public  NetworkParameters params = RegTestParams.get();

    public SimpleExample() {
        bitcoin = new WalletAppKit(params, new File("."), "testfile" + "-" + params.getPaymentProtocolId()) {
            @Override
            protected void onSetupCompleted() {
                // Don't make the user wait for confirmations for now, as the intention is they're sending it
                // their own money!
                bitcoin.wallet().allowSpendingUnconfirmedTransactions();
            }

        };
    }

    public void timestamp(File doc) throws IOException, InsufficientMoneyException {
        // Hash it
        Sha256Hash hash = Sha256Hash.of(doc);

        // Create a tx with an OP_RETURN output
        Transaction tx = new Transaction(params);
        tx.addOutput(Coin.ZERO, ScriptBuilder.createOpReturnScript(hash.getBytes()));

        //Check if the Blockchain is synchronized before you do anything!!!!!!

        // Send it to the Bitcoin network
        bitcoin.wallet().sendCoins(Wallet.SendRequest.forTx(tx));

        // Transaction proof
        Proof proof = new Proof();
        proof.setTx(tx.bitcoinSerialize());
        proof.setFilename(doc.getName());

        // Grab the merkle branch when it appears in the block chain
        bitcoin.peerGroup().addEventListener(new AbstractPeerEventListener() {
            @Override
            public void onBlocksDownloaded(Peer peer, Block block, FilteredBlock filteredBlock, int blocksLeft) {
                List<Sha256Hash> hashes = new ArrayList<>();
                PartialMerkleTree tree = filteredBlock.getPartialMerkleTree();
                tree.getTxnHashAndMerkleRoot(hashes);
                if (hashes.contains(tx.getHash())) {
                    proof.setPartialMerkleTree(tree.bitcoinSerialize());
                    proof.setBlockHash(filteredBlock.getHash());
                }
            }
        });

        // Wait for confirmations (3)
        tx.getConfidence().addEventListener((confidence, reason) -> {
            if (confidence.getConfidenceType() != TransactionConfidence.ConfidenceType.BUILDING)
                return;
            proof.depth.set(confidence.getDepthInBlocks());
            if (proof.depth.get() == 3) {
                // Save the proof to disk
                String filename = doc.toString() + ".timestamp";
                try {
                    proof.saveTo(filename);
                    System.out.println("Proof complete - Saved to " + filename);
                } catch (IOException e) {
                    System.err.println(e);
                }
            }
        });
    }
}

Respuestas (1)

Así que creo que encontré la solución a mi propia pregunta después de mirar un poco.

Modifiqué el constructor para establecer explícitamente las direcciones de los pares, así:

public SimpleExample() throws UnknownHostException {

        walletAppKit = new WalletAppKit(NETWORK_PARAMETERS,DIRECTORY, "test");
        walletAppKit
                .setAutoSave(true)
                .setBlockingStartup(false)
                .setPeerNodes(//Seed nodes for the test network
//                        new PeerAddress(InetAddress.getByName("seed.bitcoin.sipa.be"), 18333),
                        new PeerAddress(InetAddress.getByName("testnet-seed.bitcoin.petertodd.org"), 18333),
                        new PeerAddress(InetAddress.getByName("node3.mycelium.com"), 18333),
                        new PeerAddress(InetAddress.getLocalHost(), 18333));
    }

Otra cosa que hice fue llamar a 2 métodos en WalletAppKit para iniciar la sincronización:

walletAppKit.startAsync();
walletAppKit.awaitRunning();