Remove the showblock utility.
This utility is a relic from initial development before it was possible to request blocks and transactions via RPC. The correct way to do this now is by using RPC since that works while btcd is operating unlike the utility which requires an exclusive lock on the database.
This commit is contained in:
parent
741797c601
commit
188cf2555f
1 changed files with 0 additions and 313 deletions
|
@ -1,313 +0,0 @@
|
|||
// 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 (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
|
||||
"github.com/btcsuite/btcd/database"
|
||||
_ "github.com/btcsuite/btcd/database/ldb"
|
||||
"github.com/btcsuite/btclog"
|
||||
"github.com/btcsuite/btcnet"
|
||||
"github.com/btcsuite/btcutil"
|
||||
"github.com/btcsuite/btcwire"
|
||||
flags "github.com/btcsuite/go-flags"
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
)
|
||||
|
||||
type ShaHash btcwire.ShaHash
|
||||
|
||||
type config struct {
|
||||
DataDir string `short:"b" long:"datadir" description:"Directory to store data"`
|
||||
DbType string `long:"dbtype" description:"Database backend"`
|
||||
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"`
|
||||
OutFile string `short:"o" description:"outfile"`
|
||||
Progress bool `short:"p" description:"show progress"`
|
||||
ShaString string `short:"s" description:"Block SHA to process" required:"true"`
|
||||
EShaString string `short:"e" description:"End Block SHA to process"`
|
||||
RawBlock bool `short:"r" description:"Raw Block"`
|
||||
FmtBlock bool `short:"f" description:"Format Block"`
|
||||
ShowTx bool `short:"t" description:"Show transaction"`
|
||||
}
|
||||
|
||||
var (
|
||||
btcdHomeDir = btcutil.AppDataDir("btcd", false)
|
||||
defaultDataDir = filepath.Join(btcdHomeDir, "data")
|
||||
log btclog.Logger
|
||||
activeNetParams = &btcnet.MainNetParams
|
||||
)
|
||||
|
||||
const (
|
||||
ArgSha = iota
|
||||
ArgHeight
|
||||
)
|
||||
|
||||
// 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
|
||||
// btcnet parameters. This function can be used to override this directory name
|
||||
// as "testnet" when the passed active network matches btcwire.TestNet3.
|
||||
//
|
||||
// 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.
|
||||
func netName(netParams *btcnet.Params) string {
|
||||
switch netParams.Net {
|
||||
case btcwire.TestNet3:
|
||||
return "testnet"
|
||||
default:
|
||||
return netParams.Name
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
end := int64(-1)
|
||||
|
||||
cfg := config{
|
||||
DbType: "leveldb",
|
||||
DataDir: defaultDataDir,
|
||||
}
|
||||
parser := flags.NewParser(&cfg, flags.Default)
|
||||
_, err := parser.Parse()
|
||||
if err != nil {
|
||||
if e, ok := err.(*flags.Error); !ok || e.Type != flags.ErrHelp {
|
||||
parser.WriteHelp(os.Stderr)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
backendLogger := btclog.NewDefaultBackendLogger()
|
||||
defer backendLogger.Flush()
|
||||
log = btclog.NewSubsystemLogger(backendLogger, "")
|
||||
database.UseLogger(log)
|
||||
|
||||
// Multiple networks can't be selected simultaneously.
|
||||
funcName := "main"
|
||||
numNets := 0
|
||||
// Count number of network flags passed; assign active network params
|
||||
// while we're at it
|
||||
if cfg.TestNet3 {
|
||||
numNets++
|
||||
activeNetParams = &btcnet.TestNet3Params
|
||||
}
|
||||
if cfg.RegressionTest {
|
||||
numNets++
|
||||
activeNetParams = &btcnet.RegressionNetParams
|
||||
}
|
||||
if cfg.SimNet {
|
||||
numNets++
|
||||
activeNetParams = &btcnet.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
|
||||
}
|
||||
cfg.DataDir = filepath.Join(cfg.DataDir, netName(activeNetParams))
|
||||
|
||||
blockDbNamePrefix := "blocks"
|
||||
dbName := blockDbNamePrefix + "_" + cfg.DbType
|
||||
if cfg.DbType == "sqlite" {
|
||||
dbName = dbName + ".db"
|
||||
}
|
||||
dbPath := filepath.Join(cfg.DataDir, dbName)
|
||||
|
||||
log.Infof("loading db %v", cfg.DbType)
|
||||
db, err := database.OpenDB(cfg.DbType, dbPath)
|
||||
if err != nil {
|
||||
log.Warnf("db open failed: %v", err)
|
||||
return
|
||||
}
|
||||
defer db.Close()
|
||||
log.Infof("db load complete")
|
||||
|
||||
height, err := getHeight(db, cfg.ShaString)
|
||||
if err != nil {
|
||||
log.Infof("Invalid block %v", cfg.ShaString)
|
||||
return
|
||||
}
|
||||
if cfg.EShaString != "" {
|
||||
end, err = getHeight(db, cfg.EShaString)
|
||||
if err != nil {
|
||||
log.Infof("Invalid end block %v", cfg.EShaString)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
end = height + 1
|
||||
}
|
||||
|
||||
log.Infof("height %v end %v", height, end)
|
||||
|
||||
var fo io.WriteCloser
|
||||
if cfg.OutFile != "" {
|
||||
fo, err = os.Create(cfg.OutFile)
|
||||
if err != nil {
|
||||
log.Warnf("failed to open file %v, err %v", cfg.OutFile, err)
|
||||
}
|
||||
defer func() {
|
||||
if err := fo.Close(); err != nil {
|
||||
log.Warn("failed to close file %v %v", cfg.OutFile, err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
for ; height < end; height++ {
|
||||
if cfg.Progress && height%int64(1) == 0 {
|
||||
log.Infof("Processing block %v", height)
|
||||
}
|
||||
err = DumpBlock(db, height, fo, cfg.RawBlock, cfg.FmtBlock, cfg.ShowTx)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
if cfg.Progress {
|
||||
height--
|
||||
log.Infof("Processing block %v", height)
|
||||
}
|
||||
}
|
||||
|
||||
func getHeight(db database.Db, str string) (int64, error) {
|
||||
argtype, idx, sha, err := parsesha(str)
|
||||
if err != nil {
|
||||
log.Warnf("unable to decode [%v] %v", str, err)
|
||||
return 0, err
|
||||
}
|
||||
|
||||
switch argtype {
|
||||
case ArgSha:
|
||||
// nothing to do
|
||||
blk, err := db.FetchBlockBySha(sha)
|
||||
if err != nil {
|
||||
log.Warnf("unable to locate block sha %v err %v",
|
||||
sha, err)
|
||||
return 0, err
|
||||
}
|
||||
idx = blk.Height()
|
||||
case ArgHeight:
|
||||
}
|
||||
return idx, nil
|
||||
}
|
||||
|
||||
func DumpBlock(db database.Db, height int64, fo io.Writer, rflag bool, fflag bool, tflag bool) error {
|
||||
sha, err := db.FetchBlockShaByHeight(height)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
blk, err := db.FetchBlockBySha(sha)
|
||||
if err != nil {
|
||||
log.Warnf("Failed to fetch block %v, err %v", sha, err)
|
||||
return err
|
||||
}
|
||||
rblk, err := blk.Bytes()
|
||||
blkid := blk.Height()
|
||||
|
||||
if rflag {
|
||||
log.Infof("Block %v depth %v %v", sha, blkid, spew.Sdump(rblk))
|
||||
}
|
||||
|
||||
mblk := blk.MsgBlock()
|
||||
if fflag {
|
||||
log.Infof("Block %v depth %v %v", sha, blkid, spew.Sdump(mblk))
|
||||
}
|
||||
if tflag {
|
||||
log.Infof("Num transactions %v", len(mblk.Transactions))
|
||||
for i, tx := range mblk.Transactions {
|
||||
txsha, err := tx.TxSha()
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
log.Infof("tx %v: %v", i, &txsha)
|
||||
|
||||
}
|
||||
}
|
||||
if fo != nil {
|
||||
// generate and write header values
|
||||
binary.Write(fo, binary.LittleEndian, uint32(btcwire.MainNet))
|
||||
binary.Write(fo, binary.LittleEndian, uint32(len(rblk)))
|
||||
|
||||
// write block
|
||||
fo.Write(rblk)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var ntxcnt int64
|
||||
var txspendcnt int64
|
||||
var txgivecnt int64
|
||||
|
||||
var ErrBadShaPrefix = errors.New("invalid prefix")
|
||||
var ErrBadShaLen = errors.New("invalid len")
|
||||
var ErrBadShaChar = errors.New("invalid character")
|
||||
|
||||
func parsesha(argstr string) (argtype int, height int64, psha *btcwire.ShaHash, err error) {
|
||||
var sha btcwire.ShaHash
|
||||
|
||||
var hashbuf string
|
||||
|
||||
switch len(argstr) {
|
||||
case 64:
|
||||
hashbuf = argstr
|
||||
case 66:
|
||||
if argstr[0:2] != "0x" {
|
||||
log.Infof("prefix is %v", argstr[0:2])
|
||||
err = ErrBadShaPrefix
|
||||
return
|
||||
}
|
||||
hashbuf = argstr[2:]
|
||||
default:
|
||||
if len(argstr) <= 16 {
|
||||
// assume value is height
|
||||
argtype = ArgHeight
|
||||
var h int
|
||||
h, err = strconv.Atoi(argstr)
|
||||
if err == nil {
|
||||
height = int64(h)
|
||||
return
|
||||
}
|
||||
log.Infof("Unable to parse height %v, err %v", height, err)
|
||||
}
|
||||
err = ErrBadShaLen
|
||||
return
|
||||
}
|
||||
|
||||
var buf [32]byte
|
||||
for idx, ch := range hashbuf {
|
||||
var val rune
|
||||
|
||||
switch {
|
||||
case ch >= '0' && ch <= '9':
|
||||
val = ch - '0'
|
||||
case ch >= 'a' && ch <= 'f':
|
||||
val = ch - 'a' + rune(10)
|
||||
case ch >= 'A' && ch <= 'F':
|
||||
val = ch - 'A' + rune(10)
|
||||
default:
|
||||
err = ErrBadShaChar
|
||||
return
|
||||
}
|
||||
b := buf[31-idx/2]
|
||||
if idx&1 == 1 {
|
||||
b |= byte(val)
|
||||
} else {
|
||||
b |= (byte(val) << 4)
|
||||
}
|
||||
buf[31-idx/2] = b
|
||||
}
|
||||
sha.SetBytes(buf[0:32])
|
||||
psha = &sha
|
||||
return
|
||||
}
|
Loading…
Reference in a new issue