Index ETH internal transactions
This commit is contained in:
parent
c374ef86fd
commit
e3bb706ea2
@ -701,9 +701,9 @@ func (w *Worker) getEthereumTypeAddressBalances(addrDesc bchain.AddressDescripto
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// filter only transactions of this contract
|
// filter only transactions of this contract
|
||||||
filter.Vout = i + 1
|
filter.Vout = i + db.ContractIndexOffset
|
||||||
}
|
}
|
||||||
t, err := w.getEthereumToken(i+1, addrDesc, c.Contract, details, int(c.Txs))
|
t, err := w.getEthereumToken(i+db.ContractIndexOffset, addrDesc, c.Contract, details, int(c.Txs))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, 0, 0, 0, err
|
return nil, nil, nil, 0, 0, 0, err
|
||||||
}
|
}
|
||||||
|
|||||||
@ -70,6 +70,7 @@ func init() {
|
|||||||
BlockChainFactories["Ethereum"] = eth.NewEthereumRPC
|
BlockChainFactories["Ethereum"] = eth.NewEthereumRPC
|
||||||
BlockChainFactories["Ethereum Classic"] = eth.NewEthereumRPC
|
BlockChainFactories["Ethereum Classic"] = eth.NewEthereumRPC
|
||||||
BlockChainFactories["Ethereum Testnet Ropsten"] = eth.NewEthereumRPC
|
BlockChainFactories["Ethereum Testnet Ropsten"] = eth.NewEthereumRPC
|
||||||
|
BlockChainFactories["Ethereum Testnet Ropsten Archive"] = eth.NewEthereumRPC
|
||||||
BlockChainFactories["Ethereum Testnet Goerli"] = eth.NewEthereumRPC
|
BlockChainFactories["Ethereum Testnet Goerli"] = eth.NewEthereumRPC
|
||||||
BlockChainFactories["Bcash"] = bch.NewBCashRPC
|
BlockChainFactories["Bcash"] = bch.NewBCashRPC
|
||||||
BlockChainFactories["Bcash Testnet"] = bch.NewBCashRPC
|
BlockChainFactories["Bcash Testnet"] = bch.NewBCashRPC
|
||||||
|
|||||||
@ -110,8 +110,11 @@ const (
|
|||||||
// BitcoinType
|
// BitcoinType
|
||||||
cfAddressBalance
|
cfAddressBalance
|
||||||
cfTxAddresses
|
cfTxAddresses
|
||||||
|
|
||||||
|
__break__
|
||||||
|
|
||||||
// EthereumType
|
// EthereumType
|
||||||
cfAddressContracts = cfAddressBalance
|
cfAddressContracts = iota - __break__ + cfAddressBalance - 1
|
||||||
cfInternalData
|
cfInternalData
|
||||||
cfContracts
|
cfContracts
|
||||||
)
|
)
|
||||||
|
|||||||
@ -3,6 +3,7 @@ package db
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
"math/big"
|
||||||
|
|
||||||
vlq "github.com/bsm/go-vlq"
|
vlq "github.com/bsm/go-vlq"
|
||||||
"github.com/flier/gorocksdb"
|
"github.com/flier/gorocksdb"
|
||||||
@ -12,6 +13,9 @@ import (
|
|||||||
"github.com/trezor/blockbook/bchain/coins/eth"
|
"github.com/trezor/blockbook/bchain/coins/eth"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const InternalTxIndexOffset = 1
|
||||||
|
const ContractIndexOffset = 2
|
||||||
|
|
||||||
// AddrContract is Contract address with number of transactions done by given address
|
// AddrContract is Contract address with number of transactions done by given address
|
||||||
type AddrContract struct {
|
type AddrContract struct {
|
||||||
Contract bchain.AddressDescriptor
|
Contract bchain.AddressDescriptor
|
||||||
@ -108,6 +112,11 @@ func isZeroAddress(addrDesc bchain.AddressDescriptor) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const transferTo = int32(0)
|
||||||
|
const transferFrom = ^int32(0)
|
||||||
|
const internalTransferTo = int32(1)
|
||||||
|
const internalTransferFrom = ^int32(1)
|
||||||
|
|
||||||
func (d *RocksDB) addToAddressesAndContractsEthereumType(addrDesc bchain.AddressDescriptor, btxID []byte, index int32, contract bchain.AddressDescriptor, addresses addressesMap, addressContracts map[string]*AddrContracts, addTxCount bool) error {
|
func (d *RocksDB) addToAddressesAndContractsEthereumType(addrDesc bchain.AddressDescriptor, btxID []byte, index int32, contract bchain.AddressDescriptor, addresses addressesMap, addressContracts map[string]*AddrContracts, addTxCount bool) error {
|
||||||
var err error
|
var err error
|
||||||
strAddrDesc := string(addrDesc)
|
strAddrDesc := string(addrDesc)
|
||||||
@ -127,7 +136,11 @@ func (d *RocksDB) addToAddressesAndContractsEthereumType(addrDesc bchain.Address
|
|||||||
}
|
}
|
||||||
if contract == nil {
|
if contract == nil {
|
||||||
if addTxCount {
|
if addTxCount {
|
||||||
ac.NonContractTxs++
|
if index == internalTransferFrom || index == internalTransferTo {
|
||||||
|
ac.InternalTxs++
|
||||||
|
} else {
|
||||||
|
ac.NonContractTxs++
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// do not store contracts for 0x0000000000000000000000000000000000000000 address
|
// do not store contracts for 0x0000000000000000000000000000000000000000 address
|
||||||
@ -138,15 +151,21 @@ func (d *RocksDB) addToAddressesAndContractsEthereumType(addrDesc bchain.Address
|
|||||||
i = len(ac.Contracts)
|
i = len(ac.Contracts)
|
||||||
ac.Contracts = append(ac.Contracts, AddrContract{Contract: contract})
|
ac.Contracts = append(ac.Contracts, AddrContract{Contract: contract})
|
||||||
}
|
}
|
||||||
// index 0 is for ETH transfers, contract indexes start with 1
|
// index 0 is for ETH transfers, index 1 (InternalTxIndexOffset) is for internal transfers, contract indexes start with 2 (ContractIndexOffset)
|
||||||
if index < 0 {
|
if index < 0 {
|
||||||
index = ^int32(i + 1)
|
index = ^int32(i + ContractIndexOffset)
|
||||||
} else {
|
} else {
|
||||||
index = int32(i + 1)
|
index = int32(i + ContractIndexOffset)
|
||||||
}
|
}
|
||||||
if addTxCount {
|
if addTxCount {
|
||||||
ac.Contracts[i].Txs++
|
ac.Contracts[i].Txs++
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if index < 0 {
|
||||||
|
index = transferFrom
|
||||||
|
} else {
|
||||||
|
index = transferTo
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
counted := addToAddressesMap(addresses, strAddrDesc, btxID, index)
|
counted := addToAddressesMap(addresses, strAddrDesc, btxID, index)
|
||||||
@ -160,10 +179,23 @@ type ethBlockTxContract struct {
|
|||||||
addr, contract bchain.AddressDescriptor
|
addr, contract bchain.AddressDescriptor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ethInternalTransfer struct {
|
||||||
|
internalType bchain.EthereumInternalTransactionType
|
||||||
|
from, to bchain.AddressDescriptor
|
||||||
|
value big.Int
|
||||||
|
}
|
||||||
|
|
||||||
|
type ethInternalData struct {
|
||||||
|
internalType bchain.EthereumInternalTransactionType
|
||||||
|
contract bchain.AddressDescriptor
|
||||||
|
transfers []ethInternalTransfer
|
||||||
|
}
|
||||||
|
|
||||||
type ethBlockTx struct {
|
type ethBlockTx struct {
|
||||||
btxID []byte
|
btxID []byte
|
||||||
from, to bchain.AddressDescriptor
|
from, to bchain.AddressDescriptor
|
||||||
contracts []ethBlockTxContract
|
contracts []ethBlockTxContract
|
||||||
|
internalData *ethInternalData
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *RocksDB) processAddressesEthereumType(block *bchain.Block, addresses addressesMap, addressContracts map[string]*AddrContracts) ([]ethBlockTx, error) {
|
func (d *RocksDB) processAddressesEthereumType(block *bchain.Block, addresses addressesMap, addressContracts map[string]*AddrContracts) ([]ethBlockTx, error) {
|
||||||
@ -184,12 +216,12 @@ func (d *RocksDB) processAddressesEthereumType(block *bchain.Block, addresses ad
|
|||||||
if err != bchain.ErrAddressMissing {
|
if err != bchain.ErrAddressMissing {
|
||||||
glog.Warningf("rocksdb: addrDesc: %v - height %d, tx %v, output", err, block.Height, tx.Txid)
|
glog.Warningf("rocksdb: addrDesc: %v - height %d, tx %v, output", err, block.Height, tx.Txid)
|
||||||
}
|
}
|
||||||
continue
|
} else {
|
||||||
|
if err = d.addToAddressesAndContractsEthereumType(to, btxID, transferTo, nil, addresses, addressContracts, true); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
blockTx.to = to
|
||||||
}
|
}
|
||||||
if err = d.addToAddressesAndContractsEthereumType(to, btxID, 0, nil, addresses, addressContracts, true); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
blockTx.to = to
|
|
||||||
}
|
}
|
||||||
// there is only one input address in EthereumType transaction, store it in format txid ^0
|
// there is only one input address in EthereumType transaction, store it in format txid ^0
|
||||||
if len(tx.Vin) == 1 && len(tx.Vin[0].Addresses) == 1 {
|
if len(tx.Vin) == 1 && len(tx.Vin[0].Addresses) == 1 {
|
||||||
@ -198,12 +230,68 @@ func (d *RocksDB) processAddressesEthereumType(block *bchain.Block, addresses ad
|
|||||||
if err != bchain.ErrAddressMissing {
|
if err != bchain.ErrAddressMissing {
|
||||||
glog.Warningf("rocksdb: addrDesc: %v - height %d, tx %v, input", err, block.Height, tx.Txid)
|
glog.Warningf("rocksdb: addrDesc: %v - height %d, tx %v, input", err, block.Height, tx.Txid)
|
||||||
}
|
}
|
||||||
continue
|
} else {
|
||||||
|
if err = d.addToAddressesAndContractsEthereumType(from, btxID, transferFrom, nil, addresses, addressContracts, !bytes.Equal(from, to)); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
blockTx.from = from
|
||||||
}
|
}
|
||||||
if err = d.addToAddressesAndContractsEthereumType(from, btxID, ^int32(0), nil, addresses, addressContracts, !bytes.Equal(from, to)); err != nil {
|
}
|
||||||
return nil, err
|
// process internal data
|
||||||
|
eid, _ := tx.CoinSpecificData.(bchain.EthereumSpecificData)
|
||||||
|
if eid.InternalData != nil {
|
||||||
|
blockTx.internalData = ðInternalData{
|
||||||
|
internalType: eid.InternalData.Type,
|
||||||
|
}
|
||||||
|
// index contract creation
|
||||||
|
if eid.InternalData.Type == bchain.CREATE {
|
||||||
|
to, err = d.chainParser.GetAddrDescFromAddress(eid.InternalData.Contract)
|
||||||
|
if err != nil {
|
||||||
|
if err != bchain.ErrAddressMissing {
|
||||||
|
glog.Warningf("rocksdb: addrDesc: %v - height %d, tx %v, create contract", err, block.Height, tx.Txid)
|
||||||
|
}
|
||||||
|
// set the internalType to CALL if incorrect contract so that it is not breaking the packing of data to DB
|
||||||
|
blockTx.internalData.internalType = bchain.CALL
|
||||||
|
} else {
|
||||||
|
blockTx.internalData.contract = to
|
||||||
|
if err = d.addToAddressesAndContractsEthereumType(to, btxID, internalTransferTo, nil, addresses, addressContracts, true); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// index internal transfers
|
||||||
|
if len(eid.InternalData.Transfers) > 0 {
|
||||||
|
blockTx.internalData.transfers = make([]ethInternalTransfer, len(eid.InternalData.Transfers))
|
||||||
|
for i := range eid.InternalData.Transfers {
|
||||||
|
iti := &eid.InternalData.Transfers[i]
|
||||||
|
ito := &blockTx.internalData.transfers[i]
|
||||||
|
to, err = d.chainParser.GetAddrDescFromAddress(iti.To)
|
||||||
|
if err != nil {
|
||||||
|
// do not log ErrAddressMissing, transactions can be without to address (for example eth contracts)
|
||||||
|
if err != bchain.ErrAddressMissing {
|
||||||
|
glog.Warningf("rocksdb: addrDesc: %v - height %d, tx %v, internal transfer %d to", err, block.Height, tx.Txid, i)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err = d.addToAddressesAndContractsEthereumType(to, btxID, internalTransferTo, nil, addresses, addressContracts, true); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ito.to = to
|
||||||
|
}
|
||||||
|
from, err = d.chainParser.GetAddrDescFromAddress(iti.From)
|
||||||
|
if err != nil {
|
||||||
|
if err != bchain.ErrAddressMissing {
|
||||||
|
glog.Warningf("rocksdb: addrDesc: %v - height %d, tx %v, internal transfer %d from", err, block.Height, tx.Txid, i)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err = d.addToAddressesAndContractsEthereumType(from, btxID, internalTransferFrom, nil, addresses, addressContracts, !bytes.Equal(from, to)); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
ito.from = from
|
||||||
|
}
|
||||||
|
ito.internalType = iti.Type
|
||||||
|
ito.value = iti.Value
|
||||||
|
}
|
||||||
}
|
}
|
||||||
blockTx.from = from
|
|
||||||
}
|
}
|
||||||
// store erc20 transfers
|
// store erc20 transfers
|
||||||
erc20, err := d.chainParser.EthereumTypeGetErc20FromTx(&tx)
|
erc20, err := d.chainParser.EthereumTypeGetErc20FromTx(&tx)
|
||||||
@ -249,14 +337,95 @@ func (d *RocksDB) processAddressesEthereumType(block *bchain.Block, addresses ad
|
|||||||
return blockTxs, nil
|
return blockTxs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var ethZeroAddress []byte = make([]byte, eth.EthereumTypeAddressDescriptorLen)
|
||||||
|
|
||||||
|
func packEthInternalData(data *ethInternalData) []byte {
|
||||||
|
// allocate enough for type+contract+all transfers with bigint value
|
||||||
|
buf := make([]byte, 0, (2*len(data.transfers)+1)*(eth.EthereumTypeAddressDescriptorLen+16))
|
||||||
|
appendAddress := func(a bchain.AddressDescriptor) {
|
||||||
|
if len(a) != eth.EthereumTypeAddressDescriptorLen {
|
||||||
|
buf = append(buf, ethZeroAddress...)
|
||||||
|
} else {
|
||||||
|
buf = append(buf, a...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
varBuf := make([]byte, maxPackedBigintBytes)
|
||||||
|
|
||||||
|
// internalType is one bit (CALL|CREATE), it is joined with count of internal transfers*2
|
||||||
|
l := packVaruint(uint(data.internalType)&1+uint(len(data.transfers))<<1, varBuf)
|
||||||
|
buf = append(buf, varBuf[:l]...)
|
||||||
|
if data.internalType == bchain.CREATE {
|
||||||
|
appendAddress(data.contract)
|
||||||
|
}
|
||||||
|
for i := range data.transfers {
|
||||||
|
t := &data.transfers[i]
|
||||||
|
buf = append(buf, byte(t.internalType))
|
||||||
|
appendAddress(t.from)
|
||||||
|
appendAddress(t.to)
|
||||||
|
l = packBigint(&t.value, varBuf)
|
||||||
|
buf = append(buf, varBuf[:l]...)
|
||||||
|
}
|
||||||
|
return buf
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *RocksDB) unpackEthInternalData(buf []byte) (*bchain.EthereumInternalData, error) {
|
||||||
|
id := bchain.EthereumInternalData{}
|
||||||
|
v, l := unpackVaruint(buf)
|
||||||
|
id.Type = bchain.EthereumInternalTransactionType(v & 1)
|
||||||
|
id.Transfers = make([]bchain.EthereumInternalTransfer, v>>1)
|
||||||
|
if id.Type == bchain.CREATE {
|
||||||
|
addresses, _, _ := d.chainParser.GetAddressesFromAddrDesc(buf[l : l+eth.EthereumTypeAddressDescriptorLen])
|
||||||
|
l += eth.EthereumTypeAddressDescriptorLen
|
||||||
|
if len(addresses) > 0 {
|
||||||
|
id.Contract = addresses[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var ll int
|
||||||
|
for i := range id.Transfers {
|
||||||
|
t := &id.Transfers[i]
|
||||||
|
t.Type = bchain.EthereumInternalTransactionType(buf[l])
|
||||||
|
l++
|
||||||
|
addresses, _, _ := d.chainParser.GetAddressesFromAddrDesc(buf[l : l+eth.EthereumTypeAddressDescriptorLen])
|
||||||
|
l += eth.EthereumTypeAddressDescriptorLen
|
||||||
|
if len(addresses) > 0 {
|
||||||
|
t.From = addresses[0]
|
||||||
|
}
|
||||||
|
addresses, _, _ = d.chainParser.GetAddressesFromAddrDesc(buf[l : l+eth.EthereumTypeAddressDescriptorLen])
|
||||||
|
l += eth.EthereumTypeAddressDescriptorLen
|
||||||
|
if len(addresses) > 0 {
|
||||||
|
t.To = addresses[0]
|
||||||
|
}
|
||||||
|
t.Value, ll = unpackBigint(buf[l:])
|
||||||
|
l += ll
|
||||||
|
}
|
||||||
|
return &id, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *RocksDB) GetEthereumInternalData(txid string) (*bchain.EthereumInternalData, error) {
|
||||||
|
btxID, err := d.chainParser.PackTxid(txid)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
val, err := d.db.GetCF(d.ro, d.cfh[cfInternalData], btxID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer val.Free()
|
||||||
|
buf := val.Data()
|
||||||
|
if len(buf) == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return d.unpackEthInternalData(buf)
|
||||||
|
}
|
||||||
|
|
||||||
func (d *RocksDB) storeAndCleanupBlockTxsEthereumType(wb *gorocksdb.WriteBatch, block *bchain.Block, blockTxs []ethBlockTx) error {
|
func (d *RocksDB) storeAndCleanupBlockTxsEthereumType(wb *gorocksdb.WriteBatch, block *bchain.Block, blockTxs []ethBlockTx) error {
|
||||||
pl := d.chainParser.PackedTxidLen()
|
pl := d.chainParser.PackedTxidLen()
|
||||||
buf := make([]byte, 0, (pl+2*eth.EthereumTypeAddressDescriptorLen)*len(blockTxs))
|
buf := make([]byte, 0, (pl+2*eth.EthereumTypeAddressDescriptorLen)*len(blockTxs))
|
||||||
varBuf := make([]byte, vlq.MaxLen64)
|
varBuf := make([]byte, vlq.MaxLen64)
|
||||||
zeroAddress := make([]byte, eth.EthereumTypeAddressDescriptorLen)
|
|
||||||
appendAddress := func(a bchain.AddressDescriptor) {
|
appendAddress := func(a bchain.AddressDescriptor) {
|
||||||
if len(a) != eth.EthereumTypeAddressDescriptorLen {
|
if len(a) != eth.EthereumTypeAddressDescriptorLen {
|
||||||
buf = append(buf, zeroAddress...)
|
buf = append(buf, ethZeroAddress...)
|
||||||
} else {
|
} else {
|
||||||
buf = append(buf, a...)
|
buf = append(buf, a...)
|
||||||
}
|
}
|
||||||
@ -266,7 +435,29 @@ func (d *RocksDB) storeAndCleanupBlockTxsEthereumType(wb *gorocksdb.WriteBatch,
|
|||||||
buf = append(buf, blockTx.btxID...)
|
buf = append(buf, blockTx.btxID...)
|
||||||
appendAddress(blockTx.from)
|
appendAddress(blockTx.from)
|
||||||
appendAddress(blockTx.to)
|
appendAddress(blockTx.to)
|
||||||
l := packVaruint(uint(len(blockTx.contracts)), varBuf)
|
// internal data - store the number of addresses, with odd number the CREATE tx type
|
||||||
|
var internalDataTransfers uint
|
||||||
|
if blockTx.internalData != nil {
|
||||||
|
wb.PutCF(d.cfh[cfInternalData], blockTx.btxID, packEthInternalData(blockTx.internalData))
|
||||||
|
internalDataTransfers = uint(len(blockTx.internalData.transfers)) * 2
|
||||||
|
if blockTx.internalData.internalType == bchain.CREATE {
|
||||||
|
internalDataTransfers++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
l := packVaruint(internalDataTransfers, varBuf)
|
||||||
|
buf = append(buf, varBuf[:l]...)
|
||||||
|
if internalDataTransfers > 0 {
|
||||||
|
if blockTx.internalData.internalType == bchain.CREATE {
|
||||||
|
appendAddress(blockTx.internalData.contract)
|
||||||
|
}
|
||||||
|
for j := range blockTx.internalData.transfers {
|
||||||
|
c := &blockTx.internalData.transfers[j]
|
||||||
|
appendAddress(c.from)
|
||||||
|
appendAddress(c.to)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// contracts - store the number of address pairs
|
||||||
|
l = packVaruint(uint(len(blockTx.contracts)), varBuf)
|
||||||
buf = append(buf, varBuf[:l]...)
|
buf = append(buf, varBuf[:l]...)
|
||||||
for j := range blockTx.contracts {
|
for j := range blockTx.contracts {
|
||||||
c := &blockTx.contracts[j]
|
c := &blockTx.contracts[j]
|
||||||
@ -323,8 +514,33 @@ func (d *RocksDB) getBlockTxsEthereumType(height uint32) ([]ethBlockTx, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
// internal data
|
||||||
|
var internalData *ethInternalData
|
||||||
cc, l := unpackVaruint(buf[i:])
|
cc, l := unpackVaruint(buf[i:])
|
||||||
i += l
|
i += l
|
||||||
|
if cc > 0 {
|
||||||
|
internalData = ðInternalData{}
|
||||||
|
// odd count of internal transfers means it is CREATE transaction with the contract added to the list
|
||||||
|
if cc&1 == 1 {
|
||||||
|
internalData.internalType = bchain.CREATE
|
||||||
|
internalData.contract, i, err = getAddress(i)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
internalData.transfers = make([]ethInternalTransfer, cc/2)
|
||||||
|
for j := range internalData.transfers {
|
||||||
|
t := &internalData.transfers[j]
|
||||||
|
t.from, i, err = getAddress(i)
|
||||||
|
t.to, i, err = getAddress(i)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// contracts
|
||||||
|
cc, l = unpackVaruint(buf[i:])
|
||||||
|
i += l
|
||||||
contracts := make([]ethBlockTxContract, cc)
|
contracts := make([]ethBlockTxContract, cc)
|
||||||
for j := range contracts {
|
for j := range contracts {
|
||||||
contracts[j].addr, i, err = getAddress(i)
|
contracts[j].addr, i, err = getAddress(i)
|
||||||
@ -337,10 +553,11 @@ func (d *RocksDB) getBlockTxsEthereumType(height uint32) ([]ethBlockTx, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
bt = append(bt, ethBlockTx{
|
bt = append(bt, ethBlockTx{
|
||||||
btxID: txid,
|
btxID: txid,
|
||||||
from: from,
|
from: from,
|
||||||
to: to,
|
to: to,
|
||||||
contracts: contracts,
|
internalData: internalData,
|
||||||
|
contracts: contracts,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return bt, nil
|
return bt, nil
|
||||||
@ -349,7 +566,7 @@ func (d *RocksDB) getBlockTxsEthereumType(height uint32) ([]ethBlockTx, error) {
|
|||||||
func (d *RocksDB) disconnectBlockTxsEthereumType(wb *gorocksdb.WriteBatch, height uint32, blockTxs []ethBlockTx, contracts map[string]*AddrContracts) error {
|
func (d *RocksDB) disconnectBlockTxsEthereumType(wb *gorocksdb.WriteBatch, height uint32, blockTxs []ethBlockTx, contracts map[string]*AddrContracts) error {
|
||||||
glog.Info("Disconnecting block ", height, " containing ", len(blockTxs), " transactions")
|
glog.Info("Disconnecting block ", height, " containing ", len(blockTxs), " transactions")
|
||||||
addresses := make(map[string]map[string]struct{})
|
addresses := make(map[string]map[string]struct{})
|
||||||
disconnectAddress := func(btxID []byte, addrDesc, contract bchain.AddressDescriptor) error {
|
disconnectAddress := func(btxID []byte, internal bool, addrDesc, contract bchain.AddressDescriptor) error {
|
||||||
var err error
|
var err error
|
||||||
// do not process empty address
|
// do not process empty address
|
||||||
if len(addrDesc) == 0 {
|
if len(addrDesc) == 0 {
|
||||||
@ -382,10 +599,18 @@ func (d *RocksDB) disconnectBlockTxsEthereumType(wb *gorocksdb.WriteBatch, heigh
|
|||||||
c.TotalTxs--
|
c.TotalTxs--
|
||||||
}
|
}
|
||||||
if contract == nil {
|
if contract == nil {
|
||||||
if c.NonContractTxs > 0 {
|
if internal {
|
||||||
c.NonContractTxs--
|
if c.InternalTxs > 0 {
|
||||||
|
c.InternalTxs--
|
||||||
|
} else {
|
||||||
|
glog.Warning("AddressContracts ", addrDesc, ", InternalTxs would be negative, tx ", hex.EncodeToString(btxID))
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
glog.Warning("AddressContracts ", addrDesc, ", EthTxs would be negative, tx ", hex.EncodeToString(btxID))
|
if c.NonContractTxs > 0 {
|
||||||
|
c.NonContractTxs--
|
||||||
|
} else {
|
||||||
|
glog.Warning("AddressContracts ", addrDesc, ", EthTxs would be negative, tx ", hex.EncodeToString(btxID))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
i, found := findContractInAddressContracts(contract, c.Contracts)
|
i, found := findContractInAddressContracts(contract, c.Contracts)
|
||||||
@ -409,21 +634,41 @@ func (d *RocksDB) disconnectBlockTxsEthereumType(wb *gorocksdb.WriteBatch, heigh
|
|||||||
}
|
}
|
||||||
for i := range blockTxs {
|
for i := range blockTxs {
|
||||||
blockTx := &blockTxs[i]
|
blockTx := &blockTxs[i]
|
||||||
if err := disconnectAddress(blockTx.btxID, blockTx.from, nil); err != nil {
|
if err := disconnectAddress(blockTx.btxID, false, blockTx.from, nil); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// if from==to, tx is counted only once and does not have to be disconnected again
|
// if from==to, tx is counted only once and does not have to be disconnected again
|
||||||
if !bytes.Equal(blockTx.from, blockTx.to) {
|
if !bytes.Equal(blockTx.from, blockTx.to) {
|
||||||
if err := disconnectAddress(blockTx.btxID, blockTx.to, nil); err != nil {
|
if err := disconnectAddress(blockTx.btxID, false, blockTx.to, nil); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if blockTx.internalData != nil {
|
||||||
|
if blockTx.internalData.internalType == bchain.CREATE {
|
||||||
|
if err := disconnectAddress(blockTx.btxID, true, blockTx.internalData.contract, nil); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for j := range blockTx.internalData.transfers {
|
||||||
|
t := &blockTx.internalData.transfers[j]
|
||||||
|
if err := disconnectAddress(blockTx.btxID, true, t.from, nil); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// if from==to, tx is counted only once and does not have to be disconnected again
|
||||||
|
if !bytes.Equal(t.from, t.to) {
|
||||||
|
if err := disconnectAddress(blockTx.btxID, true, t.to, nil); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
for _, c := range blockTx.contracts {
|
for _, c := range blockTx.contracts {
|
||||||
if err := disconnectAddress(blockTx.btxID, c.addr, c.contract); err != nil {
|
if err := disconnectAddress(blockTx.btxID, false, c.addr, c.contract); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
wb.DeleteCF(d.cfh[cfTransactions], blockTx.btxID)
|
wb.DeleteCF(d.cfh[cfTransactions], blockTx.btxID)
|
||||||
|
wb.DeleteCF(d.cfh[cfInternalData], blockTx.btxID)
|
||||||
}
|
}
|
||||||
for a := range addresses {
|
for a := range addresses {
|
||||||
key := packAddressKey([]byte(a), height)
|
key := packAddressKey([]byte(a), height)
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/juju/errors"
|
"github.com/juju/errors"
|
||||||
|
"github.com/trezor/blockbook/bchain"
|
||||||
"github.com/trezor/blockbook/bchain/coins/eth"
|
"github.com/trezor/blockbook/bchain/coins/eth"
|
||||||
"github.com/trezor/blockbook/tests/dbtestdata"
|
"github.com/trezor/blockbook/tests/dbtestdata"
|
||||||
)
|
)
|
||||||
@ -33,10 +34,11 @@ func verifyAfterEthereumTypeBlock1(t *testing.T, d *RocksDB, afterDisconnect boo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := checkColumn(d, cfAddresses, []keyPair{
|
if err := checkColumn(d, cfAddresses, []keyPair{
|
||||||
{addressKeyHex(dbtestdata.EthAddr3e, 4321000, d), txIndexesHex(dbtestdata.EthTxidB1T1, []int32{^0}), nil},
|
{addressKeyHex(dbtestdata.EthAddr3e, 4321000, d), txIndexesHex(dbtestdata.EthTxidB1T2, []int32{^1, 1, ^1}) + txIndexesHex(dbtestdata.EthTxidB1T1, []int32{^0}), nil},
|
||||||
{addressKeyHex(dbtestdata.EthAddr55, 4321000, d), txIndexesHex(dbtestdata.EthTxidB1T2, []int32{1}) + txIndexesHex(dbtestdata.EthTxidB1T1, []int32{0}), nil},
|
{addressKeyHex(dbtestdata.EthAddr55, 4321000, d), txIndexesHex(dbtestdata.EthTxidB1T2, []int32{2}) + txIndexesHex(dbtestdata.EthTxidB1T1, []int32{0}), nil},
|
||||||
{addressKeyHex(dbtestdata.EthAddr20, 4321000, d), txIndexesHex(dbtestdata.EthTxidB1T2, []int32{^0, ^1}), nil},
|
{addressKeyHex(dbtestdata.EthAddr20, 4321000, d), txIndexesHex(dbtestdata.EthTxidB1T2, []int32{^0, ^2}), nil},
|
||||||
{addressKeyHex(dbtestdata.EthAddrContract4a, 4321000, d), txIndexesHex(dbtestdata.EthTxidB1T2, []int32{0}), nil},
|
{addressKeyHex(dbtestdata.EthAddr9f, 4321000, d), txIndexesHex(dbtestdata.EthTxidB1T2, []int32{^1, 1}), nil},
|
||||||
|
{addressKeyHex(dbtestdata.EthAddrContract4a, 4321000, d), txIndexesHex(dbtestdata.EthTxidB1T2, []int32{0, 1}), nil},
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
{
|
{
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -44,10 +46,26 @@ func verifyAfterEthereumTypeBlock1(t *testing.T, d *RocksDB, afterDisconnect boo
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err := checkColumn(d, cfAddressContracts, []keyPair{
|
if err := checkColumn(d, cfAddressContracts, []keyPair{
|
||||||
{dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr3e, d.chainParser), "010100", nil},
|
{dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr3e, d.chainParser), "020102", nil},
|
||||||
{dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr55, d.chainParser), "020100" + dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddrContract4a, d.chainParser) + "01", nil},
|
{dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr55, d.chainParser), "020100" + dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddrContract4a, d.chainParser) + "01", nil},
|
||||||
{dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr20, d.chainParser), "010100" + dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddrContract4a, d.chainParser) + "01", nil},
|
{dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr20, d.chainParser), "010100" + dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddrContract4a, d.chainParser) + "01", nil},
|
||||||
{dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddrContract4a, d.chainParser), "010100", nil},
|
{dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr9f, d.chainParser), "010002", nil},
|
||||||
|
{dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddrContract4a, d.chainParser), "010101", nil},
|
||||||
|
}); err != nil {
|
||||||
|
{
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := checkColumn(d, cfInternalData, []keyPair{
|
||||||
|
{
|
||||||
|
dbtestdata.EthTxidB1T2,
|
||||||
|
"06" +
|
||||||
|
"01" + dbtestdata.EthAddr9f + dbtestdata.EthAddrContract4a + "030f4240" +
|
||||||
|
"00" + dbtestdata.EthAddr3e + dbtestdata.EthAddr9f + "030f4241" +
|
||||||
|
"00" + dbtestdata.EthAddr3e + dbtestdata.EthAddr3e + "030f4242",
|
||||||
|
nil,
|
||||||
|
},
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
{
|
{
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -62,9 +80,13 @@ func verifyAfterEthereumTypeBlock1(t *testing.T, d *RocksDB, afterDisconnect boo
|
|||||||
{
|
{
|
||||||
"0041eee8",
|
"0041eee8",
|
||||||
dbtestdata.EthTxidB1T1 +
|
dbtestdata.EthTxidB1T1 +
|
||||||
dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr3e, d.chainParser) + dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr55, d.chainParser) + "00" +
|
dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr3e, d.chainParser) + dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr55, d.chainParser) + "00" + "00" +
|
||||||
dbtestdata.EthTxidB1T2 +
|
dbtestdata.EthTxidB1T2 +
|
||||||
dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr20, d.chainParser) + dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddrContract4a, d.chainParser) +
|
dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr20, d.chainParser) + dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddrContract4a, d.chainParser) +
|
||||||
|
"06" +
|
||||||
|
dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr9f, d.chainParser) + dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddrContract4a, d.chainParser) +
|
||||||
|
dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr3e, d.chainParser) + dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr9f, d.chainParser) +
|
||||||
|
dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr3e, d.chainParser) + dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr3e, d.chainParser) +
|
||||||
"02" +
|
"02" +
|
||||||
dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr20, d.chainParser) + dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddrContract4a, d.chainParser) +
|
dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr20, d.chainParser) + dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddrContract4a, d.chainParser) +
|
||||||
dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr55, d.chainParser) + dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddrContract4a, d.chainParser),
|
dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr55, d.chainParser) + dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddrContract4a, d.chainParser),
|
||||||
@ -97,15 +119,18 @@ func verifyAfterEthereumTypeBlock2(t *testing.T, d *RocksDB) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := checkColumn(d, cfAddresses, []keyPair{
|
if err := checkColumn(d, cfAddresses, []keyPair{
|
||||||
{addressKeyHex(dbtestdata.EthAddr3e, 4321000, d), txIndexesHex(dbtestdata.EthTxidB1T1, []int32{^0}), nil},
|
{addressKeyHex(dbtestdata.EthAddr3e, 4321000, d), txIndexesHex(dbtestdata.EthTxidB1T2, []int32{^1, 1, ^1}) + txIndexesHex(dbtestdata.EthTxidB1T1, []int32{^0}), nil},
|
||||||
{addressKeyHex(dbtestdata.EthAddr55, 4321000, d), txIndexesHex(dbtestdata.EthTxidB1T2, []int32{1}) + txIndexesHex(dbtestdata.EthTxidB1T1, []int32{0}), nil},
|
{addressKeyHex(dbtestdata.EthAddr55, 4321000, d), txIndexesHex(dbtestdata.EthTxidB1T2, []int32{2}) + txIndexesHex(dbtestdata.EthTxidB1T1, []int32{0}), nil},
|
||||||
{addressKeyHex(dbtestdata.EthAddr20, 4321000, d), txIndexesHex(dbtestdata.EthTxidB1T2, []int32{^0, ^1}), nil},
|
{addressKeyHex(dbtestdata.EthAddr20, 4321000, d), txIndexesHex(dbtestdata.EthTxidB1T2, []int32{^0, ^2}), nil},
|
||||||
{addressKeyHex(dbtestdata.EthAddrContract4a, 4321000, d), txIndexesHex(dbtestdata.EthTxidB1T2, []int32{0}), nil},
|
{addressKeyHex(dbtestdata.EthAddr9f, 4321000, d), txIndexesHex(dbtestdata.EthTxidB1T2, []int32{^1, 1}), nil},
|
||||||
{addressKeyHex(dbtestdata.EthAddr55, 4321001, d), txIndexesHex(dbtestdata.EthTxidB2T2, []int32{^2, 1}) + txIndexesHex(dbtestdata.EthTxidB2T1, []int32{^0}), nil},
|
{addressKeyHex(dbtestdata.EthAddrContract4a, 4321000, d), txIndexesHex(dbtestdata.EthTxidB1T2, []int32{0, 1}), nil},
|
||||||
{addressKeyHex(dbtestdata.EthAddr9f, 4321001, d), txIndexesHex(dbtestdata.EthTxidB2T1, []int32{0}), nil},
|
{addressKeyHex(dbtestdata.EthAddr55, 4321001, d), txIndexesHex(dbtestdata.EthTxidB2T2, []int32{^3, 2}) + txIndexesHex(dbtestdata.EthTxidB2T1, []int32{^0}), nil},
|
||||||
{addressKeyHex(dbtestdata.EthAddr4b, 4321001, d), txIndexesHex(dbtestdata.EthTxidB2T2, []int32{^0, 1, ^2, 2, ^1}), nil},
|
{addressKeyHex(dbtestdata.EthAddr9f, 4321001, d), txIndexesHex(dbtestdata.EthTxidB2T2, []int32{1, 1}) + txIndexesHex(dbtestdata.EthTxidB2T1, []int32{0}), nil},
|
||||||
{addressKeyHex(dbtestdata.EthAddr7b, 4321001, d), txIndexesHex(dbtestdata.EthTxidB2T2, []int32{^1, 2}), nil},
|
{addressKeyHex(dbtestdata.EthAddr4b, 4321001, d), txIndexesHex(dbtestdata.EthTxidB2T2, []int32{^0, ^1, 2, ^3, 3, ^2}), nil},
|
||||||
|
{addressKeyHex(dbtestdata.EthAddr7b, 4321001, d), txIndexesHex(dbtestdata.EthTxidB2T2, []int32{^2, 3}), nil},
|
||||||
|
{addressKeyHex(dbtestdata.EthAddrContract0d, 4321001, d), txIndexesHex(dbtestdata.EthTxidB2T2, []int32{1}), nil},
|
||||||
{addressKeyHex(dbtestdata.EthAddrContract47, 4321001, d), txIndexesHex(dbtestdata.EthTxidB2T2, []int32{0}), nil},
|
{addressKeyHex(dbtestdata.EthAddrContract47, 4321001, d), txIndexesHex(dbtestdata.EthTxidB2T2, []int32{0}), nil},
|
||||||
|
{addressKeyHex(dbtestdata.EthAddrContract4a, 4321001, d), txIndexesHex(dbtestdata.EthTxidB2T2, []int32{^1}), nil},
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
{
|
{
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -113,13 +138,14 @@ func verifyAfterEthereumTypeBlock2(t *testing.T, d *RocksDB) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err := checkColumn(d, cfAddressContracts, []keyPair{
|
if err := checkColumn(d, cfAddressContracts, []keyPair{
|
||||||
{dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr3e, d.chainParser), "010100", nil},
|
{dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr3e, d.chainParser), "020102", nil},
|
||||||
{dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr55, d.chainParser), "040200" + dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddrContract4a, d.chainParser) + "02" + dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddrContract0d, d.chainParser) + "01", nil},
|
{dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr55, d.chainParser), "040200" + dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddrContract4a, d.chainParser) + "02" + dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddrContract0d, d.chainParser) + "01", nil},
|
||||||
{dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr20, d.chainParser), "010100" + dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddrContract4a, d.chainParser) + "01", nil},
|
{dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr20, d.chainParser), "010100" + dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddrContract4a, d.chainParser) + "01", nil},
|
||||||
{dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddrContract4a, d.chainParser), "010100", nil},
|
{dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddrContract4a, d.chainParser), "020102", nil},
|
||||||
{dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr9f, d.chainParser), "010100", nil},
|
{dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr9f, d.chainParser), "030104", nil},
|
||||||
{dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr4b, d.chainParser), "010100" + dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddrContract0d, d.chainParser) + "02" + dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddrContract4a, d.chainParser) + "02", nil},
|
{dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr4b, d.chainParser), "010101" + dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddrContract0d, d.chainParser) + "02" + dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddrContract4a, d.chainParser) + "02", nil},
|
||||||
{dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr7b, d.chainParser), "010000" + dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddrContract4a, d.chainParser) + "01" + dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddrContract0d, d.chainParser) + "01", nil},
|
{dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr7b, d.chainParser), "010000" + dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddrContract4a, d.chainParser) + "01" + dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddrContract0d, d.chainParser) + "01", nil},
|
||||||
|
{dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddrContract0d, d.chainParser), "010001", nil},
|
||||||
{dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddrContract47, d.chainParser), "010100", nil},
|
{dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddrContract47, d.chainParser), "010100", nil},
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
{
|
{
|
||||||
@ -127,13 +153,39 @@ func verifyAfterEthereumTypeBlock2(t *testing.T, d *RocksDB) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := checkColumn(d, cfInternalData, []keyPair{
|
||||||
|
{
|
||||||
|
dbtestdata.EthTxidB1T2,
|
||||||
|
"06" +
|
||||||
|
"01" + dbtestdata.EthAddr9f + dbtestdata.EthAddrContract4a + "030f4240" +
|
||||||
|
"00" + dbtestdata.EthAddr3e + dbtestdata.EthAddr9f + "030f4241" +
|
||||||
|
"00" + dbtestdata.EthAddr3e + dbtestdata.EthAddr3e + "030f4242",
|
||||||
|
nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
dbtestdata.EthTxidB2T2,
|
||||||
|
"05" + dbtestdata.EthAddrContract0d +
|
||||||
|
"00" + dbtestdata.EthAddr4b + dbtestdata.EthAddr9f + "030f424a" +
|
||||||
|
"02" + dbtestdata.EthAddrContract4a + dbtestdata.EthAddr9f + "030f424b",
|
||||||
|
nil,
|
||||||
|
},
|
||||||
|
}); err != nil {
|
||||||
|
{
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if err := checkColumn(d, cfBlockTxs, []keyPair{
|
if err := checkColumn(d, cfBlockTxs, []keyPair{
|
||||||
{
|
{
|
||||||
"0041eee9",
|
"0041eee9",
|
||||||
dbtestdata.EthTxidB2T1 +
|
dbtestdata.EthTxidB2T1 +
|
||||||
dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr55, d.chainParser) + dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr9f, d.chainParser) + "00" +
|
dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr55, d.chainParser) + dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr9f, d.chainParser) + "00" + "00" +
|
||||||
dbtestdata.EthTxidB2T2 +
|
dbtestdata.EthTxidB2T2 +
|
||||||
dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr4b, d.chainParser) + dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddrContract47, d.chainParser) +
|
dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr4b, d.chainParser) + dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddrContract47, d.chainParser) +
|
||||||
|
"05" +
|
||||||
|
dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddrContract0d, d.chainParser) +
|
||||||
|
dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr4b, d.chainParser) + dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr9f, d.chainParser) +
|
||||||
|
dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddrContract4a, d.chainParser) + dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr9f, d.chainParser) +
|
||||||
"08" +
|
"08" +
|
||||||
dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr55, d.chainParser) + dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddrContract0d, d.chainParser) +
|
dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr55, d.chainParser) + dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddrContract0d, d.chainParser) +
|
||||||
dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr4b, d.chainParser) + dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddrContract0d, d.chainParser) +
|
dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr4b, d.chainParser) + dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddrContract0d, d.chainParser) +
|
||||||
@ -152,6 +204,19 @@ func verifyAfterEthereumTypeBlock2(t *testing.T, d *RocksDB) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func formatInternalData(in *bchain.EthereumInternalData) *bchain.EthereumInternalData {
|
||||||
|
out := *in
|
||||||
|
if out.Type == bchain.CREATE {
|
||||||
|
out.Contract = eth.EIP55AddressFromAddress(out.Contract)
|
||||||
|
}
|
||||||
|
for i := range out.Transfers {
|
||||||
|
t := &out.Transfers[i]
|
||||||
|
t.From = eth.EIP55AddressFromAddress(t.From)
|
||||||
|
t.To = eth.EIP55AddressFromAddress(t.To)
|
||||||
|
}
|
||||||
|
return &out
|
||||||
|
}
|
||||||
|
|
||||||
// TestRocksDB_Index_EthereumType is an integration test probing the whole indexing functionality for EthereumType chains
|
// TestRocksDB_Index_EthereumType is an integration test probing the whole indexing functionality for EthereumType chains
|
||||||
// It does the following:
|
// It does the following:
|
||||||
// 1) Connect two blocks (inputs from 2nd block are spending some outputs from the 1st block)
|
// 1) Connect two blocks (inputs from 2nd block are spending some outputs from the 1st block)
|
||||||
@ -195,14 +260,27 @@ func TestRocksDB_Index_EthereumType(t *testing.T) {
|
|||||||
|
|
||||||
// get transactions for various addresses / low-high ranges
|
// get transactions for various addresses / low-high ranges
|
||||||
verifyGetTransactions(t, d, "0x"+dbtestdata.EthAddr55, 0, 10000000, []txidIndex{
|
verifyGetTransactions(t, d, "0x"+dbtestdata.EthAddr55, 0, 10000000, []txidIndex{
|
||||||
{"0x" + dbtestdata.EthTxidB2T2, ^2},
|
{"0x" + dbtestdata.EthTxidB2T2, ^3},
|
||||||
{"0x" + dbtestdata.EthTxidB2T2, 1},
|
{"0x" + dbtestdata.EthTxidB2T2, 2},
|
||||||
{"0x" + dbtestdata.EthTxidB2T1, ^0},
|
{"0x" + dbtestdata.EthTxidB2T1, ^0},
|
||||||
{"0x" + dbtestdata.EthTxidB1T2, 1},
|
{"0x" + dbtestdata.EthTxidB1T2, 2},
|
||||||
{"0x" + dbtestdata.EthTxidB1T1, 0},
|
{"0x" + dbtestdata.EthTxidB1T1, 0},
|
||||||
}, nil)
|
}, nil)
|
||||||
verifyGetTransactions(t, d, "mtGXQvBowMkBpnhLckhxhbwYK44Gs9eBad", 500000, 1000000, []txidIndex{}, errors.New("Address missing"))
|
verifyGetTransactions(t, d, "mtGXQvBowMkBpnhLckhxhbwYK44Gs9eBad", 500000, 1000000, []txidIndex{}, errors.New("Address missing"))
|
||||||
|
|
||||||
|
id, err := d.GetEthereumInternalData(dbtestdata.EthTxidB1T1)
|
||||||
|
if err != nil || id != nil {
|
||||||
|
t.Errorf("GetEthereumInternalData(%s) = %+v, want %+v, err %v", dbtestdata.EthTxidB1T1, id, nil, err)
|
||||||
|
}
|
||||||
|
id, err = d.GetEthereumInternalData(dbtestdata.EthTxidB1T2)
|
||||||
|
if err != nil || !reflect.DeepEqual(id, formatInternalData(dbtestdata.EthTx2InternalData)) {
|
||||||
|
t.Errorf("GetEthereumInternalData(%s) = %+v, want %+v, err %v", dbtestdata.EthTxidB1T2, id, formatInternalData(dbtestdata.EthTx2InternalData), err)
|
||||||
|
}
|
||||||
|
id, err = d.GetEthereumInternalData(dbtestdata.EthTxidB2T2)
|
||||||
|
if err != nil || !reflect.DeepEqual(id, formatInternalData(dbtestdata.EthTx4InternalData)) {
|
||||||
|
t.Errorf("GetEthereumInternalData(%s) = %+v, want %+v, err %v", dbtestdata.EthTxidB2T2, id, formatInternalData(dbtestdata.EthTx4InternalData), err)
|
||||||
|
}
|
||||||
|
|
||||||
// GetBestBlock
|
// GetBestBlock
|
||||||
height, hash, err := d.GetBestBlock()
|
height, hash, err := d.GetBestBlock()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user