How to synchronize with the bitcoin blockchain via bitcoinJ I'am writing my very first application using bitcoinJ api and I got a bit stuck. Maybe somebody can tell me what I am missing.

My practice app wants to write a sample contract in the bitcoin blockchain, but it seems like, when I try to do so. I get a message from bitcoinJ that says:


  java.lang.IllegalStateException: Cannot call until startup is complete


I think I need somehow to wait for the blockchain to synchronize, so I can send stuff to it right?

This is how my java code looks like:

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&lt;Sha256Hash&gt; hashes = new ArrayList&lt;&gt;();
                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) -&gt; {
            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);
                }
            }
        });
    }
}
So I think I found the solution to my own question after looking around a bit.

I modified the constructor to explicitly set the peer addresses, like this:

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


Another thing I did was to call 2 methods on the WalletAppKit to start the synchronisation:

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