Ich schreibe meine allererste Anwendung mit bitcoinJ api und bin etwas hängen geblieben. Vielleicht kann mir jemand sagen, was mir fehlt.
Meine Übungs-App will einen Mustervertrag in der Bitcoin-Blockchain schreiben, aber es kommt mir so vor, als versuche ich es. Ich bekomme eine Nachricht von bitcoinJ, die besagt:
java.lang.IllegalStateException: Kann nicht aufgerufen werden, bis der Start abgeschlossen ist
Ich denke, ich muss irgendwie warten, bis die Blockchain synchronisiert ist, damit ich Sachen an sie senden kann, richtig?
So sieht mein Java-Code aus:
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);
}
}
});
}
}
Ich glaube, ich habe die Lösung für meine eigene Frage gefunden, nachdem ich mich ein wenig umgesehen habe.
Ich habe den Konstruktor geändert, um die Peer-Adressen explizit festzulegen, wie folgt:
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));
}
Eine andere Sache, die ich getan habe, war, 2 Methoden auf dem WalletAppKit aufzurufen, um die Synchronisierung zu starten:
walletAppKit.startAsync();
walletAppKit.awaitRunning();