The moves the blockchain package from the blockchain module to an internal package of the root module meaning that it is no longer a part of the exported blockchain module. Nearly all of the logic it provides is really for the internal implementation of dcrd itself and thus having it exported module significantly increases the maintenance burden. Note that as of this change the blockchain module still exists and provides the chaingen and fullblocktests packages both or which are useful and used by external consumers. This is part of a continuing overall effort to reduce the total number of exported packages and modules and eventually get to the point it will be possible to follow semver for the root module. Overview of the major changes: - Move all go files from blockchain -> internal/blockchain - Move testdata from blockchain -> internal/blockchain - Remove doc.go in favor of the README.md since godoc now displays it - Move README.md from blockchain -> internal/blockchain and update to match the new reality - Add a new README.md in the exported blockchain module that documents it contains the remaining exported packages - Update all import paths in the repository accordingly - Run go mod tidy on all modules
103 lines
3.7 KiB
Go
103 lines
3.7 KiB
Go
// Copyright (c) 2014-2016 The btcsuite developers
|
|
// Copyright (c) 2015-2022 The Decred developers
|
|
// Use of this source code is governed by an ISC
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package blockchain_test
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"github.com/decred/dcrd/chaincfg/v3"
|
|
"github.com/decred/dcrd/database/v3"
|
|
_ "github.com/decred/dcrd/database/v3/ffldb"
|
|
"github.com/decred/dcrd/dcrutil/v4"
|
|
"github.com/decred/dcrd/internal/blockchain"
|
|
"github.com/syndtr/goleveldb/leveldb"
|
|
"github.com/syndtr/goleveldb/leveldb/filter"
|
|
"github.com/syndtr/goleveldb/leveldb/opt"
|
|
)
|
|
|
|
// This example demonstrates how to create a new chain instance and use
|
|
// ProcessBlock to attempt to add a block to the chain. As the package
|
|
// overview documentation describes, this includes all of the Decred consensus
|
|
// rules. This example intentionally attempts to insert a duplicate genesis
|
|
// block to illustrate how an invalid block is handled.
|
|
func ExampleBlockChain_ProcessBlock() {
|
|
// Create a new database to store the accepted blocks into. Typically
|
|
// this would be opening an existing database and would not be deleting
|
|
// and creating a new database like this, but it is done here so this is
|
|
// a complete working example and does not leave temporary files laying
|
|
// around.
|
|
mainNetParams := chaincfg.MainNetParams()
|
|
dbPath := filepath.Join(os.TempDir(), "exampleprocessblock")
|
|
_ = os.RemoveAll(dbPath)
|
|
db, err := database.Create("ffldb", dbPath, mainNetParams.Net)
|
|
if err != nil {
|
|
fmt.Printf("Failed to create database: %v\n", err)
|
|
return
|
|
}
|
|
defer os.RemoveAll(dbPath)
|
|
defer db.Close()
|
|
|
|
// Additionally, create a new database to store the UTXO set.
|
|
utxoDbPath := filepath.Join(os.TempDir(), "exampleprocessblockutxodb")
|
|
_ = os.RemoveAll(utxoDbPath)
|
|
opts := opt.Options{
|
|
Strict: opt.DefaultStrict,
|
|
Compression: opt.NoCompression,
|
|
Filter: filter.NewBloomFilter(10),
|
|
}
|
|
utxoDb, err := leveldb.OpenFile(utxoDbPath, &opts)
|
|
if err != nil {
|
|
fmt.Printf("Failed to create UTXO database: %v\n", err)
|
|
return
|
|
}
|
|
defer os.RemoveAll(utxoDbPath)
|
|
defer utxoDb.Close()
|
|
|
|
// Create a new BlockChain instance using the underlying database for
|
|
// the main bitcoin network. This example does not demonstrate some
|
|
// of the other available configuration options such as specifying a
|
|
// notification callback and signature cache. Also, the caller would
|
|
// ordinarily keep a reference to the median time source and add time
|
|
// values obtained from other peers on the network so the local time is
|
|
// adjusted to be in agreement with other peers.
|
|
chain, err := blockchain.New(context.Background(),
|
|
&blockchain.Config{
|
|
DB: db,
|
|
ChainParams: mainNetParams,
|
|
TimeSource: blockchain.NewMedianTime(),
|
|
UtxoCache: blockchain.NewUtxoCache(&blockchain.UtxoCacheConfig{
|
|
Backend: blockchain.NewLevelDbUtxoBackend(utxoDb),
|
|
FlushBlockDB: func() error {
|
|
return nil
|
|
},
|
|
MaxSize: 100 * 1024 * 1024, // 100 MiB
|
|
}),
|
|
})
|
|
if err != nil {
|
|
fmt.Printf("Failed to create chain instance: %v\n", err)
|
|
return
|
|
}
|
|
|
|
// Process a block. For this example, intentionally cause an error by
|
|
// trying to process the genesis block which already exists.
|
|
genesisBlock := dcrutil.NewBlock(mainNetParams.GenesisBlock)
|
|
forkLen, err := chain.ProcessBlock(genesisBlock)
|
|
if err != nil {
|
|
fmt.Printf("Failed to create chain instance: %v\n", err)
|
|
return
|
|
}
|
|
isMainChain := forkLen == 0
|
|
fmt.Printf("Block accepted. Is it on the main chain?: %v", isMainChain)
|
|
|
|
// This output is dependent on the genesis block, and needs to be
|
|
// updated if the mainnet genesis block is updated.
|
|
// Output:
|
|
// Failed to process block: already have block 267a53b5ee86c24a48ec37aee4f4e7c0c4004892b7259e695e9f5b321f1ab9d2
|
|
}
|