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()) {
            protected void onSetupCompleted() {
                // Don't make the user wait for confirmations for now, as the intention is they're sending it
                // their own money!


    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

        // Transaction proof
        Proof proof = new Proof();

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

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

1 Answer 1


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");
                .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:


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.