Ensure ordering of address and xpub txs in the same block

pull/133/head
Martin Boehm 2019-03-05 13:48:11 +01:00
parent 3551c90590
commit 3d10d9c2c5
4 changed files with 30 additions and 8 deletions

View File

@ -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

View File

@ -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
}
}

View File

@ -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

View File

@ -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