Make AddressDescriptor as type,expose DB/mempool methods working with it
parent
1a931d8a65
commit
676aabfaa6
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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...)
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue