Ensure ordering of address and xpub txs in the same block
parent
3551c90590
commit
3d10d9c2c5
14
api/xpub.go
14
api/xpub.go
|
@ -34,9 +34,17 @@ type xpubTxid struct {
|
|||
|
||||
type xpubTxids []xpubTxid
|
||||
|
||||
func (a xpubTxids) Len() int { return len(a) }
|
||||
func (a xpubTxids) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||
func (a xpubTxids) Less(i, j int) bool { return a[i].height >= a[j].height }
|
||||
func (a xpubTxids) Len() int { return len(a) }
|
||||
func (a xpubTxids) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||
func (a xpubTxids) Less(i, j int) bool {
|
||||
// if the heights are equal, make inputs less than outputs
|
||||
hi := a[i].height
|
||||
hj := a[j].height
|
||||
if hi == hj {
|
||||
return (a[i].inputOutput & txInput) >= (a[j].inputOutput & txInput)
|
||||
}
|
||||
return hi > hj
|
||||
}
|
||||
|
||||
type xpubAddress struct {
|
||||
addrDesc bchain.AddressDescriptor
|
||||
|
|
|
@ -353,37 +353,44 @@ type outpoint struct {
|
|||
index int32
|
||||
}
|
||||
|
||||
// TxInput holds input data of the transaction in TxAddresses
|
||||
type TxInput struct {
|
||||
AddrDesc bchain.AddressDescriptor
|
||||
ValueSat big.Int
|
||||
}
|
||||
|
||||
// Addresses converts AddressDescriptor of the input to array of strings
|
||||
func (ti *TxInput) Addresses(p bchain.BlockChainParser) ([]string, bool, error) {
|
||||
return p.GetAddressesFromAddrDesc(ti.AddrDesc)
|
||||
}
|
||||
|
||||
// TxOutput holds output data of the transaction in TxAddresses
|
||||
type TxOutput struct {
|
||||
AddrDesc bchain.AddressDescriptor
|
||||
Spent bool
|
||||
ValueSat big.Int
|
||||
}
|
||||
|
||||
// Addresses converts AddressDescriptor of the output to array of strings
|
||||
func (to *TxOutput) Addresses(p bchain.BlockChainParser) ([]string, bool, error) {
|
||||
return p.GetAddressesFromAddrDesc(to.AddrDesc)
|
||||
}
|
||||
|
||||
// TxAddresses stores transaction inputs and outputs with amounts
|
||||
type TxAddresses struct {
|
||||
Height uint32
|
||||
Inputs []TxInput
|
||||
Outputs []TxOutput
|
||||
}
|
||||
|
||||
// AddrBalance stores number of transactions and balances of an address
|
||||
type AddrBalance struct {
|
||||
Txs uint32
|
||||
SentSat big.Int
|
||||
BalanceSat big.Int
|
||||
}
|
||||
|
||||
// ReceivedSat computes received amount from total balance and sent amount
|
||||
func (ab *AddrBalance) ReceivedSat() *big.Int {
|
||||
var r big.Int
|
||||
r.Add(&ab.BalanceSat, &ab.SentSat)
|
||||
|
@ -547,15 +554,18 @@ func (d *RocksDB) processAddressesBitcoinType(block *bchain.Block, addresses add
|
|||
return nil
|
||||
}
|
||||
|
||||
// addToAddressesMap maintains mapping between addresses and transactions in one block
|
||||
// the method assumes that outpus in the block are processed before the inputs
|
||||
// the return value is true if the tx was processed before, to not to count the tx multiple times
|
||||
func addToAddressesMap(addresses addressesMap, strAddrDesc string, btxID []byte, index int32) bool {
|
||||
// check that the address was used already in this block
|
||||
// check that the address was already processed in this block
|
||||
// if not found, it has certainly not been counted
|
||||
at, found := addresses[strAddrDesc]
|
||||
if found {
|
||||
// check that the address was already used in this tx
|
||||
// if the tx is already in the slice, append the index to the array of indexes
|
||||
for i, t := range at {
|
||||
if bytes.Equal(btxID, t.btxID) {
|
||||
at[i].indexes = append(at[i].indexes, index)
|
||||
at[i].indexes = append(t.indexes, index)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
|
|
@ -219,7 +219,7 @@ func (d *RocksDB) processAddressesEthereumType(block *bchain.Block, addresses ad
|
|||
glog.Warningf("rocksdb: GetErc20FromTx %v - height %d, tx %v, transfer %v", err, block.Height, tx.Txid, t)
|
||||
continue
|
||||
}
|
||||
if err = d.addToAddressesAndContractsEthereumType(from, btxID, ^int32(i), contract, addresses, addressContracts, true); err != nil {
|
||||
if err = d.addToAddressesAndContractsEthereumType(to, btxID, int32(i), contract, addresses, addressContracts, true); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
eq := bytes.Equal(from, to)
|
||||
|
@ -227,7 +227,7 @@ func (d *RocksDB) processAddressesEthereumType(block *bchain.Block, addresses ad
|
|||
j++
|
||||
bc.addr = from
|
||||
bc.contract = contract
|
||||
if err = d.addToAddressesAndContractsEthereumType(to, btxID, int32(i), contract, addresses, addressContracts, !eq); err != nil {
|
||||
if err = d.addToAddressesAndContractsEthereumType(from, btxID, ^int32(i), contract, addresses, addressContracts, !eq); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// add to address to blockTx.contracts only if it is different from from address
|
||||
|
|
|
@ -484,6 +484,10 @@ func TestRocksDB_Index_BitcoinType(t *testing.T) {
|
|||
verifyGetTransactions(t, d, dbtestdata.Addr8, 0, 1000000, []txidIndex{
|
||||
{dbtestdata.TxidB2T2, 0},
|
||||
}, nil)
|
||||
verifyGetTransactions(t, d, dbtestdata.Addr6, 0, 1000000, []txidIndex{
|
||||
{dbtestdata.TxidB2T2, ^0},
|
||||
{dbtestdata.TxidB2T1, 0},
|
||||
}, nil)
|
||||
verifyGetTransactions(t, d, "mtGXQvBowMkBpnhLckhxhbwYK44Gs9eBad", 500000, 1000000, []txidIndex{}, errors.New("checksum mismatch"))
|
||||
|
||||
// GetBestBlock
|
||||
|
|
Loading…
Reference in New Issue