[DEV-45] Update blockdag package tests for primitive blockDAG (#24)

* [DEV-45] Updated the BlockDB files to contain blocks that could be deserialized.

* [DEV-45] Fixed TestHaveBlock (finally)

* [DEV-45] Fixed TestLocateInventory and everything that's reliant on chainview_test::chainedNodes.

* [DEV-45] Fixed TestChainViewNil.

* [DEV-45] Fixed TestNotifications.

* [DEV-45] Fixed ExampleBlockChain_ProcessBlock.

* [DEV-45] Fixed TestCheckBlockScripts.

* [DEV-45] Fixed TestCheckConnectBlockTemplate.

* [DEV-45] Renamed the BlockDBs to their original names.

* [DEV-45] Skipping TestFullBlocks for until we have implemented Phantom.

* [DEV-45] Deleted a couple of methods that are no longer used. (They were previously used for reorganization)
This commit is contained in:
stasatdaglabs 2018-07-11 17:09:35 +03:00 committed by Svarog
parent c9c81e1a82
commit f4a0ec175d
25 changed files with 74 additions and 311 deletions

View File

@ -112,6 +112,16 @@ func (bs blockSet) hashesEqual(hashes []daghash.Hash) bool {
return true
}
// hashes returns the hashes of the blocks in this set.
func (bs blockSet) hashes() []daghash.Hash {
hashes := make([]daghash.Hash, 0, len(bs))
for hash := range bs {
hashes = append(hashes, hash)
}
return hashes
}
// first returns the first block in this set or nil if this set is empty.
func (bs blockSet) first() *blockNode {
for _, block := range bs {

View File

@ -483,8 +483,7 @@ func LockTimeToSequence(isSeconds bool, locktime uint32) uint32 {
locktime>>wire.SequenceLockTimeGranularity
}
// connectBlock handles connecting the passed node/block to the end of the main
// (best) chain.
// connectBlock handles connecting the passed node/block to the DAG.
//
// This passed utxo view must have all referenced txos the block spends marked
// as spent and all of the new txos the block creates added to it. In addition,
@ -495,13 +494,6 @@ func LockTimeToSequence(isSeconds bool, locktime uint32) uint32 {
//
// This function MUST be called with the chain state lock held (for writes).
func (b *BlockChain) connectBlock(node *blockNode, block *btcutil.Block, view *UtxoViewpoint, stxos []spentTxOut) error {
// Make sure it's extending the end of the best chain.
prevHash := block.MsgBlock().Header.SelectedPrevBlock()
if !prevHash.IsEqual(&b.bestChain.SelectedTip().hash) {
return AssertError("connectBlock must be called with a block " +
"that extends the main chain")
}
// Sanity check the correct number of stxos are provided.
if len(stxos) != countSpentOutputs(block) {
return AssertError("connectBlock called with inconsistent " +
@ -612,117 +604,6 @@ func (b *BlockChain) connectBlock(node *blockNode, block *btcutil.Block, view *U
return nil
}
// disconnectBlock handles disconnecting the passed node/block from the end of
// the main (best) chain.
//
// This function MUST be called with the chain state lock held (for writes).
func (b *BlockChain) disconnectBlock(node *blockNode, block *btcutil.Block, view *UtxoViewpoint) error {
// Make sure the node being disconnected is the end of the best chain.
if !node.hash.IsEqual(&b.bestChain.SelectedTip().hash) {
return AssertError("disconnectBlock must be called with the " +
"block at the end of the main chain")
}
// Load the previous block since some details for it are needed below.
prevNode := node.selectedParent
var prevBlock *btcutil.Block
err := b.db.View(func(dbTx database.Tx) error {
var err error
prevBlock, err = dbFetchBlockByNode(dbTx, prevNode)
return err
})
if err != nil {
return err
}
// Write any block status changes to DB before updating best state.
err = b.index.flushToDB()
if err != nil {
return err
}
// Generate a new best state snapshot that will be used to update the
// database and later memory if all database updates are successful.
b.stateLock.RLock()
curTotalTxns := b.stateSnapshot.TotalTxns
b.stateLock.RUnlock()
numTxns := uint64(len(prevBlock.MsgBlock().Transactions))
blockSize := uint64(prevBlock.MsgBlock().SerializeSize())
newTotalTxns := curTotalTxns - uint64(len(block.MsgBlock().Transactions))
state := newBestState(prevNode, blockSize, numTxns,
newTotalTxns, prevNode.CalcPastMedianTime())
err = b.db.Update(func(dbTx database.Tx) error {
// Update best block state.
err := dbPutBestState(dbTx, state, node.workSum)
if err != nil {
return err
}
// Remove the block hash and height from the block index which
// tracks the main chain.
err = dbRemoveBlockIndex(dbTx, block.Hash(), node.height)
if err != nil {
return err
}
// Update the utxo set using the state of the utxo view. This
// entails restoring all of the utxos spent and removing the new
// ones created by the block.
err = dbPutUtxoView(dbTx, view)
if err != nil {
return err
}
// Update the transaction spend journal by removing the record
// that contains all txos spent by the block .
err = dbRemoveSpendJournalEntry(dbTx, block.Hash())
if err != nil {
return err
}
// Allow the index manager to call each of the currently active
// optional indexes with the block being disconnected so they
// can update themselves accordingly.
if b.indexManager != nil {
err := b.indexManager.DisconnectBlock(dbTx, block, view)
if err != nil {
return err
}
}
return nil
})
if err != nil {
return err
}
// Prune fully spent entries and mark all entries in the view unmodified
// now that the modifications have been committed to the database.
view.commit()
// This node's parent is now the end of the best chain.
b.bestChain.SetTip(node.selectedParent)
// Update the state for the best block. Notice how this replaces the
// entire struct instead of updating the existing one. This effectively
// allows the old version to act as a snapshot which callers can use
// freely without needing to hold a lock for the duration. See the
// comments on the state variable for more details.
b.stateLock.Lock()
b.stateSnapshot = state
b.stateLock.Unlock()
// Notify the caller that the block was disconnected from the main
// chain. The caller would typically want to react with actions such as
// updating wallets.
b.chainLock.Unlock()
b.sendNotification(NTBlockDisconnected, block)
b.chainLock.Lock()
return nil
}
// countSpentOutputs returns the number of utxos the passed block spends.
func countSpentOutputs(block *btcutil.Block) int {
// Exclude the coinbase transaction since it can't spend anything.

View File

@ -17,12 +17,12 @@ import (
// TestHaveBlock tests the HaveBlock API to ensure proper functionality.
func TestHaveBlock(t *testing.T) {
// Load up blocks such that there is a side chain.
// Load up blocks such that there is a fork in the DAG.
// (genesis block) -> 1 -> 2 -> 3 -> 4
// \-> 3a
// \-> 3b
testFiles := []string{
"blk_0_to_4.dat.bz2",
"blk_3A.dat.bz2",
"blk_0_to_4.dat",
"blk_3B.dat",
}
var blocks []*btcutil.Block
@ -78,14 +78,14 @@ func TestHaveBlock(t *testing.T) {
hash string
want bool
}{
// Genesis block should be present (in the main chain).
// Genesis block should be present.
{hash: dagconfig.MainNetParams.GenesisHash.String(), want: true},
// Block 3a should be present (on a side chain).
{hash: "00000000474284d20067a4d33f6a02284e6ef70764a3a26d6a5b9df52ef663dd", want: true},
// Block 3b should be present (as a second child of Block 2).
{hash: "000000c7576990a9a73785181a36c0b346d0750c385345252c1cfa6951928c26", want: true},
// Block 100000 should be present (as an orphan).
{hash: "000000000003ba27aa200b1cecaad478d2b00432346c3f1f3986da1afd33e506", want: true},
{hash: "000000826ababf6b615336e6e1a5b479f4d2e580448cc090fc111b749a28654b", want: true},
// Random hashes should not be available.
{hash: "123", want: false},
@ -125,7 +125,7 @@ func TestCalcSequenceLock(t *testing.T) {
blockVersion := int32(0x20000000 | (uint32(1) << csvBit))
// Generate enough synthetic blocks to activate CSV.
chain := newFakeChain(netParams)
chain := newFakeDag(netParams)
node := chain.bestChain.SelectedTip()
blockTime := node.Header().Timestamp
numBlocksToActivate := (netParams.MinerConfirmationWindow * 3)
@ -464,21 +464,21 @@ func nodeHeaders(nodes []*blockNode, indexes ...int) []wire.BlockHeader {
// TestLocateInventory ensures that locating inventory via the LocateHeaders and
// LocateBlocks functions behaves as expected.
func TestLocateInventory(t *testing.T) {
// Construct a synthetic block chain with a block index consisting of
// Construct a synthetic block DAG with a block index consisting of
// the following structure.
// genesis -> 1 -> 2 -> ... -> 15 -> 16 -> 17 -> 18
// \-> 16a -> 17a
tip := tstTip
chain := newFakeChain(&dagconfig.MainNetParams)
branch0Nodes := chainedNodes(chain.bestChain.Genesis(), 18)
branch1Nodes := chainedNodes(branch0Nodes[14], 2)
dag := newFakeDag(&dagconfig.MainNetParams)
branch0Nodes := chainedNodes(setFromSlice(dag.bestChain.Genesis()), 18)
branch1Nodes := chainedNodes(setFromSlice(branch0Nodes[14]), 2)
for _, node := range branch0Nodes {
chain.index.AddNode(node)
dag.index.AddNode(node)
}
for _, node := range branch1Nodes {
chain.index.AddNode(node)
dag.index.AddNode(node)
}
chain.bestChain.SetTip(tip(branch0Nodes))
dag.bestChain.SetTip(tip(branch0Nodes))
// Create chain views for different branches of the overall chain to
// simulate a local and remote node on different parts of the chain.
@ -487,7 +487,7 @@ func TestLocateInventory(t *testing.T) {
// Create a chain view for a completely unrelated block chain to
// simulate a remote node on a totally different chain.
unrelatedBranchNodes := chainedNodes(nil, 5)
unrelatedBranchNodes := chainedNodes(newSet(), 5)
unrelatedView := newChainView(tip(unrelatedBranchNodes))
tests := []struct {
@ -772,12 +772,12 @@ func TestLocateInventory(t *testing.T) {
if test.maxAllowed != 0 {
// Need to use the unexported function to override the
// max allowed for headers.
chain.chainLock.RLock()
headers = chain.locateHeaders(test.locator,
dag.chainLock.RLock()
headers = dag.locateHeaders(test.locator,
&test.hashStop, test.maxAllowed)
chain.chainLock.RUnlock()
dag.chainLock.RUnlock()
} else {
headers = chain.LocateHeaders(test.locator,
headers = dag.LocateHeaders(test.locator,
&test.hashStop)
}
if !reflect.DeepEqual(headers, test.headers) {
@ -791,7 +791,7 @@ func TestLocateInventory(t *testing.T) {
if test.maxAllowed != 0 {
maxAllowed = test.maxAllowed
}
hashes := chain.LocateBlocks(test.locator, &test.hashStop,
hashes := dag.LocateBlocks(test.locator, &test.hashStop,
maxAllowed)
if !reflect.DeepEqual(hashes, test.hashes) {
t.Errorf("%s: unxpected hashes -- got %v, want %v",
@ -809,9 +809,9 @@ func TestHeightToHashRange(t *testing.T) {
// genesis -> 1 -> 2 -> ... -> 15 -> 16 -> 17 -> 18
// \-> 16a -> 17a -> 18a (unvalidated)
tip := tstTip
chain := newFakeChain(&dagconfig.MainNetParams)
branch0Nodes := chainedNodes(chain.bestChain.Genesis(), 18)
branch1Nodes := chainedNodes(branch0Nodes[14], 3)
chain := newFakeDag(&dagconfig.MainNetParams)
branch0Nodes := chainedNodes(setFromSlice(chain.bestChain.Genesis()), 18)
branch1Nodes := chainedNodes(setFromSlice(branch0Nodes[14]), 3)
for _, node := range branch0Nodes {
chain.index.SetStatusFlags(node, statusValid)
chain.index.AddNode(node)
@ -901,9 +901,9 @@ func TestIntervalBlockHashes(t *testing.T) {
// genesis -> 1 -> 2 -> ... -> 15 -> 16 -> 17 -> 18
// \-> 16a -> 17a -> 18a (unvalidated)
tip := tstTip
chain := newFakeChain(&dagconfig.MainNetParams)
branch0Nodes := chainedNodes(chain.bestChain.Genesis(), 18)
branch1Nodes := chainedNodes(branch0Nodes[14], 3)
chain := newFakeDag(&dagconfig.MainNetParams)
branch0Nodes := chainedNodes(setFromSlice(chain.bestChain.Genesis()), 18)
branch1Nodes := chainedNodes(setFromSlice(branch0Nodes[14]), 3)
for _, node := range branch0Nodes {
chain.index.SetStatusFlags(node, statusValid)
chain.index.AddNode(node)

View File

@ -100,6 +100,11 @@ func (c *chainView) Tips() blockSet {
c.mtx.Lock()
tip := c.tip()
c.mtx.Unlock()
if tip == nil { // TODO: (Stas) This is wrong. Modified only to satisfy compilation.
return newSet()
}
return setFromSlice(tip) // TODO: (Stas) This is wrong. Modified only to satisfy compilation.
}

View File

@ -10,7 +10,6 @@ import (
"reflect"
"testing"
"github.com/daglabs/btcd/dagconfig/daghash"
"github.com/daglabs/btcd/wire"
)
@ -21,18 +20,16 @@ var testNoncePrng = rand.New(rand.NewSource(0))
// chainedNodes returns the specified number of nodes constructed such that each
// subsequent node points to the previous one to create a chain. The first node
// will point to the passed parent which can be nil if desired.
func chainedNodes(parent *blockNode, numNodes int) []*blockNode {
func chainedNodes(parents blockSet, numNodes int) []*blockNode {
nodes := make([]*blockNode, numNodes)
tip := parent
tips := parents
for i := 0; i < numNodes; i++ {
// This is invalid, but all that is needed is enough to get the
// synthetic tests to work.
header := wire.BlockHeader{Nonce: testNoncePrng.Uint32()}
if tip != nil {
header.PrevBlocks = []daghash.Hash{tip.hash} // TODO: (Stas) This is wrong. Modified only to satisfy compilation.
}
nodes[i] = newBlockNode(&header, setFromSlice(tip)) // TODO: (Stas) This is wrong. Modified only to satisfy compilation.
tip = nodes[i]
header.PrevBlocks = tips.hashes()
nodes[i] = newBlockNode(&header, tips)
tips = setFromSlice(nodes[i])
}
return nodes
}
@ -79,8 +76,8 @@ func TestChainView(t *testing.T) {
// \-> 2a -> 3a -> 4a -> 5a -> 6a -> 7a -> ... -> 26a
// \-> 3a'-> 4a' -> 5a'
branch0Nodes := chainedNodes(nil, 5)
branch1Nodes := chainedNodes(branch0Nodes[1], 25)
branch2Nodes := chainedNodes(branch1Nodes[0], 3)
branch1Nodes := chainedNodes(setFromSlice(branch0Nodes[1]), 25)
branch2Nodes := chainedNodes(setFromSlice(branch1Nodes[0]), 3)
tip := tstTip
tests := []struct {
@ -343,8 +340,8 @@ func TestChainViewSetTip(t *testing.T) {
// structure.
// 0 -> 1 -> 2 -> 3 -> 4
// \-> 2a -> 3a -> 4a -> 5a -> 6a -> 7a -> ... -> 26a
branch0Nodes := chainedNodes(nil, 5)
branch1Nodes := chainedNodes(branch0Nodes[1], 25)
branch0Nodes := chainedNodes(newSet(), 5)
branch1Nodes := chainedNodes(setFromSlice(branch0Nodes[1]), 25)
tip := tstTip
tests := []struct {
@ -429,9 +426,9 @@ func TestChainViewNil(t *testing.T) {
genesis)
}
// Ensure the tip of an uninitialized view does not produce a node.
if tip := view.Tips(); tip != nil {
t.Fatalf("Tip: unexpected tip -- got %v, want nil", tip)
// Ensure the tips of an uninitialized view do not produce a node.
if tips := view.Tips(); len(tips) > 0 {
t.Fatalf("Tip: unexpected tips -- got %v, want nothing", tips)
}
// Ensure the height of an uninitialized view is the expected value.

View File

@ -343,14 +343,14 @@ func (b *BlockChain) TstSetCoinbaseMaturity(maturity uint16) {
b.chainParams.CoinbaseMaturity = maturity
}
// newFakeChain returns a chain that is usable for syntetic tests. It is
// newFakeDag returns a chain that is usable for syntetic tests. It is
// important to note that this chain has no database associated with it, so
// it is not usable with all functions and the tests must take care when making
// use of it.
func newFakeChain(params *dagconfig.Params) *BlockChain {
func newFakeDag(params *dagconfig.Params) *BlockChain {
// Create a genesis block node and block index index populated with it
// for use when creating the fake chain below.
node := newBlockNode(&params.GenesisBlock.Header, nil)
node := newBlockNode(&params.GenesisBlock.Header, newSet())
index := newBlockIndex(nil, params)
index.AddNode(node)

View File

@ -68,7 +68,7 @@ func ExampleBlockChain_ProcessBlock() {
fmt.Printf("Block accepted. Is it an orphan?: %v", isOrphan)
// Output:
// Failed to process block: already have block 000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f
// Failed to process block: already have block 000000094f48b026266f5b53d42ec33f453c48a31d036b785b743788e6bddc82
}
// This example demonstrates how to convert the compact "bits" in a block header

View File

@ -132,6 +132,10 @@ func chainSetup(dbName string, params *dagconfig.Params) (*blockdag.BlockChain,
// TestFullBlocks ensures all tests generated by the fullblocktests package
// have the expected result when processed via ProcessBlock.
func TestFullBlocks(t *testing.T) {
// TODO: (Stas) This test was disabled for until we have implemented Phantom
// Ticket: https://daglabs.atlassian.net/browse/DEV-60
t.SkipNow()
tests, err := fullblocktests.Generate(false)
if err != nil {
t.Fatalf("failed to generate tests: %v", err)

View File

@ -12,7 +12,7 @@ import (
// TestNotifications ensures that notification callbacks are fired on events.
func TestNotifications(t *testing.T) {
blocks, err := loadBlocks("blk_0_to_4.dat.bz2")
blocks, err := loadBlocks("blk_0_to_4.dat")
if err != nil {
t.Fatalf("Error loading file: %v\n", err)
}

View File

@ -18,7 +18,7 @@ func TestCheckBlockScripts(t *testing.T) {
runtime.GOMAXPROCS(runtime.NumCPU())
testBlockNum := 277647
blockDataFile := fmt.Sprintf("%d.dat.bz2", testBlockNum)
blockDataFile := fmt.Sprintf("%d.dat", testBlockNum)
blocks, err := loadBlocks(blockDataFile)
if err != nil {
t.Errorf("Error loading file: %v\n", err)
@ -33,7 +33,7 @@ func TestCheckBlockScripts(t *testing.T) {
return
}
storeDataFile := fmt.Sprintf("%d.utxostore.bz2", testBlockNum)
storeDataFile := fmt.Sprintf("%d.utxostore", testBlockNum)
view, err := loadUtxoView(storeDataFile)
if err != nil {
t.Errorf("Error loading txstore: %v\n", err)

BIN
blockdag/testdata/277647.dat vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
blockdag/testdata/277647.utxostore vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
blockdag/testdata/blk_0_to_4.dat vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
blockdag/testdata/blk_3A.dat vendored Normal file

Binary file not shown.

Binary file not shown.

BIN
blockdag/testdata/blk_3B.dat vendored Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -316,140 +316,6 @@ func (view *UtxoViewpoint) fetchEntryByHash(db database.DB, hash *daghash.Hash)
return entry, err
}
// disconnectTransactions updates the view by removing all of the transactions
// created by the passed block, restoring all utxos the transactions spent by
// using the provided spent txo information, and setting the best hash for the
// view to the block before the passed block.
func (view *UtxoViewpoint) disconnectTransactions(db database.DB, parents blockSet, block *btcutil.Block, stxos []spentTxOut) error {
// Sanity check the correct number of stxos are provided.
if len(stxos) != countSpentOutputs(block) {
return AssertError("disconnectTransactions called with bad " +
"spent transaction out information")
}
// Loop backwards through all transactions so everything is unspent in
// reverse order. This is necessary since transactions later in a block
// can spend from previous ones.
stxoIdx := len(stxos) - 1
transactions := block.Transactions()
for txIdx := len(transactions) - 1; txIdx > -1; txIdx-- {
tx := transactions[txIdx]
// All entries will need to potentially be marked as a coinbase.
var packedFlags txoFlags
isCoinBase := txIdx == 0
if isCoinBase {
packedFlags |= tfCoinBase
}
// Mark all of the spendable outputs originally created by the
// transaction as spent. It is instructive to note that while
// the outputs aren't actually being spent here, rather they no
// longer exist, since a pruned utxo set is used, there is no
// practical difference between a utxo that does not exist and
// one that has been spent.
//
// When the utxo does not already exist in the view, add an
// entry for it and then mark it spent. This is done because
// the code relies on its existence in the view in order to
// signal modifications have happened.
txHash := tx.Hash()
prevOut := wire.OutPoint{Hash: *txHash}
for txOutIdx, txOut := range tx.MsgTx().TxOut {
if txscript.IsUnspendable(txOut.PkScript) {
continue
}
prevOut.Index = uint32(txOutIdx)
entry := view.entries[prevOut]
if entry == nil {
entry = &UtxoEntry{
amount: txOut.Value,
pkScript: txOut.PkScript,
blockHeight: block.Height(),
packedFlags: packedFlags,
}
view.entries[prevOut] = entry
}
entry.Spend()
}
// Loop backwards through all of the transaction inputs (except
// for the coinbase which has no inputs) and unspend the
// referenced txos. This is necessary to match the order of the
// spent txout entries.
if isCoinBase {
continue
}
for txInIdx := len(tx.MsgTx().TxIn) - 1; txInIdx > -1; txInIdx-- {
// Ensure the spent txout index is decremented to stay
// in sync with the transaction input.
stxo := &stxos[stxoIdx]
stxoIdx--
// When there is not already an entry for the referenced
// output in the view, it means it was previously spent,
// so create a new utxo entry in order to resurrect it.
originOut := &tx.MsgTx().TxIn[txInIdx].PreviousOutPoint
entry := view.entries[*originOut]
if entry == nil {
entry = new(UtxoEntry)
view.entries[*originOut] = entry
}
// The legacy v1 spend journal format only stored the
// coinbase flag and height when the output was the last
// unspent output of the transaction. As a result, when
// the information is missing, search for it by scanning
// all possible outputs of the transaction since it must
// be in one of them.
//
// It should be noted that this is quite inefficient,
// but it realistically will almost never run since all
// new entries include the information for all outputs
// and thus the only way this will be hit is if a long
// enough reorg happens such that a block with the old
// spend data is being disconnected. The probability of
// that in practice is extremely low to begin with and
// becomes vanishingly small the more new blocks are
// connected. In the case of a fresh database that has
// only ever run with the new v2 format, this code path
// will never run.
if stxo.height == 0 {
utxo, err := view.fetchEntryByHash(db, txHash)
if err != nil {
return err
}
if utxo == nil {
return AssertError(fmt.Sprintf("unable "+
"to resurrect legacy stxo %v",
*originOut))
}
stxo.height = utxo.BlockHeight()
stxo.isCoinBase = utxo.IsCoinBase()
}
// Restore the utxo using the stxo data from the spend
// journal and mark it as modified.
entry.amount = stxo.amount
entry.pkScript = stxo.pkScript
entry.blockHeight = stxo.height
entry.packedFlags = tfModified
if stxo.isCoinBase {
entry.packedFlags |= tfCoinBase
}
}
}
// Update the tips for view to the block's parents since all of the
// transactions for the current block have been disconnected.
view.SetTips(parents)
return nil
}
// RemoveEntry removes the given transaction output from the current state of
// the view. It will have no effect if the passed output does not exist in the
// view.

View File

@ -1213,7 +1213,7 @@ func (b *BlockChain) CheckConnectBlockTemplate(block *btcutil.Block) error {
tips := b.bestChain.Tips()
header := block.MsgBlock().Header
prevHashes := header.PrevBlocks
if tips.hashesEqual(prevHashes) {
if !tips.hashesEqual(prevHashes) {
str := fmt.Sprintf("previous blocks must be the currents tips %v, "+
"instead got %v", tips, prevHashes)
return ruleError(ErrPrevBlockNotBest, str)

View File

@ -83,8 +83,8 @@ func TestCheckConnectBlockTemplate(t *testing.T) {
// (genesis block) -> 1 -> 2 -> 3 -> 4
// \-> 3a
testFiles := []string{
"blk_0_to_4.dat.bz2",
"blk_3A.dat.bz2",
"blk_0_to_4.dat",
"blk_3B.dat",
}
var blocks []*btcutil.Block

View File

@ -24,8 +24,8 @@ var (
bigOne = big.NewInt(1)
// mainPowLimit is the highest proof of work value a Bitcoin block can
// have for the main network. It is the value 2^224 - 1.
mainPowLimit = new(big.Int).Sub(new(big.Int).Lsh(bigOne, 224), bigOne)
// have for the main network. It is the value 2^232 - 1.
mainPowLimit = new(big.Int).Sub(new(big.Int).Lsh(bigOne, 232), bigOne)
// regressionPowLimit is the highest proof of work value a Bitcoin block
// can have for the regression test network. It is the value 2^255 - 1.
@ -33,8 +33,8 @@ var (
// testNet3PowLimit is the highest proof of work value a Bitcoin block
// can have for the test network (version 3). It is the value
// 2^224 - 1.
testNet3PowLimit = new(big.Int).Sub(new(big.Int).Lsh(bigOne, 224), bigOne)
// 2^232 - 1.
testNet3PowLimit = new(big.Int).Sub(new(big.Int).Lsh(bigOne, 232), bigOne)
// simNetPowLimit is the highest proof of work value a Bitcoin block
// can have for the simulation test network. It is the value 2^255 - 1.