FIx GetAddressUtxo
This commit is contained in:
parent
983c6e9db5
commit
f1affaf92e
@ -222,7 +222,7 @@ func (w *Worker) GetTransaction(txid string, spendingTxs bool) (*Tx, error) {
|
|||||||
|
|
||||||
func (w *Worker) getAddressTxids(addrDesc bchain.AddressDescriptor, mempool bool) ([]string, error) {
|
func (w *Worker) getAddressTxids(addrDesc bchain.AddressDescriptor, mempool bool) ([]string, error) {
|
||||||
var err error
|
var err error
|
||||||
txids := make([]string, 0)
|
txids := make([]string, 0, 4)
|
||||||
if !mempool {
|
if !mempool {
|
||||||
err = w.db.GetAddrDescTransactions(addrDesc, 0, ^uint32(0), func(txid string, vout uint32, isOutput bool) error {
|
err = w.db.GetAddrDescTransactions(addrDesc, 0, ^uint32(0), func(txid string, vout uint32, isOutput bool) error {
|
||||||
txids = append(txids, txid)
|
txids = append(txids, txid)
|
||||||
@ -484,7 +484,7 @@ func (w *Worker) GetAddressUtxo(address string) ([]AddressUtxo, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, NewAPIError(fmt.Sprintf("Invalid address, %v", err), true)
|
return nil, NewAPIError(fmt.Sprintf("Invalid address, %v", err), true)
|
||||||
}
|
}
|
||||||
var r []AddressUtxo
|
r := make([]AddressUtxo, 0, 8)
|
||||||
// get utxo from mempool
|
// get utxo from mempool
|
||||||
txm, err := w.getAddressTxids(addrDesc, true)
|
txm, err := w.getAddressTxids(addrDesc, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -516,16 +516,17 @@ func (w *Worker) GetAddressUtxo(address string) ([]AddressUtxo, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, NewAPIError(fmt.Sprintf("Address not found, %v", err), true)
|
return nil, NewAPIError(fmt.Sprintf("Address not found, %v", err), true)
|
||||||
}
|
}
|
||||||
|
var checksum big.Int
|
||||||
// ba can be nil if the address is only in mempool!
|
// ba can be nil if the address is only in mempool!
|
||||||
if ba != nil && ba.BalanceSat.Uint64() > 0 {
|
if ba != nil && ba.BalanceSat.Uint64() > 0 {
|
||||||
type outpoint struct {
|
type outpoint struct {
|
||||||
txid string
|
txid string
|
||||||
vout uint32
|
vout uint32
|
||||||
}
|
}
|
||||||
txids := make([]outpoint, 0)
|
outpoints := make([]outpoint, 0, 8)
|
||||||
err = w.db.GetAddrDescTransactions(addrDesc, 0, ^uint32(0), func(txid string, vout uint32, isOutput bool) error {
|
err = w.db.GetAddrDescTransactions(addrDesc, 0, ^uint32(0), func(txid string, vout uint32, isOutput bool) error {
|
||||||
if isOutput {
|
if isOutput {
|
||||||
txids = append(txids, outpoint{txid, vout})
|
outpoints = append(outpoints, outpoint{txid, vout})
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
@ -534,14 +535,14 @@ func (w *Worker) GetAddressUtxo(address string) ([]AddressUtxo, error) {
|
|||||||
}
|
}
|
||||||
var lastTxid string
|
var lastTxid string
|
||||||
var ta *db.TxAddresses
|
var ta *db.TxAddresses
|
||||||
total := ba.BalanceSat
|
checksum = ba.BalanceSat
|
||||||
b, _, err := w.db.GetBestBlock()
|
b, _, err := w.db.GetBestBlock()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
bestheight := int(b)
|
bestheight := int(b)
|
||||||
for i := len(txids) - 1; i >= 0 && total.Int64() > 0; i-- {
|
for i := len(outpoints) - 1; i >= 0 && checksum.Int64() > 0; i-- {
|
||||||
o := txids[i]
|
o := outpoints[i]
|
||||||
if lastTxid != o.txid {
|
if lastTxid != o.txid {
|
||||||
ta, err = w.db.GetTxAddresses(o.txid)
|
ta, err = w.db.GetTxAddresses(o.txid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -555,20 +556,25 @@ func (w *Worker) GetAddressUtxo(address string) ([]AddressUtxo, error) {
|
|||||||
if len(ta.Outputs) <= int(o.vout) {
|
if len(ta.Outputs) <= int(o.vout) {
|
||||||
glog.Warning("DB inconsistency: txAddresses ", o.txid, " does not have enough outputs")
|
glog.Warning("DB inconsistency: txAddresses ", o.txid, " does not have enough outputs")
|
||||||
} else {
|
} else {
|
||||||
v := ta.Outputs[o.vout].ValueSat
|
if !ta.Outputs[o.vout].Spent {
|
||||||
r = append(r, AddressUtxo{
|
v := ta.Outputs[o.vout].ValueSat
|
||||||
Txid: o.txid,
|
r = append(r, AddressUtxo{
|
||||||
Vout: o.vout,
|
Txid: o.txid,
|
||||||
AmountSat: v,
|
Vout: o.vout,
|
||||||
Amount: w.chainParser.AmountToDecimalString(&v),
|
AmountSat: v,
|
||||||
Height: int(ta.Height),
|
Amount: w.chainParser.AmountToDecimalString(&v),
|
||||||
Confirmations: bestheight - int(ta.Height) + 1,
|
Height: int(ta.Height),
|
||||||
})
|
Confirmations: bestheight - int(ta.Height) + 1,
|
||||||
total.Sub(&total, &v)
|
})
|
||||||
|
checksum.Sub(&checksum, &v)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if checksum.Uint64() != 0 {
|
||||||
|
glog.Warning("DB inconsistency: ", address, ": checksum is not zero")
|
||||||
|
}
|
||||||
glog.Info("GetAddressUtxo ", address, ", ", len(r), " utxos, finished in ", time.Since(start))
|
glog.Info("GetAddressUtxo ", address, ", ", len(r), " utxos, finished in ", time.Since(start))
|
||||||
return r, nil
|
return r, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@ -637,7 +637,7 @@ func (d *RocksDB) getBlockTxs(height uint32) ([]blockTxs, error) {
|
|||||||
}
|
}
|
||||||
defer val.Free()
|
defer val.Free()
|
||||||
buf := val.Data()
|
buf := val.Data()
|
||||||
bt := make([]blockTxs, 0)
|
bt := make([]blockTxs, 0, 8)
|
||||||
for i := 0; i < len(buf); {
|
for i := 0; i < len(buf); {
|
||||||
if len(buf)-i < pl {
|
if len(buf)-i < pl {
|
||||||
glog.Error("rocksdb: Inconsistent data in blockTxs ", hex.EncodeToString(buf))
|
glog.Error("rocksdb: Inconsistent data in blockTxs ", hex.EncodeToString(buf))
|
||||||
@ -796,7 +796,7 @@ func unpackTxOutput(to *TxOutput, buf []byte) int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *RocksDB) packOutpoints(outpoints []outpoint) []byte {
|
func (d *RocksDB) packOutpoints(outpoints []outpoint) []byte {
|
||||||
buf := make([]byte, 0)
|
buf := make([]byte, 0, 32)
|
||||||
bvout := make([]byte, vlq.MaxLen32)
|
bvout := make([]byte, vlq.MaxLen32)
|
||||||
for _, o := range outpoints {
|
for _, o := range outpoints {
|
||||||
l := packVarint32(o.index, bvout)
|
l := packVarint32(o.index, bvout)
|
||||||
@ -808,7 +808,7 @@ func (d *RocksDB) packOutpoints(outpoints []outpoint) []byte {
|
|||||||
|
|
||||||
func (d *RocksDB) unpackOutpoints(buf []byte) ([]outpoint, error) {
|
func (d *RocksDB) unpackOutpoints(buf []byte) ([]outpoint, error) {
|
||||||
txidUnpackedLen := d.chainParser.PackedTxidLen()
|
txidUnpackedLen := d.chainParser.PackedTxidLen()
|
||||||
outpoints := make([]outpoint, 0)
|
outpoints := make([]outpoint, 0, 8)
|
||||||
for i := 0; i < len(buf); {
|
for i := 0; i < len(buf); {
|
||||||
btxID := append([]byte(nil), buf[i:i+txidUnpackedLen]...)
|
btxID := append([]byte(nil), buf[i:i+txidUnpackedLen]...)
|
||||||
i += txidUnpackedLen
|
i += txidUnpackedLen
|
||||||
|
|||||||
@ -210,7 +210,7 @@ type resultAddressTxids struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *SocketIoServer) getAddressTxids(addr []string, opts *addrOpts) (res resultAddressTxids, err error) {
|
func (s *SocketIoServer) getAddressTxids(addr []string, opts *addrOpts) (res resultAddressTxids, err error) {
|
||||||
txids := make([]string, 0)
|
txids := make([]string, 0, 8)
|
||||||
lower, higher := uint32(opts.End), uint32(opts.Start)
|
lower, higher := uint32(opts.End), uint32(opts.Start)
|
||||||
for _, address := range addr {
|
for _, address := range addr {
|
||||||
if !opts.QueryMempoolOnly {
|
if !opts.QueryMempoolOnly {
|
||||||
@ -381,7 +381,7 @@ func (s *SocketIoServer) getAddressHistory(addr []string, opts *addrOpts) (res r
|
|||||||
}
|
}
|
||||||
txids := txr.Result
|
txids := txr.Result
|
||||||
res.Result.TotalCount = len(txids)
|
res.Result.TotalCount = len(txids)
|
||||||
res.Result.Items = make([]addressHistoryItem, 0)
|
res.Result.Items = make([]addressHistoryItem, 0, 8)
|
||||||
to := len(txids)
|
to := len(txids)
|
||||||
if to > opts.To {
|
if to > opts.To {
|
||||||
to = opts.To
|
to = opts.To
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user