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

com.google.bitcoin.core.FullPrunedBlockChain Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2012 Matt Corallo.
 *
 * 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 com.google.bitcoin.core;

import com.google.bitcoin.script.Script;
import com.google.bitcoin.store.BlockStoreException;
import com.google.bitcoin.store.FullPrunedBlockStore;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Nullable;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
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 larg 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 a regular Satoshi * client 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 BlockChain 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(java.io.File)} */ public FullPrunedBlockChain(NetworkParameters params, Wallet wallet, FullPrunedBlockStore blockStore) throws BlockStoreException { this(params, new ArrayList(), blockStore); if (wallet != null) addWallet(wallet); } /** * Constructs a BlockChain that has no wallet at all. This is helpful when you don't actually care about sending * and receiving coins but rather, just want to explore the network data structures. */ public FullPrunedBlockChain(NetworkParameters params, FullPrunedBlockStore blockStore) throws BlockStoreException { this(params, new ArrayList(), blockStore); } /** * Constructs a BlockChain connected to the given list of wallets and a store. */ public FullPrunedBlockChain(NetworkParameters params, List listeners, FullPrunedBlockStore blockStore) throws BlockStoreException { super(params, listeners, blockStore); this.blockStore = blockStore; // Ignore upgrading for now this.chainHead = blockStore.getVerifiedChainHead(); } @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 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()); /** A job submitted to the executor which verifies signatures. */ private static class Verifier implements Callable { final Transaction tx; final List