All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bitcoinj.core.FullPrunedBlockChain Maven / Gradle / Ivy

There is a newer version: 0.15-cm06
Show newest version
/*
 * Copyright 2012 Matt Corallo.
 * Copyright 2014 Andreas Schildbach
 *
 * 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.core;

import org.bitcoinj.script.Script;
import org.bitcoinj.script.Script.VerifyFlag;
import org.bitcoinj.store.BlockStoreException;
import org.bitcoinj.store.FullPrunedBlockStore;
import org.bitcoinj.utils.*;
import org.bitcoinj.wallet.Wallet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Set;
import java.util.concurrent.*;

import static com.google.common.base.Preconditions.checkState;

/**
 * 

A FullPrunedBlockChain works in conjunction with a {@link FullPrunedBlockStore} to verify all the rules of the * Bitcoin system, with the downside being a large cost in system resources. Fully verifying means all unspent * transaction outputs are stored. Once a transaction output is spent and that spend is buried deep enough, the data * related to it is deleted to ensure disk space usage doesn't grow forever. For this reason a pruning node cannot * serve the full block chain to other clients, but it nevertheless provides the same security guarantees as Bitcoin * Core does.

*/ public class FullPrunedBlockChain extends AbstractBlockChain { private static final Logger log = LoggerFactory.getLogger(FullPrunedBlockChain.class); /** * Keeps a map of block hashes to StoredBlocks. */ protected final FullPrunedBlockStore blockStore; // Whether or not to execute scriptPubKeys before accepting a transaction (i.e. check signatures). private boolean runScripts = true; /** * Constructs a block chain connected to the given wallet and store. To obtain a {@link Wallet} you can construct * one from scratch, or you can deserialize a saved wallet from disk using * {@link Wallet#loadFromFile} */ public FullPrunedBlockChain(Context context, Wallet wallet, FullPrunedBlockStore blockStore) throws BlockStoreException { this(context, new ArrayList(), blockStore); addWallet(wallet); } /** * Constructs a block chain connected to the given wallet and store. To obtain a {@link Wallet} you can construct * one from scratch, or you can deserialize a saved wallet from disk using * {@link Wallet#loadFromFile} */ public FullPrunedBlockChain(NetworkParameters params, Wallet wallet, FullPrunedBlockStore blockStore) throws BlockStoreException { this(Context.getOrCreate(params), wallet, blockStore); } /** * Constructs a block chain connected to the given store. */ public FullPrunedBlockChain(Context context, FullPrunedBlockStore blockStore) throws BlockStoreException { this(context, new ArrayList(), blockStore); } /** * See {@link #FullPrunedBlockChain(Context, Wallet, FullPrunedBlockStore)} */ public FullPrunedBlockChain(NetworkParameters params, FullPrunedBlockStore blockStore) throws BlockStoreException { this(Context.getOrCreate(params), blockStore); } /** * Constructs a block chain connected to the given list of wallets and a store. */ public FullPrunedBlockChain(Context context, List listeners, FullPrunedBlockStore blockStore) throws BlockStoreException { super(context, listeners, blockStore); this.blockStore = blockStore; // Ignore upgrading for now this.chainHead = blockStore.getVerifiedChainHead(); } /** * See {@link #FullPrunedBlockChain(Context, List, FullPrunedBlockStore)} */ public FullPrunedBlockChain(NetworkParameters params, List listeners, FullPrunedBlockStore blockStore) throws BlockStoreException { this(Context.getOrCreate(params), listeners, blockStore); } @Override protected StoredBlock addToBlockStore(StoredBlock storedPrev, Block header, TransactionOutputChanges txOutChanges) throws BlockStoreException, VerificationException { StoredBlock newBlock = storedPrev.build(header); blockStore.put(newBlock, new StoredUndoableBlock(newBlock.getHeader().getHash(), txOutChanges)); return newBlock; } @Override protected StoredBlock addToBlockStore(StoredBlock storedPrev, Block block) throws BlockStoreException, VerificationException { StoredBlock newBlock = storedPrev.build(block); blockStore.put(newBlock, new StoredUndoableBlock(newBlock.getHeader().getHash(), block.transactions)); return newBlock; } @Override protected void rollbackBlockStore(int height) throws BlockStoreException { throw new BlockStoreException("Unsupported"); } @Override protected boolean shouldVerifyTransactions() { return true; } /** * Whether or not to run scripts whilst accepting blocks (i.e. checking signatures, for most transactions). * If you're accepting data from an untrusted node, such as one found via the P2P network, this should be set * to true (which is the default). If you're downloading a chain from a node you control, script execution * is redundant because you know the connected node won't relay bad data to you. In that case it's safe to set * this to false and obtain a significant speedup. */ public void setRunScripts(boolean value) { this.runScripts = value; } // TODO: Remove lots of duplicated code in the two connectTransactions // TODO: execute in order of largest transaction (by input count) first ExecutorService scriptVerificationExecutor = Executors.newFixedThreadPool( Runtime.getRuntime().availableProcessors(), new ContextPropagatingThreadFactory("Script verification")); /** * A job submitted to the executor which verifies signatures. */ private static class Verifier implements Callable { final Transaction tx; final List