findcheckpoints: Remove utility.

This utility is no longer be necessary since the manual checkpoint logic
is being reworked in upcoming commits.
This commit is contained in:
Dave Collins 2022-05-10 11:55:15 -05:00
parent f31191a8c8
commit d4a0310073
No known key found for this signature in database
GPG Key ID: B8904D9D9C93D1F2
2 changed files with 0 additions and 334 deletions

View File

@ -1,129 +0,0 @@
// Copyright (c) 2013-2016 The btcsuite developers
// Copyright (c) 2015-2020 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package main
import (
"errors"
"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"
flags "github.com/jessevdk/go-flags"
)
const (
minCandidates = 1
maxCandidates = 20
defaultNumCandidates = 5
defaultDbType = "ffldb"
)
var (
dcrdHomeDir = dcrutil.AppDataDir("dcrd", false)
defaultDataDir = filepath.Join(dcrdHomeDir, "data")
knownDbTypes = database.SupportedDrivers()
activeNetParams = chaincfg.MainNetParams()
)
// config defines the configuration options for findcheckpoint.
//
// See loadConfig for details on the configuration load process.
type config struct {
DataDir string `short:"b" long:"datadir" description:"Location of the dcrd data directory"`
DbType string `long:"dbtype" description:"Database backend to use for the Block Chain"`
TestNet bool `long:"testnet" description:"Use the test network"`
SimNet bool `long:"simnet" description:"Use the simulation test network"`
NumCandidates int `short:"n" long:"numcandidates" description:"Max num of checkpoint candidates to show {1-20}"`
UseGoOutput bool `short:"g" long:"gooutput" description:"Display the candidates using Go syntax that is ready to insert into the dcrchain checkpoint list"`
}
// validDbType returns whether or not dbType is a supported database type.
func validDbType(dbType string) bool {
for _, knownType := range knownDbTypes {
if dbType == knownType {
return true
}
}
return false
}
// loadConfig initializes and parses the config using command line options.
func loadConfig() (*config, []string, error) {
// Default config.
cfg := config{
DataDir: defaultDataDir,
DbType: defaultDbType,
NumCandidates: defaultNumCandidates,
}
// Parse command line options.
parser := flags.NewParser(&cfg, flags.Default)
remainingArgs, err := parser.Parse()
if err != nil {
var e *flags.Error
if !errors.As(err, &e) || e.Type != flags.ErrHelp {
parser.WriteHelp(os.Stderr)
}
return nil, nil, err
}
// Multiple networks can't be selected simultaneously.
funcName := "loadConfig"
numNets := 0
// Count number of network flags passed; assign active network params
// while we're at it
if cfg.TestNet {
numNets++
activeNetParams = chaincfg.TestNet3Params()
}
if cfg.SimNet {
numNets++
activeNetParams = chaincfg.SimNetParams()
}
if numNets > 1 {
str := "%s: the testnet, regtest, and simnet params can't be " +
"used together -- choose one of the three"
err := fmt.Errorf(str, funcName)
fmt.Fprintln(os.Stderr, err)
parser.WriteHelp(os.Stderr)
return nil, nil, err
}
// Validate database type.
if !validDbType(cfg.DbType) {
str := "%s: the specified database type [%v] is invalid -- " +
"supported types %v"
err := fmt.Errorf(str, "loadConfig", cfg.DbType, knownDbTypes)
fmt.Fprintln(os.Stderr, err)
parser.WriteHelp(os.Stderr)
return nil, nil, err
}
// Append the network type to the data directory so it is "namespaced"
// per network. In addition to the block database, there are other
// pieces of data that are saved to disk such as address manager state.
// All data is specific to a network, so namespacing the data directory
// means each individual piece of serialized data does not have to
// worry about changing names per network and such.
cfg.DataDir = filepath.Join(cfg.DataDir, activeNetParams.Name)
// Validate the number of candidates.
if cfg.NumCandidates < minCandidates || cfg.NumCandidates > maxCandidates {
str := "%s: The specified number of candidates is out of " +
"range -- parsed [%v]"
err = fmt.Errorf(str, "loadConfig", cfg.NumCandidates)
fmt.Fprintln(os.Stderr, err)
parser.WriteHelp(os.Stderr)
return nil, nil, err
}
return &cfg, remainingArgs, nil
}

View File

@ -1,205 +0,0 @@
// Copyright (c) 2013-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 main
import (
"context"
"fmt"
"os"
"path/filepath"
"github.com/decred/dcrd/blockchain/v5"
"github.com/decred/dcrd/chaincfg/chainhash"
"github.com/decred/dcrd/chaincfg/v3"
"github.com/decred/dcrd/database/v3"
)
const blockDbNamePrefix = "blocks"
var (
cfg *config
)
// loadBlockDB opens the block database and returns a handle to it.
func loadBlockDB() (database.DB, error) {
// The database name is based on the database type.
dbName := blockDbNamePrefix + "_" + cfg.DbType
dbPath := filepath.Join(cfg.DataDir, dbName)
fmt.Printf("Loading block database from '%s'\n", dbPath)
db, err := database.Open(cfg.DbType, dbPath, activeNetParams.Net)
if err != nil {
return nil, err
}
return db, nil
}
// findCandidates searches the chain backwards for checkpoint candidates and
// returns a slice of found candidates, if any. It also stops searching for
// candidates at the last checkpoint that is already hard coded into chain
// since there is no point in finding candidates before already existing
// checkpoints.
func findCandidates(chain *blockchain.BlockChain, latestHash *chainhash.Hash) ([]*chaincfg.Checkpoint, error) {
// Start with the latest block of the main chain.
block, err := chain.BlockByHash(latestHash)
if err != nil {
return nil, err
}
// Get the latest known checkpoint.
latestCheckpoint := chain.LatestCheckpoint()
if latestCheckpoint == nil {
// Set the latest checkpoint to the genesis block if there isn't
// already one.
latestCheckpoint = &chaincfg.Checkpoint{
Hash: &activeNetParams.GenesisHash,
Height: 0,
}
}
// The latest known block must be at least the last known checkpoint
// plus required checkpoint confirmations.
checkpointConfirmations := int64(blockchain.CheckpointConfirmations)
requiredHeight := latestCheckpoint.Height + checkpointConfirmations
if block.Height() < requiredHeight {
return nil, fmt.Errorf("the block database is only at height "+
"%d which is less than the latest checkpoint height "+
"of %d plus required confirmations of %d",
block.Height(), latestCheckpoint.Height,
checkpointConfirmations)
}
// For the first checkpoint, the required height is any block after the
// genesis block, so long as the chain has at least the required number
// of confirmations (which is enforced above).
if len(activeNetParams.Checkpoints) == 0 {
requiredHeight = 1
}
// Indeterminate progress setup.
numBlocksToTest := block.Height() - requiredHeight
progressInterval := (numBlocksToTest / 100) + 1 // min 1
fmt.Print("Searching for candidates")
defer fmt.Println()
// Loop backwards through the chain to find checkpoint candidates.
candidates := make([]*chaincfg.Checkpoint, 0, cfg.NumCandidates)
numTested := int64(0)
for len(candidates) < cfg.NumCandidates && block.Height() > requiredHeight {
// Display progress.
if numTested%progressInterval == 0 {
fmt.Print(".")
}
// Determine if this block is a checkpoint candidate.
isCandidate, err := chain.IsCheckpointCandidate(block)
if err != nil {
return nil, err
}
// All checks passed, so this node seems like a reasonable
// checkpoint candidate.
if isCandidate {
checkpoint := chaincfg.Checkpoint{
Height: block.Height(),
Hash: block.Hash(),
}
candidates = append(candidates, &checkpoint)
}
prevHash := &block.MsgBlock().Header.PrevBlock
block, err = chain.BlockByHash(prevHash)
if err != nil {
return nil, err
}
numTested++
}
return candidates, nil
}
// showCandidate display a checkpoint candidate using and output format
// determined by the configuration parameters. The Go syntax output
// uses the format the chain code expects for checkpoints added to the list.
func showCandidate(candidateNum int, checkpoint *chaincfg.Checkpoint) {
if cfg.UseGoOutput {
fmt.Printf("Candidate %d -- {%d, newHashFromStr(\"%v\")},\n",
candidateNum, checkpoint.Height, checkpoint.Hash)
return
}
fmt.Printf("Candidate %d -- Height: %d, Hash: %v\n", candidateNum,
checkpoint.Height, checkpoint.Hash)
}
func main() {
// Load configuration and parse command line.
tcfg, _, err := loadConfig()
if err != nil {
return
}
cfg = tcfg
// Load the block database.
db, err := loadBlockDB()
if err != nil {
fmt.Fprintln(os.Stderr, "failed to load database:", err)
return
}
defer db.Close()
// Load the UTXO database.
utxoDb, err := blockchain.LoadUtxoDB(context.Background(), activeNetParams,
cfg.DataDir)
if err != nil {
fmt.Fprintln(os.Stderr, "failed to load UTXO database:", err)
return
}
defer utxoDb.Close()
// Instantiate a UTXO backend and UTXO cache.
utxoBackend := blockchain.NewLevelDbUtxoBackend(utxoDb)
utxoCache := blockchain.NewUtxoCache(&blockchain.UtxoCacheConfig{
Backend: utxoBackend,
FlushBlockDB: db.Flush,
MaxSize: 100 * 1024 * 1024, // 100 MiB
})
// Setup chain. Ignore notifications since they aren't needed for this
// util.
chain, err := blockchain.New(context.Background(),
&blockchain.Config{
DB: db,
ChainParams: activeNetParams,
UtxoBackend: blockchain.NewLevelDbUtxoBackend(utxoDb),
UtxoCache: utxoCache,
})
if err != nil {
fmt.Fprintf(os.Stderr, "failed to initialize chain: %v\n", err)
return
}
// Get the latest block hash and height from the database and report
// status.
best := chain.BestSnapshot()
fmt.Printf("Block database loaded with block height %d\n", best.Height)
// Find checkpoint candidates.
candidates, err := findCandidates(chain, &best.Hash)
if err != nil {
fmt.Fprintln(os.Stderr, "Unable to identify candidates:", err)
return
}
// No candidates.
if len(candidates) == 0 {
fmt.Println("No candidates found.")
return
}
// Show the candidates.
for i, checkpoint := range candidates {
showCandidate(i+1, checkpoint)
}
}