2013-08-03 17:20:05 +02:00
|
|
|
// 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
|
|
|
|
}
|
|
|
|
|
2013-10-13 17:08:21 +02:00
|
|
|
// FetchTxByShaList returns the most recent tx of the name fully spent or not
|
|
|
|
func (db *LevelDb) FetchTxByShaList(txShaList []*btcwire.ShaHash) []*btcdb.TxListReply {
|
|
|
|
// until the fully spent separation of tx is complete this is identical
|
|
|
|
// to FetchUnSpentTxByShaList
|
|
|
|
return db.FetchUnSpentTxByShaList(txShaList)
|
|
|
|
}
|
|
|
|
|
2013-10-03 21:21:45 +02:00
|
|
|
// FetchUnSpentTxByShaList given a array of ShaHash, look up the transactions
|
2013-08-03 17:20:05 +02:00
|
|
|
// and return them in a TxListReply array.
|
2013-10-03 21:21:45 +02:00
|
|
|
func (db *LevelDb) FetchUnSpentTxByShaList(txShaList []*btcwire.ShaHash) []*btcdb.TxListReply {
|
2013-08-03 17:20:05 +02:00
|
|
|
db.dbLock.Lock()
|
|
|
|
defer db.dbLock.Unlock()
|
|
|
|
|
|
|
|
replies := make([]*btcdb.TxListReply, len(txShaList))
|
|
|
|
for i, txsha := range txShaList {
|
2013-10-03 21:21:45 +02:00
|
|
|
tx, blockSha, height, txspent, err := db.fetchTxDataBySha(txsha)
|
2013-08-03 17:20:05 +02:00
|
|
|
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
|
|
|
|
}
|
|
|
|
}
|
2013-10-03 21:21:45 +02:00
|
|
|
txlre := btcdb.TxListReply{Sha: txsha, Tx: tx, BlkSha: blockSha, Height: height, TxSpent: btxspent, Err: err}
|
2013-08-03 17:20:05 +02:00
|
|
|
replies[i] = &txlre
|
|
|
|
}
|
|
|
|
return replies
|
|
|
|
}
|
|
|
|
|
|
|
|
// fetchTxDataBySha returns several pieces of data regarding the given sha.
|
2013-10-03 21:21:45 +02:00
|
|
|
func (db *LevelDb) fetchTxDataBySha(txsha *btcwire.ShaHash) (rtx *btcwire.MsgTx, rblksha *btcwire.ShaHash, rheight int64, rtxspent []byte, err error) {
|
2013-08-03 17:20:05 +02:00
|
|
|
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)
|
|
|
|
|
2013-10-13 20:02:45 +02:00
|
|
|
rbuf := bytes.NewBuffer(blkbuf[txOff : txOff+txLen])
|
2013-08-03 17:20:05 +02:00
|
|
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2013-10-03 21:21:45 +02:00
|
|
|
return &tx, blksha, blkHeight, txspent, nil
|
2013-08-03 17:20:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// FetchTxBySha returns some data for the given Tx Sha.
|
2013-10-03 21:21:45 +02:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2013-10-13 20:02:45 +02:00
|
|
|
replies := make([]*btcdb.TxListReply, 1)
|
2013-10-03 21:21:45 +02:00
|
|
|
|
|
|
|
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
|
2013-08-03 17:20:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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() {
|
|
|
|
}
|