/* * Copyright by the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.bitcoinj.tools; import org.bitcoinj.core.*; import org.bitcoinj.core.listeners.PeerConnectedEventListener; import org.bitcoinj.core.listeners.PeerDisconnectedEventListener; import org.bitcoinj.kits.WalletAppKit; import org.bitcoinj.params.MainNetParams; import org.bitcoinj.utils.BriefLogFormatter; import org.bitcoinj.wallet.SendRequest; import org.bitcoinj.wallet.Wallet; import java.io.File; /** * A program that sends a transaction with the specified fee and measures how long it takes to confirm. */ public class TestFeeLevel { private static final MainNetParams PARAMS = MainNetParams.get(); private static final int NUM_OUTPUTS = 2; private static WalletAppKit kit; public static void main(String[] args) throws Exception { BriefLogFormatter.initWithSilentBitcoinJ(); if (args.length == 0) { System.err.println("Specify the fee rate to test in satoshis/kB as the first argument."); return; } Coin feeRateToTest = Coin.valueOf(Long.parseLong(args[0])); System.out.println("Fee rate to test is " + feeRateToTest.toFriendlyString() + "/kB"); kit = new WalletAppKit(PARAMS, new File("."), "testfeelevel"); kit.startAsync(); kit.awaitRunning(); try { go(feeRateToTest, NUM_OUTPUTS); } finally { kit.stopAsync(); kit.awaitTerminated(); } } private static void go(Coin feeRateToTest, int numOutputs) throws InterruptedException, java.util.concurrent.ExecutionException, InsufficientMoneyException { System.out.println("Wallet has " + kit.wallet().getBalance().toFriendlyString() + "; current receive address is " + kit.wallet().currentReceiveAddress()); kit.peerGroup().setMaxConnections(25); if (kit.wallet().getBalance().compareTo(feeRateToTest) < 0) { System.out.println("Send some coins to receive address and wait for it to confirm ..."); kit.wallet().getBalanceFuture(feeRateToTest, Wallet.BalanceType.AVAILABLE).get(); } int heightAtStart = kit.chain().getBestChainHeight(); System.out.println("Height at start is " + heightAtStart); Coin value = kit.wallet().getBalance().divide(2); // Keep a chunk for the fee. Coin outputValue = value.divide(numOutputs); Transaction transaction = new Transaction(PARAMS); for (int i = 0; i < numOutputs - 1; i++) { transaction.addOutput(outputValue, kit.wallet().freshReceiveAddress()); value = value.subtract(outputValue); } transaction.addOutput(value, kit.wallet().freshReceiveAddress()); SendRequest request = SendRequest.forTx(transaction); request.feePerKb = feeRateToTest; request.ensureMinRequiredFee = false; kit.wallet().completeTx(request); System.out.println("Size in bytes is " + request.tx.unsafeBitcoinSerialize().length); System.out.println("TX is " + request.tx); System.out.println("Waiting for " + kit.peerGroup().getMaxConnections() + " connected peers"); kit.peerGroup().addDisconnectedEventListener(new PeerDisconnectedEventListener() { @Override public void onPeerDisconnected(Peer peer, int peerCount) { System.out.println(peerCount + " peers connected"); } }); kit.peerGroup().addConnectedEventListener(new PeerConnectedEventListener() { @Override public void onPeerConnected(Peer peer, int peerCount) { System.out.println(peerCount + " peers connected"); } }); kit.peerGroup().broadcastTransaction(request.tx).future().get(); System.out.println("Send complete, waiting for confirmation"); request.tx.getConfidence().getDepthFuture(1).get(); int heightNow = kit.chain().getBestChainHeight(); System.out.println("Height after confirmation is " + heightNow); System.out.println("Result: took " + (heightNow - heightAtStart) + " blocks to confirm at this fee level"); } }