Make AddressDescriptor as type,expose DB/mempool methods working with it

pull/56/head
Martin Boehm 2018-08-30 22:39:03 +02:00
parent 1a931d8a65
commit 676aabfaa6
14 changed files with 206 additions and 85 deletions

View File

@ -79,7 +79,7 @@ func GetChainParams(chain string) *chaincfg.Params {
}
// GetAddrDescFromAddress returns internal address representation of given address
func (p *BCashParser) GetAddrDescFromAddress(address string) ([]byte, error) {
func (p *BCashParser) GetAddrDescFromAddress(address string) (bchain.AddressDescriptor, error) {
return p.addressToOutputScript(address)
}

View File

@ -205,6 +205,11 @@ func (c *blockChainWithMetrics) GetMempoolTransactions(address string) (v []stri
return c.b.GetMempoolTransactions(address)
}
func (c *blockChainWithMetrics) GetMempoolTransactionsForAddrDesc(addrDesc bchain.AddressDescriptor) (v []string, err error) {
defer func(s time.Time) { c.observeRPCLatency("GetMempoolTransactionsForAddrDesc", s, err) }(time.Now())
return c.b.GetMempoolTransactionsForAddrDesc(addrDesc)
}
func (c *blockChainWithMetrics) GetMempoolEntry(txid string) (v *bchain.MempoolEntry, err error) {
defer func(s time.Time) { c.observeRPCLatency("GetMempoolEntry", s, err) }(time.Now())
return c.b.GetMempoolEntry(txid)

View File

@ -52,22 +52,22 @@ func GetChainParams(chain string) *chaincfg.Params {
}
// GetAddrDescFromVout returns internal address representation (descriptor) of given transaction output
func (p *BitcoinParser) GetAddrDescFromVout(output *bchain.Vout) ([]byte, error) {
func (p *BitcoinParser) GetAddrDescFromVout(output *bchain.Vout) (bchain.AddressDescriptor, error) {
return hex.DecodeString(output.ScriptPubKey.Hex)
}
// GetAddrDescFromAddress returns internal address representation (descriptor) of given address
func (p *BitcoinParser) GetAddrDescFromAddress(address string) ([]byte, error) {
func (p *BitcoinParser) GetAddrDescFromAddress(address string) (bchain.AddressDescriptor, error) {
return p.addressToOutputScript(address)
}
// GetAddressesFromAddrDesc returns addresses for given address descriptor with flag if the addresses are searchable
func (p *BitcoinParser) GetAddressesFromAddrDesc(addrDesc []byte) ([]string, bool, error) {
func (p *BitcoinParser) GetAddressesFromAddrDesc(addrDesc bchain.AddressDescriptor) ([]string, bool, error) {
return p.OutputScriptToAddressesFunc(addrDesc)
}
// GetScriptFromAddrDesc returns output script for given address descriptor
func (p *BitcoinParser) GetScriptFromAddrDesc(addrDesc []byte) ([]byte, error) {
func (p *BitcoinParser) GetScriptFromAddrDesc(addrDesc bchain.AddressDescriptor) ([]byte, error) {
return addrDesc, nil
}

View File

@ -617,12 +617,17 @@ func (b *BitcoinRPC) ResyncMempool(onNewTxAddr func(txid string, addr string)) (
return b.Mempool.Resync(onNewTxAddr)
}
// GetMempoolTransactions returns slice of mempool transactions for given address.
// GetMempoolTransactions returns slice of mempool transactions for given address
func (b *BitcoinRPC) GetMempoolTransactions(address string) ([]string, error) {
return b.Mempool.GetTransactions(address)
}
// EstimateSmartFee returns fee estimation.
// GetMempoolTransactionsForAddrDesc returns slice of mempool transactions for given address descriptor
func (b *BitcoinRPC) GetMempoolTransactionsForAddrDesc(addrDesc bchain.AddressDescriptor) ([]string, error) {
return b.Mempool.GetAddrDescTransactions(addrDesc)
}
// EstimateSmartFee returns fee estimation
func (b *BitcoinRPC) EstimateSmartFee(blocks int, conservative bool) (big.Int, error) {
// use EstimateFee if EstimateSmartFee is not supported
if !b.ChainConfig.SupportsEstimateSmartFee && b.ChainConfig.SupportsEstimateFee {

View File

@ -119,7 +119,7 @@ func (p *EthereumParser) ethTxToTx(tx *rpcTransaction, blocktime int64, confirma
}
// GetAddrDescFromVout returns internal address representation of given transaction output
func (p *EthereumParser) GetAddrDescFromVout(output *bchain.Vout) ([]byte, error) {
func (p *EthereumParser) GetAddrDescFromVout(output *bchain.Vout) (bchain.AddressDescriptor, error) {
if len(output.ScriptPubKey.Addresses) != 1 {
return nil, bchain.ErrAddressMissing
}
@ -131,7 +131,7 @@ func has0xPrefix(s string) bool {
}
// GetAddrDescFromAddress returns internal address representation of given address
func (p *EthereumParser) GetAddrDescFromAddress(address string) ([]byte, error) {
func (p *EthereumParser) GetAddrDescFromAddress(address string) (bchain.AddressDescriptor, error) {
// github.com/ethereum/go-ethereum/common.HexToAddress does not handle address errors, using own decoding
if has0xPrefix(address) {
address = address[2:]
@ -146,12 +146,12 @@ func (p *EthereumParser) GetAddrDescFromAddress(address string) ([]byte, error)
}
// GetAddressesFromAddrDesc returns addresses for given address descriptor with flag if the addresses are searchable
func (p *EthereumParser) GetAddressesFromAddrDesc(addrDesc []byte) ([]string, bool, error) {
func (p *EthereumParser) GetAddressesFromAddrDesc(addrDesc bchain.AddressDescriptor) ([]string, bool, error) {
return []string{hexutil.Encode(addrDesc)}, true, nil
}
// GetScriptFromAddrDesc returns output script for given address descriptor
func (p *EthereumParser) GetScriptFromAddrDesc(addrDesc []byte) ([]byte, error) {
func (p *EthereumParser) GetScriptFromAddrDesc(addrDesc bchain.AddressDescriptor) ([]byte, error) {
return addrDesc, nil
}

View File

@ -480,12 +480,12 @@ func (b *EthereumRPC) GetMempool() ([]string, error) {
return body.Transactions, nil
}
// EstimateFee returns fee estimation.
// EstimateFee returns fee estimation
func (b *EthereumRPC) EstimateFee(blocks int) (big.Int, error) {
return b.EstimateSmartFee(blocks, true)
}
// EstimateSmartFee returns fee estimation.
// EstimateSmartFee returns fee estimation
func (b *EthereumRPC) EstimateSmartFee(blocks int, conservative bool) (big.Int, error) {
ctx, cancel := context.WithTimeout(context.Background(), b.timeout)
defer cancel()
@ -503,7 +503,7 @@ func (b *EthereumRPC) EstimateSmartFee(blocks int, conservative bool) (big.Int,
return r, nil
}
// SendRawTransaction sends raw transaction.
// SendRawTransaction sends raw transaction
func (b *EthereumRPC) SendRawTransaction(tx string) (string, error) {
return "", errors.New("SendRawTransaction: not implemented")
}
@ -512,10 +512,16 @@ func (b *EthereumRPC) ResyncMempool(onNewTxAddr func(txid string, addr string))
return b.Mempool.Resync(onNewTxAddr)
}
// GetMempoolTransactions returns slice of mempool transactions for given address
func (b *EthereumRPC) GetMempoolTransactions(address string) ([]string, error) {
return b.Mempool.GetTransactions(address)
}
// GetMempoolTransactionsForAddrDesc returns slice of mempool transactions for given address descriptor
func (b *EthereumRPC) GetMempoolTransactionsForAddrDesc(addrDesc bchain.AddressDescriptor) ([]string, error) {
return b.Mempool.GetAddrDescTransactions(addrDesc)
}
func (b *EthereumRPC) GetMempoolEntry(txid string) (*bchain.MempoolEntry, error) {
return nil, errors.New("GetMempoolEntry: not implemented")
}

View File

@ -1,6 +1,7 @@
package monacoin
import (
"blockbook/bchain"
"blockbook/bchain/coins/btc"
"github.com/btcsuite/btcd/chaincfg"
@ -89,8 +90,8 @@ func GetMonaChainParams(chain string) *monacoinCfg.Params {
}
}
// GetAddrIDFromAddress returns internal address representation of given address
func (p *MonacoinParser) GetAddrIDFromAddress(address string) ([]byte, error) {
// GetAddrDescFromAddress returns internal address representation (descriptor) of given address
func (p *MonacoinParser) GetAddrDescFromAddress(address string) (bchain.AddressDescriptor, error) {
return p.addressToOutputScript(address)
}

View File

@ -121,6 +121,81 @@ func Test_GetAddrDescFromAddress_Mainnet(t *testing.T) {
}
}
func Test_GetAddressesFromAddrDesc(t *testing.T) {
type args struct {
script string
}
tests := []struct {
name string
args args
want []string
want2 bool
wantErr bool
}{
{
name: "P2PKH",
args: args{script: "76a91451dadacc7021440cbe4ca148a5db563b329b4c0388ac"},
want: []string{"MFMy9FwJsV6HiN5eZDqDETw4pw52q3UGrb"},
want2: true,
wantErr: false,
},
{
name: "P2SH",
args: args{script: "a9146449f568c9cd2378138f2636e1567112a184a9e887"},
want: []string{"PHjTKtgYLTJ9D2Bzw2f6xBB41KBm2HeGfg"},
want2: true,
wantErr: false,
},
{
name: "P2WPKH",
args: args{script: "0014a96d3cef194f469b33801f868ec9bc89a8831c22"},
want: []string{"mona1q49knemcefarfkvuqr7rgajdu3x5gx8pzdnurgq"},
want2: true,
wantErr: false,
},
{
name: "P2WSH",
args: args{script: "002009d27aa88e70cb7a0da620908c9bc08ac6c633bd1a61036312e514396aeb4893"},
want: []string{"mona1qp8f842ywwr9h5rdxyzggex7q3trvvvaarfssxccju52rj6htfzfsqr79j2"},
want2: true,
wantErr: false,
},
{
name: "OP_RETURN ascii",
args: args{script: "6a0461686f6a"},
want: []string{"OP_RETURN (ahoj)"},
want2: false,
wantErr: false,
},
{
name: "OP_RETURN hex",
args: args{script: "6a072020f1686f6a20"},
want: []string{"OP_RETURN 07 2020f1686f6a20"},
want2: false,
wantErr: false,
},
}
parser := NewMonacoinParser(GetChainParams("main"), &btc.Configuration{})
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
b, _ := hex.DecodeString(tt.args.script)
got, got2, err := parser.GetAddressesFromAddrDesc(b)
if (err != nil) != tt.wantErr {
t.Errorf("outputScriptToAddresses() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("GetAddressesFromAddrDesc() = %v, want %v", got, tt.want)
}
if !reflect.DeepEqual(got2, tt.want2) {
t.Errorf("GetAddressesFromAddrDesc() = %v, want %v", got2, tt.want2)
}
})
}
}
var (
testTx1 bchain.Tx

View File

@ -52,7 +52,7 @@ func GetChainParams(chain string) *chaincfg.Params {
}
// GetAddrDescFromVout returns internal address representation of given transaction output
func (p *ZCashParser) GetAddrDescFromVout(output *bchain.Vout) ([]byte, error) {
func (p *ZCashParser) GetAddrDescFromVout(output *bchain.Vout) (bchain.AddressDescriptor, error) {
if len(output.ScriptPubKey.Addresses) != 1 {
return nil, nil
}
@ -61,19 +61,19 @@ func (p *ZCashParser) GetAddrDescFromVout(output *bchain.Vout) ([]byte, error) {
}
// GetAddrDescFromAddress returns internal address representation of given address
func (p *ZCashParser) GetAddrDescFromAddress(address string) ([]byte, error) {
func (p *ZCashParser) GetAddrDescFromAddress(address string) (bchain.AddressDescriptor, error) {
hash, _, err := utils.CheckDecode(address)
return hash, err
}
// GetAddressesFromAddrDesc returns addresses for given address descriptor with flag if the addresses are searchable
func (p *ZCashParser) GetAddressesFromAddrDesc(addrDesc []byte) ([]string, bool, error) {
func (p *ZCashParser) GetAddressesFromAddrDesc(addrDesc bchain.AddressDescriptor) ([]string, bool, error) {
// TODO implement
return nil, false, errors.New("GetAddressesFromAddrDesc: not implemented")
}
// GetScriptFromAddrDesc returns output script for given address descriptor
func (p *ZCashParser) GetScriptFromAddrDesc(addrDesc []byte) ([]byte, error) {
func (p *ZCashParser) GetScriptFromAddrDesc(addrDesc bchain.AddressDescriptor) ([]byte, error) {
// TODO implement
return nil, errors.New("GetScriptFromAddrDesc: not implemented")
}

View File

@ -12,7 +12,7 @@ type NonUTXOMempool struct {
chain BlockChain
mux sync.Mutex
txToInputOutput map[string][]addrIndex
addrDescToTx map[string][]outpoint
addrDescToTx map[string][]outpoint
}
// NewNonUTXOMempool creates new mempool handler.
@ -27,6 +27,11 @@ func (m *NonUTXOMempool) GetTransactions(address string) ([]string, error) {
if err != nil {
return nil, err
}
return m.GetAddrDescTransactions(addrDesc)
}
// GetAddrDescTransactions returns slice of mempool transactions for given address descriptor
func (m *NonUTXOMempool) GetAddrDescTransactions(addrDesc AddressDescriptor) ([]string, error) {
m.mux.Lock()
defer m.mux.Unlock()
outpoints := m.addrDescToTx[string(addrDesc)]

View File

@ -74,6 +74,11 @@ func (m *UTXOMempool) GetTransactions(address string) ([]string, error) {
if err != nil {
return nil, err
}
return m.GetAddrDescTransactions(addrDesc)
}
// GetAddrDescTransactions returns slice of mempool transactions for given address descriptor
func (m *UTXOMempool) GetAddrDescTransactions(addrDesc AddressDescriptor) ([]string, error) {
m.mux.Lock()
defer m.mux.Unlock()
outpoints := m.addrDescToTx[string(addrDesc)]

View File

@ -111,6 +111,9 @@ func (e *RPCError) Error() string {
return fmt.Sprintf("%d: %s", e.Code, e.Message)
}
// AddressDescriptor is an opaque type obtained by parser.GetAddrDesc* methods
type AddressDescriptor []byte
// BlockChain defines common interface to block chain daemon
type BlockChain interface {
// life-cycle methods
@ -137,6 +140,7 @@ type BlockChain interface {
// mempool
ResyncMempool(onNewTxAddr func(txid string, addr string)) (int, error)
GetMempoolTransactions(address string) ([]string, error)
GetMempoolTransactionsForAddrDesc(addrDesc AddressDescriptor) ([]string, error)
GetMempoolEntry(txid string) (*MempoolEntry, error)
// parser
GetChainParser() BlockChainParser
@ -158,10 +162,10 @@ type BlockChainParser interface {
// it uses string operations to avoid problems with rounding
AmountToBigInt(n json.Number) (big.Int, error)
// address descriptor conversions
GetAddrDescFromVout(output *Vout) ([]byte, error)
GetAddrDescFromAddress(address string) ([]byte, error)
GetAddressesFromAddrDesc(addrDesc []byte) ([]string, bool, error)
GetScriptFromAddrDesc(addrDesc []byte) ([]byte, error)
GetAddrDescFromVout(output *Vout) (AddressDescriptor, error)
GetAddrDescFromAddress(address string) (AddressDescriptor, error)
GetAddressesFromAddrDesc(addrDesc AddressDescriptor) ([]string, bool, error)
GetScriptFromAddrDesc(addrDesc AddressDescriptor) ([]byte, error)
// transactions
PackedTxidLen() int
PackTxid(txid string) ([]byte, error)

View File

@ -155,6 +155,13 @@ func (d *RocksDB) GetMemoryStats() string {
return fmt.Sprintf("%+v", m)
}
// StopIteration is returned by callback function to signal stop of iteration
type StopIteration struct{}
func (e *StopIteration) Error() string {
return ""
}
// GetTransactions finds all input/output transactions for address
// Transaction are passed to callback function.
func (d *RocksDB) GetTransactions(address string, lower uint32, higher uint32, fn func(txid string, vout uint32, isOutput bool) error) (err error) {
@ -165,7 +172,12 @@ func (d *RocksDB) GetTransactions(address string, lower uint32, higher uint32, f
if err != nil {
return err
}
return d.GetAddrDescTransactions(addrDesc, lower, higher, fn)
}
// GetAddrDescTransactions finds all input/output transactions for address descriptor
// Transaction are passed to callback function.
func (d *RocksDB) GetAddrDescTransactions(addrDesc bchain.AddressDescriptor, lower uint32, higher uint32, fn func(txid string, vout uint32, isOutput bool) error) (err error) {
kstart := packAddressKey(addrDesc, lower)
kstop := packAddressKey(addrDesc, higher)
@ -200,6 +212,9 @@ func (d *RocksDB) GetTransactions(address string, lower uint32, higher uint32, f
return err
}
if err := fn(tx, vout, isOutput); err != nil {
if _, ok := err.(*StopIteration); ok {
return nil
}
return err
}
}
@ -281,22 +296,22 @@ type outpoint struct {
}
type TxInput struct {
addrDesc []byte
AddrDesc bchain.AddressDescriptor
ValueSat big.Int
}
func (ti *TxInput) Addresses(p bchain.BlockChainParser) ([]string, bool, error) {
return p.GetAddressesFromAddrDesc(ti.addrDesc)
return p.GetAddressesFromAddrDesc(ti.AddrDesc)
}
type TxOutput struct {
addrDesc []byte
AddrDesc bchain.AddressDescriptor
Spent bool
ValueSat big.Int
}
func (to *TxOutput) Addresses(p bchain.BlockChainParser) ([]string, bool, error) {
return p.GetAddressesFromAddrDesc(to.addrDesc)
return p.GetAddressesFromAddrDesc(to.AddrDesc)
}
type TxAddresses struct {
@ -322,7 +337,7 @@ type blockTxs struct {
inputs []outpoint
}
func (d *RocksDB) resetValueSatToZero(valueSat *big.Int, addrDesc []byte, logText string) {
func (d *RocksDB) resetValueSatToZero(valueSat *big.Int, addrDesc bchain.AddressDescriptor, logText string) {
ad, _, err := d.chainParser.GetAddressesFromAddrDesc(addrDesc)
had := hex.EncodeToString(addrDesc)
if err != nil {
@ -363,7 +378,7 @@ func (d *RocksDB) processAddressesUTXO(block *bchain.Block, addresses map[string
}
continue
}
tao.addrDesc = addrDesc
tao.AddrDesc = addrDesc
strAddrDesc := string(addrDesc)
// check that the address was used already in this block
o, processed := addresses[strAddrDesc]
@ -377,7 +392,7 @@ func (d *RocksDB) processAddressesUTXO(block *bchain.Block, addresses map[string
})
ab, e := balances[strAddrDesc]
if !e {
ab, err = d.getAddrDescBalance(addrDesc)
ab, err = d.GetAddrDescBalance(addrDesc)
if err != nil {
return err
}
@ -431,18 +446,18 @@ func (d *RocksDB) processAddressesUTXO(block *bchain.Block, addresses map[string
if ot.Spent {
glog.Warningf("rocksdb: height %d, tx %v, input tx %v vout %v is double spend", block.Height, tx.Txid, input.Txid, input.Vout)
}
tai.addrDesc = ot.addrDesc
tai.AddrDesc = ot.AddrDesc
tai.ValueSat = ot.ValueSat
// mark the output as spent in tx
ot.Spent = true
if len(ot.addrDesc) == 0 {
if len(ot.AddrDesc) == 0 {
if !logged {
glog.Warningf("rocksdb: height %d, tx %v, input tx %v vout %v skipping empty address", block.Height, tx.Txid, input.Txid, input.Vout)
logged = true
}
continue
}
strAddrDesc := string(ot.addrDesc)
strAddrDesc := string(ot.AddrDesc)
// check that the address was used already in this block
o, processed := addresses[strAddrDesc]
if processed {
@ -455,7 +470,7 @@ func (d *RocksDB) processAddressesUTXO(block *bchain.Block, addresses map[string
})
ab, e := balances[strAddrDesc]
if !e {
ab, err = d.getAddrDescBalance(ot.addrDesc)
ab, err = d.GetAddrDescBalance(ot.AddrDesc)
if err != nil {
return err
}
@ -470,7 +485,7 @@ func (d *RocksDB) processAddressesUTXO(block *bchain.Block, addresses map[string
}
ab.BalanceSat.Sub(&ab.BalanceSat, &ot.ValueSat)
if ab.BalanceSat.Sign() < 0 {
d.resetValueSatToZero(&ab.BalanceSat, ot.addrDesc, "balance")
d.resetValueSatToZero(&ab.BalanceSat, ot.AddrDesc, "balance")
}
ab.SentSat.Add(&ab.SentSat, &ot.ValueSat)
}
@ -489,7 +504,7 @@ func processedInTx(o []outpoint, btxID []byte) bool {
func (d *RocksDB) storeAddresses(wb *gorocksdb.WriteBatch, height uint32, addresses map[string][]outpoint) error {
for addrDesc, outpoints := range addresses {
ba := []byte(addrDesc)
ba := bchain.AddressDescriptor(addrDesc)
key := packAddressKey(ba, height)
val := d.packOutpoints(outpoints)
wb.PutCF(d.cfh[cfAddresses], key, val)
@ -513,14 +528,14 @@ func (d *RocksDB) storeBalances(wb *gorocksdb.WriteBatch, abm map[string]*AddrBa
for addrDesc, ab := range abm {
// balance with 0 transactions is removed from db - happens in disconnect
if ab == nil || ab.Txs <= 0 {
wb.DeleteCF(d.cfh[cfAddressBalance], []byte(addrDesc))
wb.DeleteCF(d.cfh[cfAddressBalance], bchain.AddressDescriptor(addrDesc))
} else {
l := packVaruint(uint(ab.Txs), buf)
ll := packBigint(&ab.SentSat, buf[l:])
l += ll
ll = packBigint(&ab.BalanceSat, buf[l:])
l += ll
wb.PutCF(d.cfh[cfAddressBalance], []byte(addrDesc), buf[:l])
wb.PutCF(d.cfh[cfAddressBalance], bchain.AddressDescriptor(addrDesc), buf[:l])
}
}
return nil
@ -609,7 +624,7 @@ func (d *RocksDB) getBlockTxs(height uint32) ([]blockTxs, error) {
return bt, nil
}
func (d *RocksDB) getAddrDescBalance(addrDesc []byte) (*AddrBalance, error) {
func (d *RocksDB) GetAddrDescBalance(addrDesc bchain.AddressDescriptor) (*AddrBalance, error) {
val, err := d.db.GetCF(d.ro, d.cfh[cfAddressBalance], addrDesc)
if err != nil {
return nil, err
@ -636,7 +651,7 @@ func (d *RocksDB) GetAddressBalance(address string) (*AddrBalance, error) {
if err != nil {
return nil, err
}
return d.getAddrDescBalance(addrDesc)
return d.GetAddrDescBalance(addrDesc)
}
func (d *RocksDB) getTxAddresses(btxID []byte) (*TxAddresses, error) {
@ -680,23 +695,23 @@ func packTxAddresses(ta *TxAddresses, buf []byte, varBuf []byte) []byte {
}
func appendTxInput(txi *TxInput, buf []byte, varBuf []byte) []byte {
la := len(txi.addrDesc)
la := len(txi.AddrDesc)
l := packVaruint(uint(la), varBuf)
buf = append(buf, varBuf[:l]...)
buf = append(buf, txi.addrDesc...)
buf = append(buf, txi.AddrDesc...)
l = packBigint(&txi.ValueSat, varBuf)
buf = append(buf, varBuf[:l]...)
return buf
}
func appendTxOutput(txo *TxOutput, buf []byte, varBuf []byte) []byte {
la := len(txo.addrDesc)
la := len(txo.AddrDesc)
if txo.Spent {
la = ^la
}
l := packVarint(la, varBuf)
buf = append(buf, varBuf[:l]...)
buf = append(buf, txo.addrDesc...)
buf = append(buf, txo.AddrDesc...)
l = packBigint(&txo.ValueSat, varBuf)
buf = append(buf, varBuf[:l]...)
return buf
@ -723,8 +738,8 @@ func unpackTxAddresses(buf []byte) (*TxAddresses, error) {
func unpackTxInput(ti *TxInput, buf []byte) int {
al, l := unpackVaruint(buf)
ti.addrDesc = make([]byte, al)
copy(ti.addrDesc, buf[l:l+int(al)])
ti.AddrDesc = make([]byte, al)
copy(ti.AddrDesc, buf[l:l+int(al)])
al += uint(l)
ti.ValueSat, l = unpackBigint(buf[al:])
return l + int(al)
@ -736,8 +751,8 @@ func unpackTxOutput(to *TxOutput, buf []byte) int {
to.Spent = true
al = ^al
}
to.addrDesc = make([]byte, al)
copy(to.addrDesc, buf[l:l+al])
to.AddrDesc = make([]byte, al)
copy(to.AddrDesc, buf[l:l+al])
al += l
to.ValueSat, l = unpackBigint(buf[al:])
return l + al
@ -790,7 +805,7 @@ func (d *RocksDB) unpackNOutpoints(buf []byte) ([]outpoint, int, error) {
return outpoints, p, nil
}
func (d *RocksDB) addAddrDescToRecords(op int, wb *gorocksdb.WriteBatch, records map[string][]outpoint, addrDesc []byte, btxid []byte, vout int32, bh uint32) error {
func (d *RocksDB) addAddrDescToRecords(op int, wb *gorocksdb.WriteBatch, records map[string][]outpoint, addrDesc bchain.AddressDescriptor, btxid []byte, vout int32, bh uint32) error {
if len(addrDesc) > 0 {
if len(addrDesc) > maxAddrDescLen {
glog.Infof("rocksdb: block %d, skipping addrDesc of length %d", bh, len(addrDesc))
@ -846,7 +861,7 @@ func (d *RocksDB) writeAddressesNonUTXO(wb *gorocksdb.WriteBatch, block *bchain.
}
}
for addrDesc, outpoints := range addresses {
key := packAddressKey([]byte(addrDesc), block.Height)
key := packAddressKey(bchain.AddressDescriptor(addrDesc), block.Height)
switch op {
case opInsert:
val := d.packOutpoints(outpoints)
@ -1022,12 +1037,12 @@ func (d *RocksDB) allAddressesScan(lower uint32, higher uint32) ([][]byte, [][]b
func (d *RocksDB) disconnectTxAddresses(wb *gorocksdb.WriteBatch, height uint32, txid string, inputs []outpoint, txa *TxAddresses,
txAddressesToUpdate map[string]*TxAddresses, balances map[string]*AddrBalance) error {
addresses := make(map[string]struct{})
getAddressBalance := func(addrDesc []byte) (*AddrBalance, error) {
getAddressBalance := func(addrDesc bchain.AddressDescriptor) (*AddrBalance, error) {
var err error
s := string(addrDesc)
b, fb := balances[s]
if !fb {
b, err = d.getAddrDescBalance(addrDesc)
b, err = d.GetAddrDescBalance(addrDesc)
if err != nil {
return nil, err
}
@ -1036,13 +1051,13 @@ func (d *RocksDB) disconnectTxAddresses(wb *gorocksdb.WriteBatch, height uint32,
return b, nil
}
for i, t := range txa.Inputs {
if len(t.addrDesc) > 0 {
s := string(t.addrDesc)
if len(t.AddrDesc) > 0 {
s := string(t.AddrDesc)
_, exist := addresses[s]
if !exist {
addresses[s] = struct{}{}
}
b, err := getAddressBalance(t.addrDesc)
b, err := getAddressBalance(t.AddrDesc)
if err != nil {
return err
}
@ -1053,12 +1068,12 @@ func (d *RocksDB) disconnectTxAddresses(wb *gorocksdb.WriteBatch, height uint32,
}
b.SentSat.Sub(&b.SentSat, &t.ValueSat)
if b.SentSat.Sign() < 0 {
d.resetValueSatToZero(&b.SentSat, t.addrDesc, "sent amount")
d.resetValueSatToZero(&b.SentSat, t.AddrDesc, "sent amount")
}
b.BalanceSat.Add(&b.BalanceSat, &t.ValueSat)
} else {
ad, _, _ := d.chainParser.GetAddressesFromAddrDesc(t.addrDesc)
had := hex.EncodeToString(t.addrDesc)
ad, _, _ := d.chainParser.GetAddressesFromAddrDesc(t.AddrDesc)
had := hex.EncodeToString(t.AddrDesc)
glog.Warningf("Balance for address %s (%s) not found", ad, had)
}
s = string(inputs[i].btxID)
@ -1074,13 +1089,13 @@ func (d *RocksDB) disconnectTxAddresses(wb *gorocksdb.WriteBatch, height uint32,
}
}
for _, t := range txa.Outputs {
if len(t.addrDesc) > 0 {
s := string(t.addrDesc)
if len(t.AddrDesc) > 0 {
s := string(t.AddrDesc)
_, exist := addresses[s]
if !exist {
addresses[s] = struct{}{}
}
b, err := getAddressBalance(t.addrDesc)
b, err := getAddressBalance(t.AddrDesc)
if err != nil {
return err
}
@ -1091,11 +1106,11 @@ func (d *RocksDB) disconnectTxAddresses(wb *gorocksdb.WriteBatch, height uint32,
}
b.BalanceSat.Sub(&b.BalanceSat, &t.ValueSat)
if b.BalanceSat.Sign() < 0 {
d.resetValueSatToZero(&b.BalanceSat, t.addrDesc, "balance")
d.resetValueSatToZero(&b.BalanceSat, t.AddrDesc, "balance")
}
} else {
ad, _, _ := d.chainParser.GetAddressesFromAddrDesc(t.addrDesc)
had := hex.EncodeToString(t.addrDesc)
ad, _, _ := d.chainParser.GetAddressesFromAddrDesc(t.AddrDesc)
had := hex.EncodeToString(t.AddrDesc)
glog.Warningf("Balance for address %s (%s) not found", ad, had)
}
}
@ -1427,7 +1442,7 @@ func (d *RocksDB) ComputeInternalStateColumnStats(stopCompute chan os.Signal) er
// Helpers
func packAddressKey(addrDesc []byte, height uint32) []byte {
func packAddressKey(addrDesc bchain.AddressDescriptor, height uint32) []byte {
bheight := packUint(height)
buf := make([]byte, 0, len(addrDesc)+len(bheight))
buf = append(buf, addrDesc...)

View File

@ -816,22 +816,22 @@ func TestRocksDB_Index_UTXO(t *testing.T) {
Height: 225494,
Inputs: []TxInput{
{
addrDesc: addressToAddrDesc(addr3, d.chainParser),
AddrDesc: addressToAddrDesc(addr3, d.chainParser),
ValueSat: *satB1T2A3,
},
{
addrDesc: addressToAddrDesc(addr2, d.chainParser),
AddrDesc: addressToAddrDesc(addr2, d.chainParser),
ValueSat: *satB1T1A2,
},
},
Outputs: []TxOutput{
{
addrDesc: addressToAddrDesc(addr6, d.chainParser),
AddrDesc: addressToAddrDesc(addr6, d.chainParser),
Spent: true,
ValueSat: *satB2T1A6,
},
{
addrDesc: addressToAddrDesc(addr7, d.chainParser),
AddrDesc: addressToAddrDesc(addr7, d.chainParser),
Spent: false,
ValueSat: *satB2T1A7,
},
@ -1001,17 +1001,17 @@ func Test_packTxAddresses_unpackTxAddresses(t *testing.T) {
Height: 123,
Inputs: []TxInput{
{
addrDesc: addressToAddrDesc("tb1qgw4vyzs3dcy75nmezjlpc40yc9a2vq9hghdyt2", parser),
AddrDesc: addressToAddrDesc("tb1qgw4vyzs3dcy75nmezjlpc40yc9a2vq9hghdyt2", parser),
ValueSat: *big.NewInt(0),
},
{
addrDesc: addressToAddrDesc("tb1q233n429a9e2jh48gnsq7w0qm0yz7kkzx0qczw8", parser),
AddrDesc: addressToAddrDesc("tb1q233n429a9e2jh48gnsq7w0qm0yz7kkzx0qczw8", parser),
ValueSat: *big.NewInt(1234123421342341234),
},
},
Outputs: []TxOutput{
{
addrDesc: addressToAddrDesc("tb1qgw4vyzs3dcy75nmezjlpc40yc9a2vq9hghdyt2", parser),
AddrDesc: addressToAddrDesc("tb1qgw4vyzs3dcy75nmezjlpc40yc9a2vq9hghdyt2", parser),
ValueSat: *big.NewInt(1),
Spent: true,
},
@ -1025,39 +1025,39 @@ func Test_packTxAddresses_unpackTxAddresses(t *testing.T) {
Height: 12345,
Inputs: []TxInput{
{
addrDesc: addressToAddrDesc("2N7iL7AvS4LViugwsdjTB13uN4T7XhV1bCP", parser),
AddrDesc: addressToAddrDesc("2N7iL7AvS4LViugwsdjTB13uN4T7XhV1bCP", parser),
ValueSat: *big.NewInt(9011000000),
},
{
addrDesc: addressToAddrDesc("2Mt9v216YiNBAzobeNEzd4FQweHrGyuRHze", parser),
AddrDesc: addressToAddrDesc("2Mt9v216YiNBAzobeNEzd4FQweHrGyuRHze", parser),
ValueSat: *big.NewInt(8011000000),
},
{
addrDesc: addressToAddrDesc("2NDyqJpHvHnqNtL1F9xAeCWMAW8WLJmEMyD", parser),
AddrDesc: addressToAddrDesc("2NDyqJpHvHnqNtL1F9xAeCWMAW8WLJmEMyD", parser),
ValueSat: *big.NewInt(7011000000),
},
},
Outputs: []TxOutput{
{
addrDesc: addressToAddrDesc("2MuwoFGwABMakU7DCpdGDAKzyj2nTyRagDP", parser),
AddrDesc: addressToAddrDesc("2MuwoFGwABMakU7DCpdGDAKzyj2nTyRagDP", parser),
ValueSat: *big.NewInt(5011000000),
Spent: true,
},
{
addrDesc: addressToAddrDesc("2Mvcmw7qkGXNWzkfH1EjvxDcNRGL1Kf2tEM", parser),
AddrDesc: addressToAddrDesc("2Mvcmw7qkGXNWzkfH1EjvxDcNRGL1Kf2tEM", parser),
ValueSat: *big.NewInt(6011000000),
},
{
addrDesc: addressToAddrDesc("2N9GVuX3XJGHS5MCdgn97gVezc6EgvzikTB", parser),
AddrDesc: addressToAddrDesc("2N9GVuX3XJGHS5MCdgn97gVezc6EgvzikTB", parser),
ValueSat: *big.NewInt(7011000000),
Spent: true,
},
{
addrDesc: addressToAddrDesc("mzii3fuRSpExMLJEHdHveW8NmiX8MPgavk", parser),
AddrDesc: addressToAddrDesc("mzii3fuRSpExMLJEHdHveW8NmiX8MPgavk", parser),
ValueSat: *big.NewInt(999900000),
},
{
addrDesc: addressToAddrDesc("mqHPFTRk23JZm9W1ANuEFtwTYwxjESSgKs", parser),
AddrDesc: addressToAddrDesc("mqHPFTRk23JZm9W1ANuEFtwTYwxjESSgKs", parser),
ValueSat: *big.NewInt(5000000000),
Spent: true,
},
@ -1071,17 +1071,17 @@ func Test_packTxAddresses_unpackTxAddresses(t *testing.T) {
Height: 123456789,
Inputs: []TxInput{
{
addrDesc: []byte{},
AddrDesc: []byte{},
ValueSat: *big.NewInt(1234),
},
},
Outputs: []TxOutput{
{
addrDesc: []byte{},
AddrDesc: []byte{},
ValueSat: *big.NewInt(5678),
},
{
addrDesc: []byte{},
AddrDesc: []byte{},
ValueSat: *big.NewInt(98),
Spent: true,
},