func verifyChain(db btcdb.Db, level, depth int32) error { _, curheight64, err := db.NewestSha() if err != nil { rpcsLog.Errorf("Verify is unable to fetch current block "+ "height: %v", err) } curheight := int32(curheight64) if depth > curheight { depth = curheight } for height := curheight; height > (curheight - depth); height-- { // Level 0 just looks up the block. sha, err := db.FetchBlockShaByHeight(int64(height)) if err != nil { rpcsLog.Errorf("Verify is unable to fetch block at "+ "height %d: %v", height, err) return err } block, err := db.FetchBlockBySha(sha) if err != nil { rpcsLog.Errorf("Verify is unable to fetch block at "+ "sha %v height %d: %v", sha, height, err) return err } // Level 1 does basic chain sanity checks. if level > 0 { err := btcchain.CheckBlockSanity(block, activeNetParams.powLimit) if err != nil { rpcsLog.Errorf("Verify is unable to "+ "validate block at sha %v height "+ "%d: %v", sha, height, err) return err } } } rpcsLog.Infof("Chain verify completed successfully") return nil }
func DumpBlock(db btcdb.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 }
func fetch(db btcdb.Db, rd *rData) error { sha, err := db.FetchBlockShaByHeight(rd.in.H) if err != nil { return fmt.Errorf("failed FetchBlockShaByHeight(%v): %v\n", rd.in.H, err) } blk, err := db.FetchBlockBySha(sha) if err != nil { return fmt.Errorf("failed FetchBlockBySha(%v) - h %v: %v\n", sha, rd.in.H, err) } tx := blk.Transactions()[rd.in.Tx] rd.blkSha = sha rd.blk = blk rd.tx = tx rd.txInIndex = rd.in.TxIn rd.txIn = tx.MsgTx().TxIn[rd.in.TxIn] txPrevList, err := db.FetchTxBySha(&rd.txIn.PreviousOutPoint.Hash) if err != nil { return fmt.Errorf("failed FetchTxBySha(%v) - h %v: %v\n", rd.txIn.PreviousOutPoint.Hash, rd.in.H, err) } if len(txPrevList) != 1 { return fmt.Errorf("not single FetchTxBySha(%v) - h %v: %v\n", rd.txIn.PreviousOutPoint.Hash, rd.in.H, len(txPrevList)) } blkPrev, err := db.FetchBlockBySha(txPrevList[0].BlkSha) if err != nil { return fmt.Errorf("failed prev FetchBlockBySha(%v) - h %v: %v\n", txPrevList[0].BlkSha, rd.in.H, err) } rd.txPrev = txPrevList[0] rd.txPrevOutIndex = rd.txIn.PreviousOutPoint.Index rd.txPrevOut = rd.txPrev.Tx.TxOut[rd.txPrevOutIndex] rd.blkPrev = blkPrev return nil }
func getSha(db btcdb.Db, str string) (btcwire.ShaHash, error) { argtype, idx, sha, err := parsesha(str) if err != nil { log.Warnf("unable to decode [%v] %v", str, err) return btcwire.ShaHash{}, err } switch argtype { case ArgSha: // nothing to do case ArgHeight: sha, err = db.FetchBlockShaByHeight(idx) if err != nil { return btcwire.ShaHash{}, err } } if sha == nil { fmt.Printf("wtf sha is nil but err is %v", err) } return *sha, nil }
func getSignatures(maxHeigth int64, log btclog.Logger, db btcdb.Db) chan *rData { heigthChan := make(chan int64) blockChan := make(chan *btcutil.Block) sigChan := make(chan *rData) go func() { for h := int64(0); h < maxHeigth; h++ { heigthChan <- h } close(heigthChan) }() var blockWg sync.WaitGroup for i := 0; i <= 10; i++ { blockWg.Add(1) go func() { for h := range heigthChan { sha, err := db.FetchBlockShaByHeight(h) if err != nil { log.Warnf("failed FetchBlockShaByHeight(%v): %v", h, err) return } blk, err := db.FetchBlockBySha(sha) if err != nil { log.Warnf("failed FetchBlockBySha(%v) - h %v: %v", sha, h, err) return } blockChan <- blk } blockWg.Done() }() } go func() { blockWg.Wait() close(blockChan) }() var sigWg sync.WaitGroup for i := 0; i <= 10; i++ { sigWg.Add(1) go func() { for blk := range blockChan { mblk := blk.MsgBlock() for i, tx := range mblk.Transactions { if btcchain.IsCoinBase(btcutil.NewTx(tx)) { continue } for t, txin := range tx.TxIn { dataSlice, err := btcscript.PushedData(txin.SignatureScript) if err != nil { continue } for d, data := range dataSlice { signature, err := btcec.ParseSignature(data, btcec.S256()) if err != nil { continue } sigChan <- &rData{ sig: signature, H: blk.Height(), Tx: i, TxIn: t, Data: d, } } } } } sigWg.Done() }() } go func() { sigWg.Wait() close(sigChan) }() return sigChan }
func testFetch(t *testing.T, db btcdb.Db, shas []btcwire.ShaHash, sync string) { // Test the newest sha is what we expect and call it twice to ensure // caching is working working properly. numShas := int64(len(shas)) newestSha := shas[numShas-1] newestBlockID := int64(numShas) testNewestSha(t, db, newestSha, newestBlockID, sync) testNewestSha(t, db, newestSha, newestBlockID, sync+" cached") for i, sha := range shas { // Add one for genesis block skew. i = i + 1 // Ensure the sha exists in the db as expected. if !db.ExistsSha(&sha) { t.Errorf("testSha %d doesn't exists (%s)", i, sync) break } // Fetch the sha from the db and ensure all fields are expected // values. buf, pver, idx, err := sqlite3.FetchSha(db, &sha) if err != nil { t.Errorf("Failed to fetch testSha %d (%s)", i, sync) } if !bytes.Equal(zeroBlock, buf) { t.Errorf("testSha %d incorrect block return (%s)", i, sync) } if pver != 1 { t.Errorf("pver is %d and not 1 for testSha %d (%s)", pver, i, sync) } if idx != int64(i) { t.Errorf("index isn't as expected %d vs %d (%s)", idx, i, sync) } // Fetch the sha by index and ensure it matches. tsha, err := db.FetchBlockShaByHeight(int64(i)) if err != nil { t.Errorf("can't fetch sha at index %d: %v", i, err) continue } if !tsha.IsEqual(&sha) { t.Errorf("sha for index %d isn't shas[%d]", i, i) } } endBlockID := numShas + 1 midBlockID := endBlockID / 2 fetchIdxTests := []fetchIdxTest{ // All shas. {1, btcdb.AllShas, shas, "fetch all shas"}, //// All shas using known bounds. {1, endBlockID, shas, "fetch all shas2"}, // Partial list starting at beginning. {1, midBlockID, shas[:midBlockID-1], "fetch first half"}, // Partial list ending at end. {midBlockID, endBlockID, shas[midBlockID-1 : endBlockID-1], "fetch second half"}, // Nonexistent off the end. {endBlockID, endBlockID * 2, []btcwire.ShaHash{}, "fetch nonexistent"}, } for _, test := range fetchIdxTests { t.Logf("numSha: %d - Fetch from %d to %d\n", numShas, test.start, test.end) if shalist, err := db.FetchHeightRange(test.start, test.end); err == nil { compareArray(t, shalist, test.exp, test.test, sync) } else { t.Errorf("failed to fetch index range for %s (%s)", test.test, sync) } } // Try and fetch nonexistent sha. if db.ExistsSha(&badSha) { t.Errorf("nonexistent sha exists (%s)!", sync) } _, _, _, err := sqlite3.FetchSha(db, &badSha) if err == nil { t.Errorf("Success when fetching a bad sha! (%s)", sync) } // XXX if not check to see it is the right value? testIterator(t, db, shas, sync) }