diff --git a/bchain/coins/bch/bcashparser.go b/bchain/coins/bch/bcashparser.go index ccfebc29..2c804867 100644 --- a/bchain/coins/bch/bcashparser.go +++ b/bchain/coins/bch/bcashparser.go @@ -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) } diff --git a/bchain/coins/blockchain.go b/bchain/coins/blockchain.go index ddd1ffd2..b0be1d2b 100644 --- a/bchain/coins/blockchain.go +++ b/bchain/coins/blockchain.go @@ -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) diff --git a/bchain/coins/btc/bitcoinparser.go b/bchain/coins/btc/bitcoinparser.go index e48829fd..a4745be0 100644 --- a/bchain/coins/btc/bitcoinparser.go +++ b/bchain/coins/btc/bitcoinparser.go @@ -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 } diff --git a/bchain/coins/btc/bitcoinrpc.go b/bchain/coins/btc/bitcoinrpc.go index a6305106..ead2380c 100644 --- a/bchain/coins/btc/bitcoinrpc.go +++ b/bchain/coins/btc/bitcoinrpc.go @@ -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 { diff --git a/bchain/coins/eth/ethparser.go b/bchain/coins/eth/ethparser.go index f933b761..d76aa6bf 100644 --- a/bchain/coins/eth/ethparser.go +++ b/bchain/coins/eth/ethparser.go @@ -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 } diff --git a/bchain/coins/eth/ethrpc.go b/bchain/coins/eth/ethrpc.go index 2ef90b5d..cb08b664 100644 --- a/bchain/coins/eth/ethrpc.go +++ b/bchain/coins/eth/ethrpc.go @@ -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") } diff --git a/bchain/coins/monacoin/monacoinparser.go b/bchain/coins/monacoin/monacoinparser.go index 88d0870c..4a05bdf0 100644 --- a/bchain/coins/monacoin/monacoinparser.go +++ b/bchain/coins/monacoin/monacoinparser.go @@ -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) } diff --git a/bchain/coins/monacoin/monacoinparser_test.go b/bchain/coins/monacoin/monacoinparser_test.go index 9f559749..3b9e759e 100644 --- a/bchain/coins/monacoin/monacoinparser_test.go +++ b/bchain/coins/monacoin/monacoinparser_test.go @@ -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 diff --git a/bchain/coins/zec/zcashparser.go b/bchain/coins/zec/zcashparser.go index 84f422db..7b7e6e20 100644 --- a/bchain/coins/zec/zcashparser.go +++ b/bchain/coins/zec/zcashparser.go @@ -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") } diff --git a/bchain/mempool_nonutxo.go b/bchain/mempool_nonutxo.go index 3d1aa66f..1930aaa6 100644 --- a/bchain/mempool_nonutxo.go +++ b/bchain/mempool_nonutxo.go @@ -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)] diff --git a/bchain/mempool_utxo.go b/bchain/mempool_utxo.go index f89daa29..f111b513 100644 --- a/bchain/mempool_utxo.go +++ b/bchain/mempool_utxo.go @@ -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)] diff --git a/bchain/types.go b/bchain/types.go index 50d69f9a..e27bca57 100644 --- a/bchain/types.go +++ b/bchain/types.go @@ -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) diff --git a/db/rocksdb.go b/db/rocksdb.go index 82c7d46d..00967f0d 100644 --- a/db/rocksdb.go +++ b/db/rocksdb.go @@ -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...) diff --git a/db/rocksdb_test.go b/db/rocksdb_test.go index e1785fda..5b04fa3f 100644 --- a/db/rocksdb_test.go +++ b/db/rocksdb_test.go @@ -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, },