cda0b10082
FetchTxBySha changes what it returns, it can now return a TxListReply and and error if none are found. FetchTxByShaList is renamed to FetchUnSpentTxByShaList to indicate that it will (likey/eventually) only return Tx that have some unspent TxOuts. Tx which are fully spent may not be (reliably) looked up using this API.
129 lines
3.5 KiB
Go
129 lines
3.5 KiB
Go
// 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 ldb
|
|
|
|
import (
|
|
"bytes"
|
|
"github.com/conformal/btcdb"
|
|
"github.com/conformal/btcutil"
|
|
"github.com/conformal/btcwire"
|
|
)
|
|
|
|
// FetchBlockBySha - return a btcutil Block, object may be a cached.
|
|
func (db *LevelDb) FetchBlockBySha(sha *btcwire.ShaHash) (blk *btcutil.Block, err error) {
|
|
db.dbLock.Lock()
|
|
defer db.dbLock.Unlock()
|
|
return db.fetchBlockBySha(sha)
|
|
}
|
|
|
|
// fetchBlockBySha - return a btcutil Block, object may be a cached.
|
|
// Must be called with db lock held.
|
|
func (db *LevelDb) fetchBlockBySha(sha *btcwire.ShaHash) (blk *btcutil.Block, err error) {
|
|
|
|
buf, height, err := db.fetchSha(sha)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
blk, err = btcutil.NewBlockFromBytes(buf)
|
|
if err != nil {
|
|
return
|
|
}
|
|
blk.SetHeight(height)
|
|
|
|
return
|
|
}
|
|
|
|
// FetchUnSpentTxByShaList given a array of ShaHash, look up the transactions
|
|
// and return them in a TxListReply array.
|
|
func (db *LevelDb) FetchUnSpentTxByShaList(txShaList []*btcwire.ShaHash) []*btcdb.TxListReply {
|
|
db.dbLock.Lock()
|
|
defer db.dbLock.Unlock()
|
|
|
|
replies := make([]*btcdb.TxListReply, len(txShaList))
|
|
for i, txsha := range txShaList {
|
|
tx, blockSha, height, txspent, err := db.fetchTxDataBySha(txsha)
|
|
btxspent := []bool{}
|
|
if err == nil {
|
|
btxspent = make([]bool, len(tx.TxOut), len(tx.TxOut))
|
|
for idx := range tx.TxOut {
|
|
byteidx := idx / 8
|
|
byteoff := uint(idx % 8)
|
|
btxspent[idx] = (txspent[byteidx] & (byte(1) << byteoff)) != 0
|
|
}
|
|
}
|
|
txlre := btcdb.TxListReply{Sha: txsha, Tx: tx, BlkSha: blockSha, Height: height, TxSpent: btxspent, Err: err}
|
|
replies[i] = &txlre
|
|
}
|
|
return replies
|
|
}
|
|
|
|
// fetchTxDataBySha returns several pieces of data regarding the given sha.
|
|
func (db *LevelDb) fetchTxDataBySha(txsha *btcwire.ShaHash) (rtx *btcwire.MsgTx, rblksha *btcwire.ShaHash, rheight int64, rtxspent []byte, err error) {
|
|
var blksha *btcwire.ShaHash
|
|
var blkHeight int64
|
|
var txspent []byte
|
|
var txOff, txLen int
|
|
var blkbuf []byte
|
|
|
|
blkHeight, txOff, txLen, txspent, err = db.getTxData(txsha)
|
|
if err != nil {
|
|
err = btcdb.TxShaMissing
|
|
return
|
|
}
|
|
|
|
blksha, blkbuf, err = db.getBlkByHeight(blkHeight)
|
|
if err != nil {
|
|
return
|
|
}
|
|
|
|
//log.Trace("transaction %v is at block %v %v txoff %v, txlen %v\n",
|
|
// txsha, blksha, blkHeight, txOff, txLen)
|
|
|
|
rbuf := bytes.NewBuffer(blkbuf[txOff:txOff+txLen])
|
|
|
|
var tx btcwire.MsgTx
|
|
err = tx.Deserialize(rbuf)
|
|
if err != nil {
|
|
log.Warnf("unable to decode tx block %v %v txoff %v txlen %v",
|
|
blkHeight, blksha, txOff, txLen)
|
|
return
|
|
}
|
|
|
|
return &tx, blksha, blkHeight, txspent, nil
|
|
}
|
|
|
|
// FetchTxBySha returns some data for the given Tx Sha.
|
|
func (db *LevelDb) FetchTxBySha(txsha *btcwire.ShaHash) ([]*btcdb.TxListReply, error) {
|
|
tx, blksha, height, txspent, err := db.fetchTxDataBySha(txsha)
|
|
if err != nil {
|
|
return []*btcdb.TxListReply{}, err
|
|
}
|
|
|
|
replies := make ([]*btcdb.TxListReply, 1)
|
|
|
|
btxspent := make([]bool, len(tx.TxOut), len(tx.TxOut))
|
|
for idx := range tx.TxOut {
|
|
byteidx := idx / 8
|
|
byteoff := uint(idx % 8)
|
|
btxspent[idx] = (txspent[byteidx] & (byte(1) << byteoff)) != 0
|
|
}
|
|
|
|
txlre := btcdb.TxListReply{Sha: txsha, Tx: tx, BlkSha: blksha, Height: height, TxSpent: btxspent, Err: err}
|
|
replies[0] = &txlre
|
|
return replies, nil
|
|
}
|
|
|
|
// InvalidateTxCache clear/release all cached transactions.
|
|
func (db *LevelDb) InvalidateTxCache() {
|
|
}
|
|
|
|
// InvalidateTxCache clear/release all cached blocks.
|
|
func (db *LevelDb) InvalidateBlockCache() {
|
|
}
|
|
|
|
// InvalidateCache clear/release all cached blocks and transactions.
|
|
func (db *LevelDb) InvalidateCache() {
|
|
}
|