This commit refactors the code to make use of the btcnet package for
network-specific parameters instead of switching on the specific network.
For example, the percentage of the network that needs to run version 2
blocks is different between testnet and mainnet. Previously the code was
using a switch to choose these values. With this refactor, those
parameters are part of the network parameters provided when creating a new
chain instance.
Another example is checkpoints, which have been moved to btcnet so they
can be specified by the caller instead of hard coded into this package.
As a result, the checkpoints for the standard networks are now specified
in the btcnet package.
This makes it easier to add new networks such as a testnet4 should it
become needed. It also allows callers to define their own custom network
parameters without having to modify the code of the package to add new
switch cases for the custom network.
This commit corrects the debug log print to use the hash of referenced
coinbase transaction instead of the hash of the current transation when a
coinbase maturity is not met.
Rather than using the deprecated TxShas function on a btcutil.Block,
convert the checkBIP0030 to use the newer preferred method of ranging over
the Transactions to obtain the cached hash of each transaction.
This is also a little more efficient since it can avoid creating and
caching an extra slice to keep the hashes in addition to having the hash
cached with each transaction.
This commit makes a slight variant of the existing calcPastMedianTime
function available to external callers. The new exported version
calculates the past median time from the end of the current main chain
versus an arbitrary block node.
This commit makes a slight variant of the existing checkConnectBlock
function available to external callers. The new exported version checks
if the passed block will connect to the end of the current main chain.
In order to support this, a few other small modifications have been made
to the initial index generation and the existing checkConnectBlock since
it previously made some assumptions about the state of genesis block which
can no longer be assumed due accepting blocks from callers directly.
Also, add a quick test to ensure the new function fails when checking if
the genesis block will connect again when it's already inserted.
This commit exports a new variant of the existing internal
calcNextRequiredDifficulty function which calculates and returns the next
required difficulty for a block after the end of the current best chain
based on the difficulty retarget rules.
In order to support the exported function the internal one was slightly
modified to accept the block timestamp instead of an entire block since
the timestamp is all that is needed and the caller of the exported
function might next have a full block yet.
This commit modifies the BuildMerkleTreeStore function to accept a slice
of btcutil.Tx transactions as opposed to a full block. This allows more
flexibility when calculating merkle roots since a full block may not be
created yet (particularly when generating blocks that need to be solved in
mining).
Previously, the BuildMerkleTreeStore function accepted a btcutil.Block
because originally the block itself cached the transaction hashes and it
was necessary to have access to the block to make use of the cached
transactions. However, the code has since been improved such that it
caches transaction hashes directly in each btcutil.Tx. This means the
code can remain as efficient as before while allowing the individual
transacitons to be passed.
This commit adds an additional sanity check to ensure the block that is
being processed does not contain a timestamp with a precision higher than
one second. This is necessary because the consensus rules only deal with
whole seconds in the time comparisons whereas the internal data structures
make use of Go time.Time values which support up to nanosecond precision.
Also, add a test to ensure the new functionality works as expected.
ok @owainga
This commit moves the subsidy halving interval to the chain params so it
can be configured per network. With that change it sets the regression
test halving interval to 150 to match the regression test params of the
reference implementation.
This was pointed out by @flammit.
The name findLatestKnownCheckpoint is confusing and doesn't really convey
the fact the purpose of the function is to the find the checkpoint prior
to the current known block.
Therefore, rename the function to findPreviousCheckpoint for clarity.
Also, update some comments to follow suit.
This commit adds an additional check to the block acceptance rules which
prevents new blocks that fork the main chain before the previous known
good checkpoint. This prevents storage of new, otherwise valid, blocks
from building off of old blocks which are likely at a much easier
difficulty and therefore could be used to waste cache and disk space.
Note this is slightly different than the other existing check which
prevents blocks with a timestamp before the timestamp of the latest known
good checkpoint since that check effectively prevents old side chain
blocks that already existed (per the claimed timestamp).
ok drahn@
This commit resolves an issue where the block node index was forcing
entire blocks to be kept in memory thereby forcing excessive memory usage.
For example, prior to this change, the memory usage could consume upwards
of 1.5GB while importing bootstrap.dat via the addblock utility. With
this change the entire import takes <150MB. This also has the same memory
reduction to btcd since it uses the same code path.
Previously there was only a function to get the latest checkpoint. This
commit exposes a new function named Checkpoints which returns a slice of
checkpoints ordered by height for the active network or nil when
checkpoints are disabled.
The recent addition of the fast add path to support headers first was not
running the block node index pruning code which removes unneeded block
nodes from memory. This resulted in higher memory usage than needed in
fast add mode.
Previously the code was only adding a new block node as a child in the
inernal node index for the cases it extended the main chain or a side
chain and not for a node which caused a reorg. This resulted in the block
node pruning code not clearing the parent link of reorged nodes which
ultimately led to a sanity check error accordingly.
This commit resolves the issue by ensuring new block nodes are added as
children of their respective parents in all cases.
Closes#4.
This commit changes the node index creation to use block headers instead
of full blocks. This speeds up the initial node index generation since it
doesn't require loading a bunch of full blocks at startup.
This commit modifies local variables that are used for more convenient
access to a block's header to use pointers. This avoids copying the
header multiple times.
Previously the code performed a database query for every checkpoint (going
backwards) to find the latest known checkpoint on every block. This was
particularly noticabled near the beginning of the block chain when there
are still several checkpoints that haven't been reached yet.
This commit changes the logic to cache the latest known checkpoint while
keeping track of when it needs to be updated once a new later known
checkpoint has been reached.
While here, also add a log message when a checkpoint has been reached and
verified.
The previous script validation logic entailed starting up a hard-coded
number of goroutines to process the transaction scripts in parallel. In
particular, one goroutine (up to 8 max) was started per transaction in a
block and another one was started for each input script pair in the
each transaction. This resulted in 64 goroutines simultaneously running
scripts and verifying cryptographic signatures. This could easily lead to
the overall system feeling sluggish.
Further the previous design could also result in bursty behavior since the
number of inputs to a transaction as well as its complexity can vary
widely between transactions. For example, starting 2 goroutines (one to
process the transaction and one for actual script pair validation) to
verify a transaction with a single input was not desirable.
Finally, the previous design validated all transactions and inputs
regardless of a failure in one of the other scripts. This really didn't
have a big impact since it's quite rare that blocks with invalid
verifications are being processed, but it was a potential way DoS vector.
This commit changes the logic in a few ways to improve things:
- The max number of validation goroutines is now based on the number of
cores in the system
- All transaction inputs from all transactions in the block are collated
into a single list which is fed through the aforementioned validation
goroutines
- The validation CPU usage is much more consistent due to the collation of
inputs
- A validation error in any goroutine immediately stops validation of all
remaining inputs
- The errors have been improved to include context about what tx script
pair failed as opposed to showing the information as a warning
This closesconformal/btcd#59.
It is not necessary to do all of the transaction validation on
blocks if they have been confirmed to be in the block chain leading
up to the final checkpoint in a given blockschain.
This algorithm fetches block headers from the peer, then once it has
established the full blockchain connection, it requests blocks.
Any blocks before the final checkpoint pass true for fastAdd on
btcchain operation, which causes it to do less valiation on the block.
This commit modifies the tests to setup a chain instance backed by the new
memory database backend for btcdb. This allows the tests to avoid
creating and cleaning up files and also allows the tests to run faster
since it can all happen in memory.
The chainSetup function has also been changed to provide logic to switch
on the database type to allow for easy changing of the backend to a
different database type as needed. For example, it could be useful to
provide extra testing against new database backends.
Rather than defining CheckBlockSanity as a member of a BlockChain
instance, define it at the root level so it is truly context free as
intended. In order to make it context free, the proof of work limit is
now a required parameter.