lbcd/ldb/tx.go

171 lines
4 KiB
Go
Raw Normal View History

// 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"
"encoding/binary"
"fmt"
//"github.com/conformal/btcdb"
"github.com/conformal/btcwire"
)
type txUpdateObj struct {
txSha *btcwire.ShaHash
blkHeight int64
txoff int
txlen int
spentData []byte
delete bool
}
// InsertTx inserts a tx hash and its associated data into the database.
func (db *LevelDb) InsertTx(txsha *btcwire.ShaHash, height int64, txoff int, txlen int, spentbuf []byte) (err error) {
db.dbLock.Lock()
defer db.dbLock.Unlock()
return db.insertTx(txsha, height, txoff, txlen, spentbuf)
}
// insertTx inserts a tx hash and its associated data into the database.
// Must be called with db lock held.
func (db *LevelDb) insertTx(txSha *btcwire.ShaHash, height int64, txoff int, txlen int, spentbuf []byte) (err error) {
var txU txUpdateObj
txU.txSha = txSha
txU.blkHeight = height
txU.txoff = txoff
txU.txlen = txlen
txU.spentData = spentbuf
db.txUpdateMap[*txSha] = &txU
return nil
}
// formatTx generates the value buffer for the Tx db.
func (db *LevelDb) formatTx(txu *txUpdateObj) ([]byte, error) {
blkHeight := txu.blkHeight
txoff := txu.txoff
txlen := txu.txlen
spentbuf := txu.spentData
txOff := int32(txoff)
txLen := int32(txlen)
var txW bytes.Buffer
err := binary.Write(&txW, binary.LittleEndian, blkHeight)
if err != nil {
err = fmt.Errorf("Write fail")
return nil, err
}
err = binary.Write(&txW, binary.LittleEndian, txOff)
if err != nil {
err = fmt.Errorf("Write fail")
return nil, err
}
err = binary.Write(&txW, binary.LittleEndian, txLen)
if err != nil {
err = fmt.Errorf("Write fail")
return nil, err
}
err = binary.Write(&txW, binary.LittleEndian, spentbuf)
if err != nil {
err = fmt.Errorf("Write fail")
return nil, err
}
return txW.Bytes(), nil
}
func (db *LevelDb) getTxData(txsha *btcwire.ShaHash) (rblkHeight int64,
rtxOff int, rtxLen int, rspentBuf []byte, err error) {
var buf []byte
key := shaTxToKey(txsha)
buf, err = db.lDb.Get(key, db.ro)
if err != nil {
return
}
var blkHeight int64
var txOff, txLen int32
dr := bytes.NewBuffer(buf)
err = binary.Read(dr, binary.LittleEndian, &blkHeight)
if err != nil {
err = fmt.Errorf("Db Corrupt 1")
return
}
err = binary.Read(dr, binary.LittleEndian, &txOff)
if err != nil {
err = fmt.Errorf("Db Corrupt 2")
return
}
err = binary.Read(dr, binary.LittleEndian, &txLen)
if err != nil {
err = fmt.Errorf("Db Corrupt 3")
return
}
// remainder of buffer is spentbuf
spentBuf := make([]byte, dr.Len())
err = binary.Read(dr, binary.LittleEndian, spentBuf)
if err != nil {
err = fmt.Errorf("Db Corrupt 4")
return
}
return blkHeight, int(txOff), int(txLen), spentBuf, nil
}
// ExistsTxSha returns if the given tx sha exists in the database
func (db *LevelDb) ExistsTxSha(txsha *btcwire.ShaHash) (exists bool) {
db.dbLock.Lock()
defer db.dbLock.Unlock()
return db.existsTxSha(txsha)
}
// existsTxSha returns if the given tx sha exists in the database.o
// Must be called with the db lock held.
func (db *LevelDb) existsTxSha(txSha *btcwire.ShaHash) (exists bool) {
_, _, _, _, err := db.getTxData(txSha)
if err == nil {
return true
}
// BUG(drahn) If there was an error beside non-existant deal with it.
return false
}
// FetchLocationBySha looks up the Tx sha information by name.
func (db *LevelDb) FetchLocationBySha(txsha *btcwire.ShaHash) (blockidx int64, txoff int, txlen int, err error) {
db.dbLock.Lock()
defer db.dbLock.Unlock()
err = fmt.Errorf("obsolete function")
return
}
// FetchTxUsedBySha returns the used/spent buffer for a given transaction.
func (db *LevelDb) FetchTxUsedBySha(txSha *btcwire.ShaHash) (spentbuf []byte, err error) {
db.dbLock.Lock()
defer db.dbLock.Unlock()
_, _, _, spentbuf, err = db.getTxData(txSha)
if err != nil {
return
}
return // spentbuf has the value already
}
func (db *LevelDb) fetchLocationUsedBySha(txsha *btcwire.ShaHash) error {
// delete me
return fmt.Errorf("Deleted function")
}