Merge branch 'master' into ethereum

This commit is contained in:
Martin Boehm 2018-03-26 17:19:16 +02:00
commit 4de5673bb3
3 changed files with 61 additions and 19 deletions

View file

@ -331,6 +331,11 @@ func (b *BitcoinRPC) GetBlockChainInfo() (string, error) {
return res.Result.Chain, nil return res.Result.Chain, nil
} }
func isErrBlockNotFound(err *bchain.RPCError) bool {
return err.Message == "Block not found" ||
err.Message == "Block height out of range"
}
// GetBlockHash returns hash of block in best-block-chain at given height. // GetBlockHash returns hash of block in best-block-chain at given height.
func (b *BitcoinRPC) GetBlockHash(height uint32) (string, error) { func (b *BitcoinRPC) GetBlockHash(height uint32) (string, error) {
glog.V(1).Info("rpc: getblockhash ", height) glog.V(1).Info("rpc: getblockhash ", height)
@ -344,6 +349,9 @@ func (b *BitcoinRPC) GetBlockHash(height uint32) (string, error) {
return "", errors.Annotatef(err, "height %v", height) return "", errors.Annotatef(err, "height %v", height)
} }
if res.Error != nil { if res.Error != nil {
if isErrBlockNotFound(res.Error) {
return "", bchain.ErrBlockNotFound
}
return "", errors.Annotatef(res.Error, "height %v", height) return "", errors.Annotatef(res.Error, "height %v", height)
} }
return res.Result, nil return res.Result, nil
@ -363,6 +371,9 @@ func (b *BitcoinRPC) GetBlockHeader(hash string) (*bchain.BlockHeader, error) {
return nil, errors.Annotatef(err, "hash %v", hash) return nil, errors.Annotatef(err, "hash %v", hash)
} }
if res.Error != nil { if res.Error != nil {
if isErrBlockNotFound(res.Error) {
return nil, bchain.ErrBlockNotFound
}
return nil, errors.Annotatef(res.Error, "hash %v", hash) return nil, errors.Annotatef(res.Error, "hash %v", hash)
} }
return &res.Result, nil return &res.Result, nil
@ -370,6 +381,13 @@ func (b *BitcoinRPC) GetBlockHeader(hash string) (*bchain.BlockHeader, error) {
// GetBlock returns block with given hash. // GetBlock returns block with given hash.
func (b *BitcoinRPC) GetBlock(hash string, height uint32) (*bchain.Block, error) { func (b *BitcoinRPC) GetBlock(hash string, height uint32) (*bchain.Block, error) {
var err error
if hash == "" && height > 0 {
hash, err = b.GetBlockHash(height)
if err != nil {
return nil, err
}
}
if !b.ParseBlocks { if !b.ParseBlocks {
return b.GetBlockFull(hash) return b.GetBlockFull(hash)
} }
@ -423,6 +441,9 @@ func (b *BitcoinRPC) GetBlockRaw(hash string) ([]byte, error) {
return nil, errors.Annotatef(err, "hash %v", hash) return nil, errors.Annotatef(err, "hash %v", hash)
} }
if res.Error != nil { if res.Error != nil {
if isErrBlockNotFound(res.Error) {
return nil, bchain.ErrBlockNotFound
}
return nil, errors.Annotatef(res.Error, "hash %v", hash) return nil, errors.Annotatef(res.Error, "hash %v", hash)
} }
return hex.DecodeString(res.Result) return hex.DecodeString(res.Result)
@ -443,6 +464,9 @@ func (b *BitcoinRPC) GetBlockList(hash string) (*bchain.Block, error) {
return nil, errors.Annotatef(err, "hash %v", hash) return nil, errors.Annotatef(err, "hash %v", hash)
} }
if res.Error != nil { if res.Error != nil {
if isErrBlockNotFound(res.Error) {
return nil, bchain.ErrBlockNotFound
}
return nil, errors.Annotatef(res.Error, "hash %v", hash) return nil, errors.Annotatef(res.Error, "hash %v", hash)
} }
@ -475,6 +499,9 @@ func (b *BitcoinRPC) GetBlockFull(hash string) (*bchain.Block, error) {
return nil, errors.Annotatef(err, "hash %v", hash) return nil, errors.Annotatef(err, "hash %v", hash)
} }
if res.Error != nil { if res.Error != nil {
if isErrBlockNotFound(res.Error) {
return nil, bchain.ErrBlockNotFound
}
return nil, errors.Annotatef(res.Error, "hash %v", hash) return nil, errors.Annotatef(res.Error, "hash %v", hash)
} }
return &res.Result, nil return &res.Result, nil

View file

@ -1,6 +1,17 @@
package bchain package bchain
import "fmt" import (
"errors"
"fmt"
)
// errors with specific meaning returned by blockchain rpc
var (
// ErrBlockNotFound is returned when block is not found
// either unknown hash or too high height
// can be returned from GetBlockHash, GetBlockHeader, GetBlock
ErrBlockNotFound = errors.New("Block not found")
)
type ScriptSig struct { type ScriptSig struct {
// Asm string `json:"asm"` // Asm string `json:"asm"`

View file

@ -4,7 +4,6 @@ import (
"blockbook/bchain" "blockbook/bchain"
"blockbook/common" "blockbook/common"
"os" "os"
"strings"
"sync" "sync"
"sync/atomic" "sync/atomic"
"time" "time"
@ -20,6 +19,7 @@ type SyncWorker struct {
syncWorkers, syncChunk int syncWorkers, syncChunk int
dryRun bool dryRun bool
startHeight uint32 startHeight uint32
startHash string
chanOsSignal chan os.Signal chanOsSignal chan os.Signal
metrics *common.Metrics metrics *common.Metrics
} }
@ -67,10 +67,6 @@ func (w *SyncWorker) ResyncIndex(onNewBlock func(hash string)) error {
return err return err
} }
func isError(err error, s string) bool {
return strings.Contains(err.Error(), s)
}
func (w *SyncWorker) resyncIndex(onNewBlock func(hash string)) error { func (w *SyncWorker) resyncIndex(onNewBlock func(hash string)) error {
remote, err := w.chain.GetBestBlockHash() remote, err := w.chain.GetBestBlockHash()
if err != nil { if err != nil {
@ -94,7 +90,7 @@ func (w *SyncWorker) resyncIndex(onNewBlock func(hash string)) error {
header, err = w.chain.GetBlockHeader(local) header, err = w.chain.GetBlockHeader(local)
forked := false forked := false
if err != nil { if err != nil {
if isError(err, "Block not found") { if err == bchain.ErrBlockNotFound {
forked = true forked = true
} else { } else {
return err return err
@ -132,16 +128,15 @@ func (w *SyncWorker) resyncIndex(onNewBlock func(hash string)) error {
} }
} }
var hash string
if header != nil { if header != nil {
glog.Info("resync: local is behind") glog.Info("resync: local is behind")
hash = header.Next w.startHash = header.Next
w.startHeight = localBestHeight w.startHeight = localBestHeight
} else { } else {
// If the local block is missing, we're indexing from the genesis block // If the local block is missing, we're indexing from the genesis block
// or from the start block specified by flags // or from the start block specified by flags
glog.Info("resync: genesis from block ", w.startHeight) glog.Info("resync: genesis from block ", w.startHeight)
hash, err = w.chain.GetBlockHash(w.startHeight) w.startHash, err = w.chain.GetBlockHash(w.startHeight)
if err != nil { if err != nil {
return err return err
} }
@ -166,15 +161,15 @@ func (w *SyncWorker) resyncIndex(onNewBlock func(hash string)) error {
} }
} }
return w.connectBlocks(hash, onNewBlock) return w.connectBlocks(onNewBlock)
} }
func (w *SyncWorker) connectBlocks(hash string, onNewBlock func(hash string)) error { func (w *SyncWorker) connectBlocks(onNewBlock func(hash string)) error {
bch := make(chan blockResult, 8) bch := make(chan blockResult, 8)
done := make(chan struct{}) done := make(chan struct{})
defer close(done) defer close(done)
go w.getBlockChain(hash, bch, done) go w.getBlockChain(bch, done)
var lastRes blockResult var lastRes blockResult
for res := range bch { for res := range bch {
@ -276,7 +271,7 @@ func (w *SyncWorker) connectBlockChunk(lower, higher uint32) error {
connected, err := w.isBlockConnected(higher) connected, err := w.isBlockConnected(higher)
if err != nil || connected { if err != nil || connected {
// if higher is over the best block, continue with lower block, otherwise return error // if higher is over the best block, continue with lower block, otherwise return error
if isError(err, "Block height out of range") { if err != bchain.ErrBlockNotFound {
return err return err
} }
} }
@ -327,7 +322,7 @@ func (w *SyncWorker) ConnectBlocksParallelInChunks(lower, higher uint32) error {
} }
err := w.connectBlockChunk(low, high) err := w.connectBlockChunk(low, high)
if err != nil { if err != nil {
if isError(err, "Block height out of range") || isError(err, "Block not found") { if err == bchain.ErrBlockNotFound {
break break
} }
glog.Fatalf("connectBlocksParallel %d-%d %v", low, high, err) glog.Fatalf("connectBlocksParallel %d-%d %v", low, high, err)
@ -348,7 +343,7 @@ func (w *SyncWorker) isBlockConnected(height uint32) (bool, error) {
if err != nil { if err != nil {
return false, err return false, err
} }
remote, err := w.db.GetBlockHash(height) remote, err := w.chain.GetBlockHash(height)
if err != nil { if err != nil {
return false, err return false, err
} }
@ -363,21 +358,30 @@ type blockResult struct {
err error err error
} }
func (w *SyncWorker) getBlockChain(hash string, out chan blockResult, done chan struct{}) { func (w *SyncWorker) getBlockChain(out chan blockResult, done chan struct{}) {
defer close(out) defer close(out)
for hash != "" { hash := w.startHash
height := w.startHeight
// some coins do not return Next hash
// must loop until error
for {
select { select {
case <-done: case <-done:
return return
default: default:
} }
block, err := w.chain.GetBlock(hash, 0) block, err := w.chain.GetBlock(hash, height)
if err != nil { if err != nil {
if err == bchain.ErrBlockNotFound {
break
}
out <- blockResult{err: err} out <- blockResult{err: err}
return return
} }
hash = block.Next hash = block.Next
height++
out <- blockResult{block: block} out <- blockResult{block: block}
} }
} }