2013-10-04 17:12:24 +02:00
// Copyright (c) 2013 Conformal Systems LLC.
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package main
import (
"fmt"
2013-10-08 03:53:25 +02:00
"github.com/conformal/btcdb"
_ "github.com/conformal/btcdb/ldb"
_ "github.com/conformal/btcdb/sqlite3"
"github.com/conformal/btcwire"
2013-10-07 16:06:15 +02:00
"github.com/conformal/go-flags"
2013-10-04 17:12:24 +02:00
"os"
"path/filepath"
)
const (
minCandidates = 1
maxCandidates = 20
defaultNumCandidates = 5
2013-10-09 03:50:15 +02:00
defaultDbType = "leveldb"
2013-10-04 17:12:24 +02:00
)
var (
defaultDataDir = filepath . Join ( btcdHomeDir ( ) , "data" )
2013-10-08 03:53:25 +02:00
knownDbTypes = btcdb . SupportedDBs ( )
activeNetwork = btcwire . MainNet
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 {
DataDir string ` short:"b" long:"datadir" description:"Location of the btcd data directory" `
2013-10-08 03:53:25 +02:00
DbType string ` long:"dbtype" description:"Database backend to use for the Block Chain" `
TestNet3 bool ` long:"testnet" description:"Use the test network" `
2013-10-04 17:12:24 +02:00
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" `
}
// btcdHomeDir returns an OS appropriate home directory for btcd.
func btcdHomeDir ( ) string {
// Search for Windows APPDATA first. This won't exist on POSIX OSes.
appData := os . Getenv ( "APPDATA" )
if appData != "" {
return filepath . Join ( appData , "btcd" )
}
// Fall back to standard HOME directory that works for most POSIX OSes.
home := os . Getenv ( "HOME" )
if home != "" {
return filepath . Join ( home , ".btcd" )
}
// In the worst case, use the current directory.
return "."
}
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
}
2013-10-08 20:34:04 +02:00
// netName returns a human-readable name for the passed bitcoin network.
2013-10-08 03:53:25 +02:00
func netName ( btcnet btcwire . BitcoinNet ) string {
net := "mainnet"
if btcnet == btcwire . TestNet3 {
net = "testnet"
}
return net
}
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
}
2013-10-08 03:53:25 +02:00
// Choose the active network based on the flags.
if cfg . TestNet3 {
activeNetwork = btcwire . TestNet3
}
// 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.
2013-10-08 03:53:25 +02:00
cfg . DataDir = filepath . Join ( cfg . DataDir , netName ( activeNetwork ) )
// 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
}