2015-08-26 06:03:18 +02:00
// Copyright (c) 2013-2016 The btcsuite developers
2013-10-04 17:12:24 +02:00
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package main
import (
"fmt"
2014-07-02 15:50:08 +02:00
"os"
"path/filepath"
2015-02-06 06:18:27 +01:00
"github.com/btcsuite/btcd/chaincfg"
2015-08-26 11:54:55 +02:00
"github.com/btcsuite/btcd/database"
_ "github.com/btcsuite/btcd/database/ffldb"
2015-02-05 22:16:39 +01:00
"github.com/btcsuite/btcd/wire"
2015-01-15 17:30:38 +01:00
"github.com/btcsuite/btcutil"
2015-01-16 07:56:49 +01:00
flags "github.com/btcsuite/go-flags"
2013-10-04 17:12:24 +02:00
)
const (
minCandidates = 1
maxCandidates = 20
defaultNumCandidates = 5
2015-08-26 06:03:18 +02:00
defaultDbType = "ffldb"
2013-10-04 17:12:24 +02:00
)
var (
2014-07-21 07:42:41 +02:00
btcdHomeDir = btcutil . AppDataDir ( "btcd" , false )
defaultDataDir = filepath . Join ( btcdHomeDir , "data" )
2015-08-26 06:03:18 +02:00
knownDbTypes = database . SupportedDrivers ( )
2015-02-06 06:18:27 +01:00
activeNetParams = & chaincfg . MainNetParams
2013-10-04 17:12:24 +02:00
)
// config defines the configuration options for findcheckpoint.
//
// See loadConfig for details on the configuration load process.
type config struct {
2014-07-21 07:42:41 +02:00
DataDir string ` short:"b" long:"datadir" description:"Location of the btcd data directory" `
DbType string ` long:"dbtype" description:"Database backend to use for the Block Chain" `
TestNet3 bool ` long:"testnet" description:"Use the test network" `
RegressionTest bool ` long:"regtest" description:"Use the regression 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 btcchain checkpoint list" `
2013-10-04 17:12:24 +02:00
}
2013-10-08 03:53:25 +02:00
// 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
}
2014-05-27 06:39:30 +02:00
// netName returns the name used when referring to a bitcoin network. At the
// time of writing, btcd currently places blocks for testnet version 3 in the
// data and log directory "testnet", which does not match the Name field of the
2015-02-06 06:18:27 +01:00
// chaincfg parameters. This function can be used to override this directory name
2015-02-05 22:16:39 +01:00
// as "testnet" when the passed active network matches wire.TestNet3.
2014-05-27 06:39:30 +02:00
//
// A proper upgrade to move the data and log directories for this network to
// "testnet3" is planned for the future, at which point this function can be
// removed and the network parameter's name used instead.
2015-02-06 06:18:27 +01:00
func netName ( chainParams * chaincfg . Params ) string {
switch chainParams . Net {
2015-02-05 22:16:39 +01:00
case wire . TestNet3 :
2014-05-27 06:39:30 +02:00
return "testnet"
default :
2015-02-06 06:18:27 +01:00
return chainParams . Name
2013-10-08 03:53:25 +02:00
}
}
2013-10-04 17:12:24 +02:00
// loadConfig initializes and parses the config using command line options.
func loadConfig ( ) ( * config , [ ] string , error ) {
// Default config.
cfg := config {
DataDir : defaultDataDir ,
2013-10-08 03:53:25 +02:00
DbType : defaultDbType ,
2013-10-04 17:12:24 +02:00
NumCandidates : defaultNumCandidates ,
}
// Parse command line options.
parser := flags . NewParser ( & cfg , flags . Default )
remainingArgs , err := parser . Parse ( )
if err != nil {
if e , ok := err . ( * flags . Error ) ; ! ok || e . Type != flags . ErrHelp {
parser . WriteHelp ( os . Stderr )
}
return nil , nil , err
}
2014-07-21 07:42:41 +02:00
// 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
2013-10-08 03:53:25 +02:00
if cfg . TestNet3 {
2014-07-21 07:42:41 +02:00
numNets ++
2015-02-06 06:18:27 +01:00
activeNetParams = & chaincfg . TestNet3Params
2014-07-21 07:42:41 +02:00
}
if cfg . RegressionTest {
numNets ++
2015-02-06 06:18:27 +01:00
activeNetParams = & chaincfg . RegressionNetParams
2014-07-21 07:42:41 +02:00
}
if cfg . SimNet {
numNets ++
2015-02-06 06:18:27 +01:00
activeNetParams = & chaincfg . SimNetParams
2014-07-21 07:42:41 +02:00
}
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
2013-10-08 03:53:25 +02:00
}
// 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 )
2013-10-04 17:12:24 +02:00
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.
2014-07-21 07:42:41 +02:00
cfg . DataDir = filepath . Join ( cfg . DataDir , netName ( activeNetParams ) )
2013-10-08 03:53:25 +02:00
// 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
}
2013-10-04 17:12:24 +02:00
return & cfg , remainingArgs , nil
}