96f7305c29
improved error handling Fix testing, no point in running tests multiple times Fix error when no blocks in database, reopen would misreport NewstSha() return
170 lines
4 KiB
Go
170 lines
4 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"
|
|
"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")
|
|
}
|