forked from cerc-io/ipld-eth-server
* Add vendor dir so builds dont require dep * Pin specific version go-eth version
This commit is contained in:
+185
@@ -0,0 +1,185 @@
|
||||
// Copyright (c) 2013-2016 The btcsuite developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/btcsuite/btcd/blockchain"
|
||||
"github.com/btcsuite/btcd/chaincfg"
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/database"
|
||||
)
|
||||
|
||||
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 btcchain
|
||||
// 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 := int32(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 := int32(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 btcchain code expects for checkpoints added to the list.
|
||||
func showCandidate(candidateNum int, checkpoint *chaincfg.Checkpoint) {
|
||||
if cfg.UseGoOutput {
|
||||
fmt.Printf("Candidate %d -- {%d, newShaHashFromStr(\"%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()
|
||||
|
||||
// Setup chain. Ignore notifications since they aren't needed for this
|
||||
// util.
|
||||
chain, err := blockchain.New(&blockchain.Config{
|
||||
DB: db,
|
||||
ChainParams: activeNetParams,
|
||||
TimeSource: blockchain.NewMedianTime(),
|
||||
})
|
||||
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)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user