Я пишу свое самое первое приложение, используя биткойн J API, и я немного застрял. Может быть, кто-нибудь может сказать мне, что мне не хватает.
Мое практическое приложение хочет написать образец контракта в блокчейне биткойнов, но, похоже, когда я пытаюсь это сделать. Я получаю сообщение от bitcoinJ, в котором говорится:
java.lang.IllegalStateException: невозможно вызвать до завершения запуска
Я думаю, мне нужно как-то дождаться синхронизации блокчейна, чтобы я мог отправлять туда что-то, верно?
Вот как выглядит мой 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);
}
}
});
}
}
Итак, я думаю, что нашел решение своего вопроса, немного осмотревшись.
Я изменил конструктор, чтобы явно установить адреса одноранговых узлов, например:
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));
}
Еще одна вещь, которую я сделал, это вызвать 2 метода в WalletAppKit, чтобы начать синхронизацию:
walletAppKit.startAsync();
walletAppKit.awaitRunning();