Update types in preparation for eth internal transactions,

bump dbVersion to 6
This commit is contained in:
Martin Boehm 2021-12-10 00:30:27 +01:00 committed by Martin
parent 5818ce8aa2
commit c374ef86fd
13 changed files with 185 additions and 154 deletions

View File

@ -173,12 +173,14 @@ type TokenTransfer struct {
// EthereumSpecific contains ethereum specific transaction data
type EthereumSpecific struct {
Status eth.TxStatus `json:"status"` // 1 OK, 0 Fail, -1 pending
Nonce uint64 `json:"nonce"`
GasLimit *big.Int `json:"gasLimit"`
GasUsed *big.Int `json:"gasUsed"`
GasPrice *Amount `json:"gasPrice"`
Data string `json:"data,omitempty"`
TxType string `json:"txType,omitempty"`
Status eth.TxStatus `json:"status"` // 1 OK, 0 Fail, -1 pending
Nonce uint64 `json:"nonce"`
GasLimit *big.Int `json:"gasLimit"`
GasUsed *big.Int `json:"gasUsed"`
GasPrice *Amount `json:"gasPrice"`
Data string `json:"data,omitempty"`
InternalTransfers []bchain.EthereumInternalTransfer `json:"internalTransfers,omitempty"`
}
// Tx holds information about a transaction

View File

@ -56,7 +56,7 @@ func addressFromPaddedHex(s string) (string, error) {
return a.String(), nil
}
func erc20GetTransfersFromLog(logs []*rpcLog) ([]bchain.Erc20Transfer, error) {
func erc20GetTransfersFromLog(logs []*bchain.RpcLog) ([]bchain.Erc20Transfer, error) {
var r []bchain.Erc20Transfer
for _, l := range logs {
if len(l.Topics) == 3 && l.Topics[0] == erc20TransferEventSignature {
@ -84,7 +84,7 @@ func erc20GetTransfersFromLog(logs []*rpcLog) ([]bchain.Erc20Transfer, error) {
return r, nil
}
func erc20GetTransfersFromTx(tx *rpcTransaction) ([]bchain.Erc20Transfer, error) {
func erc20GetTransfersFromTx(tx *bchain.RpcTransaction) ([]bchain.Erc20Transfer, error) {
var r []bchain.Erc20Transfer
if len(tx.Payload) == 128+len(erc20TransferMethodSignature) && strings.HasPrefix(tx.Payload, erc20TransferMethodSignature) {
to, err := addressFromPaddedHex(tx.Payload[len(erc20TransferMethodSignature) : 64+len(erc20TransferMethodSignature)])

View File

@ -15,13 +15,13 @@ import (
func TestErc20_erc20GetTransfersFromLog(t *testing.T) {
tests := []struct {
name string
args []*rpcLog
args []*bchain.RpcLog
want []bchain.Erc20Transfer
wantErr bool
}{
{
name: "1",
args: []*rpcLog{
args: []*bchain.RpcLog{
{
Address: "0x76a45e8976499ab9ae223cc584019341d5a84e96",
Topics: []string{
@ -43,7 +43,7 @@ func TestErc20_erc20GetTransfersFromLog(t *testing.T) {
},
{
name: "2",
args: []*rpcLog{
args: []*bchain.RpcLog{
{ // Transfer
Address: "0x0d0f936ee4c93e25944694d6c121de94d9760f11",
Topics: []string{
@ -167,17 +167,17 @@ func TestErc20_erc20GetTransfersFromTx(t *testing.T) {
bn, _ := new(big.Int).SetString("21e19e0c9bab2400000", 16)
tests := []struct {
name string
args *rpcTransaction
args *bchain.RpcTransaction
want []bchain.Erc20Transfer
}{
{
name: "0",
args: (b.Txs[0].CoinSpecificData.(completeTransaction)).Tx,
args: (b.Txs[0].CoinSpecificData.(bchain.EthereumSpecificData)).Tx,
want: []bchain.Erc20Transfer{},
},
{
name: "1",
args: (b.Txs[1].CoinSpecificData.(completeTransaction)).Tx,
args: (b.Txs[1].CoinSpecificData.(bchain.EthereumSpecificData)).Tx,
want: []bchain.Erc20Transfer{
{
Contract: "0x4af4114f73d1c1c903ac9e0361b379d1291808a2",

View File

@ -41,49 +41,13 @@ type rpcHeader struct {
Nonce string `json:"nonce"`
}
type rpcTransaction struct {
AccountNonce string `json:"nonce"`
GasPrice string `json:"gasPrice"`
GasLimit string `json:"gas"`
To string `json:"to"` // nil means contract creation
Value string `json:"value"`
Payload string `json:"input"`
Hash string `json:"hash"`
BlockNumber string `json:"blockNumber"`
BlockHash string `json:"blockHash,omitempty"`
From string `json:"from"`
TransactionIndex string `json:"transactionIndex"`
// Signature values - ignored
// V string `json:"v"`
// R string `json:"r"`
// S string `json:"s"`
}
type rpcLog struct {
Address string `json:"address"`
Topics []string `json:"topics"`
Data string `json:"data"`
}
type rpcLogWithTxHash struct {
rpcLog
bchain.RpcLog
Hash string `json:"transactionHash"`
}
type rpcReceipt struct {
GasUsed string `json:"gasUsed"`
Status string `json:"status"`
Logs []*rpcLog `json:"logs"`
}
type completeTransaction struct {
Tx *rpcTransaction `json:"tx"`
InternalData *bchain.EthereumInternalData `json:"internalData,omitempty"`
Receipt *rpcReceipt `json:"receipt,omitempty"`
}
type rpcBlockTransactions struct {
Transactions []rpcTransaction `json:"transactions"`
Transactions []bchain.RpcTransaction `json:"transactions"`
}
type rpcBlockTxids struct {
@ -97,7 +61,7 @@ func ethNumber(n string) (int64, error) {
return 0, errors.Errorf("Not a number: '%v'", n)
}
func (p *EthereumParser) ethTxToTx(tx *rpcTransaction, receipt *rpcReceipt, internalData *bchain.EthereumInternalData, blocktime int64, confirmations uint32, fixEIP55 bool) (*bchain.Tx, error) {
func (p *EthereumParser) ethTxToTx(tx *bchain.RpcTransaction, receipt *bchain.RpcReceipt, internalData *bchain.EthereumInternalData, blocktime int64, confirmations uint32, fixEIP55 bool) (*bchain.Tx, error) {
txid := tx.Hash
var (
fa, ta []string
@ -136,7 +100,7 @@ func (p *EthereumParser) ethTxToTx(tx *rpcTransaction, receipt *rpcReceipt, inte
}
}
}
ct := completeTransaction{
ct := bchain.EthereumSpecificData{
Tx: tx,
InternalData: internalData,
Receipt: receipt,
@ -274,7 +238,7 @@ func hexEncodeBig(b []byte) string {
func (p *EthereumParser) PackTx(tx *bchain.Tx, height uint32, blockTime int64) ([]byte, error) {
var err error
var n uint64
r, ok := tx.CoinSpecificData.(completeTransaction)
r, ok := tx.CoinSpecificData.(bchain.EthereumSpecificData)
if !ok {
return nil, errors.New("Missing CoinSpecificData")
}
@ -373,7 +337,7 @@ func (p *EthereumParser) UnpackTx(buf []byte) (*bchain.Tx, uint32, error) {
if err != nil {
return nil, 0, err
}
rt := rpcTransaction{
rt := bchain.RpcTransaction{
AccountNonce: hexutil.EncodeUint64(pt.Tx.AccountNonce),
BlockNumber: hexutil.EncodeUint64(uint64(pt.BlockNumber)),
From: EIP55Address(pt.Tx.From),
@ -388,15 +352,15 @@ func (p *EthereumParser) UnpackTx(buf []byte) (*bchain.Tx, uint32, error) {
TransactionIndex: hexutil.EncodeUint64(uint64(pt.Tx.TransactionIndex)),
Value: hexEncodeBig(pt.Tx.Value),
}
var rr *rpcReceipt
var rr *bchain.RpcReceipt
if pt.Receipt != nil {
logs := make([]*rpcLog, len(pt.Receipt.Log))
logs := make([]*bchain.RpcLog, len(pt.Receipt.Log))
for i, l := range pt.Receipt.Log {
topics := make([]string, len(l.Topics))
for j, t := range l.Topics {
topics[j] = hexutil.Encode(t)
}
logs[i] = &rpcLog{
logs[i] = &bchain.RpcLog{
Address: EIP55Address(l.Address),
Data: hexutil.Encode(l.Data),
Topics: topics,
@ -407,7 +371,7 @@ func (p *EthereumParser) UnpackTx(buf []byte) (*bchain.Tx, uint32, error) {
if len(pt.Receipt.Status) != 1 || pt.Receipt.Status[0] != 'U' {
status = hexEncodeBig(pt.Receipt.Status)
}
rr = &rpcReceipt{
rr = &bchain.RpcReceipt{
GasUsed: hexEncodeBig(pt.Receipt.GasUsed),
Status: status,
Logs: logs,
@ -460,7 +424,7 @@ func (p *EthereumParser) GetChainType() bchain.ChainType {
// GetHeightFromTx returns ethereum specific data from bchain.Tx
func GetHeightFromTx(tx *bchain.Tx) (uint32, error) {
var bn string
csd, ok := tx.CoinSpecificData.(completeTransaction)
csd, ok := tx.CoinSpecificData.(bchain.EthereumSpecificData)
if !ok {
return 0, errors.New("Missing CoinSpecificData")
}
@ -476,7 +440,7 @@ func GetHeightFromTx(tx *bchain.Tx) (uint32, error) {
func (p *EthereumParser) EthereumTypeGetErc20FromTx(tx *bchain.Tx) ([]bchain.Erc20Transfer, error) {
var r []bchain.Erc20Transfer
var err error
csd, ok := tx.CoinSpecificData.(completeTransaction)
csd, ok := tx.CoinSpecificData.(bchain.EthereumSpecificData)
if ok {
if csd.Receipt != nil {
r, err = erc20GetTransfersFromLog(csd.Receipt.Logs)
@ -519,7 +483,7 @@ func GetEthereumTxData(tx *bchain.Tx) *EthereumTxData {
// GetEthereumTxDataFromSpecificData returns EthereumTxData from coinSpecificData
func GetEthereumTxDataFromSpecificData(coinSpecificData interface{}) *EthereumTxData {
etd := EthereumTxData{Status: TxStatusPending}
csd, ok := coinSpecificData.(completeTransaction)
csd, ok := coinSpecificData.(bchain.EthereumSpecificData)
if ok {
if csd.Tx != nil {
etd.Nonce, _ = hexutil.DecodeUint64(csd.Tx.AccountNonce)

View File

@ -89,8 +89,8 @@ func init() {
},
},
},
CoinSpecificData: completeTransaction{
Tx: &rpcTransaction{
CoinSpecificData: bchain.EthereumSpecificData{
Tx: &bchain.RpcTransaction{
AccountNonce: "0xb26c",
GasPrice: "0x430e23400",
GasLimit: "0x5208",
@ -102,10 +102,10 @@ func init() {
From: "0x3E3a3D69dc66bA10737F531ed088954a9EC89d97",
TransactionIndex: "0xa",
},
Receipt: &rpcReceipt{
Receipt: &bchain.RpcReceipt{
GasUsed: "0x5208",
Status: "0x1",
Logs: []*rpcLog{},
Logs: []*bchain.RpcLog{},
},
},
}
@ -127,8 +127,8 @@ func init() {
},
},
},
CoinSpecificData: completeTransaction{
Tx: &rpcTransaction{
CoinSpecificData: bchain.EthereumSpecificData{
Tx: &bchain.RpcTransaction{
AccountNonce: "0xd0",
GasPrice: "0x9502f9000",
GasLimit: "0x130d5",
@ -139,10 +139,10 @@ func init() {
BlockNumber: "0x41eee8",
From: "0x20cD153de35D469BA46127A0C8F18626b59a256A",
TransactionIndex: "0x0"},
Receipt: &rpcReceipt{
Receipt: &bchain.RpcReceipt{
GasUsed: "0xcb39",
Status: "0x1",
Logs: []*rpcLog{
Logs: []*bchain.RpcLog{
{
Address: "0x4af4114F73d1c1C903aC9E0361b379D1291808A2",
Data: "0x00000000000000000000000000000000000000000000021e19e0c9bab2400000",
@ -174,8 +174,8 @@ func init() {
},
},
},
CoinSpecificData: completeTransaction{
Tx: &rpcTransaction{
CoinSpecificData: bchain.EthereumSpecificData{
Tx: &bchain.RpcTransaction{
AccountNonce: "0xb26c",
GasPrice: "0x430e23400",
GasLimit: "0x5208",
@ -187,10 +187,10 @@ func init() {
From: "0x3E3a3D69dc66bA10737F531ed088954a9EC89d97",
TransactionIndex: "0xa",
},
Receipt: &rpcReceipt{
Receipt: &bchain.RpcReceipt{
GasUsed: "0x5208",
Status: "0x0",
Logs: []*rpcLog{},
Logs: []*bchain.RpcLog{},
},
},
}
@ -212,8 +212,8 @@ func init() {
},
},
},
CoinSpecificData: completeTransaction{
Tx: &rpcTransaction{
CoinSpecificData: bchain.EthereumSpecificData{
Tx: &bchain.RpcTransaction{
AccountNonce: "0xb26c",
GasPrice: "0x430e23400",
GasLimit: "0x5208",
@ -225,10 +225,10 @@ func init() {
From: "0x3E3a3D69dc66bA10737F531ed088954a9EC89d97",
TransactionIndex: "0xa",
},
Receipt: &rpcReceipt{
Receipt: &bchain.RpcReceipt{
GasUsed: "0x5208",
Status: "",
Logs: []*rpcLog{},
Logs: []*bchain.RpcLog{},
},
},
}
@ -351,8 +351,8 @@ func TestEthereumParser_UnpackTx(t *testing.T) {
return
}
// DeepEqual has problems with pointers in completeTransaction
gs := got.CoinSpecificData.(completeTransaction)
ws := tt.want.CoinSpecificData.(completeTransaction)
gs := got.CoinSpecificData.(bchain.EthereumSpecificData)
ws := tt.want.CoinSpecificData.(bchain.EthereumSpecificData)
gc := *got
wc := *tt.want
gc.CoinSpecificData = nil

View File

@ -490,7 +490,7 @@ func (b *EthereumRPC) getBlockRaw(hash string, height uint32, fullTxs bool) (jso
return raw, nil
}
func (b *EthereumRPC) getERC20EventsForBlock(blockNumber string) (map[string][]*rpcLog, error) {
func (b *EthereumRPC) getERC20EventsForBlock(blockNumber string) (map[string][]*bchain.RpcLog, error) {
ctx, cancel := context.WithTimeout(context.Background(), b.timeout)
defer cancel()
var logs []rpcLogWithTxHash
@ -502,10 +502,10 @@ func (b *EthereumRPC) getERC20EventsForBlock(blockNumber string) (map[string][]*
if err != nil {
return nil, errors.Annotatef(err, "blockNumber %v", blockNumber)
}
r := make(map[string][]*rpcLog)
r := make(map[string][]*bchain.RpcLog)
for i := range logs {
l := &logs[i]
r[l.Hash] = append(r[l.Hash], &l.rpcLog)
r[l.Hash] = append(r[l.Hash], &l.RpcLog)
}
return r, nil
}
@ -555,7 +555,7 @@ func (b *EthereumRPC) processCallTrace(call rpcCallTrace, d *bchain.EthereumInte
// getInternalDataForBlock fetches debug trace using callTracer, extracts internal transfers and creations and destructions of contracts
// by design, it never returns error so that missing internal transactions do not stop the rest of the blockchain import
func (b *EthereumRPC) getInternalDataForBlock(blockHash string, transactions []rpcTransaction) ([]bchain.EthereumInternalData, error) {
func (b *EthereumRPC) getInternalDataForBlock(blockHash string, transactions []bchain.RpcTransaction) ([]bchain.EthereumInternalData, error) {
data := make([]bchain.EthereumInternalData, len(transactions))
if b.ChainConfig.ProcessInternalTransactions {
ctx, cancel := context.WithTimeout(context.Background(), b.timeout)
@ -619,7 +619,7 @@ func (b *EthereumRPC) GetBlock(hash string, height uint32) (*bchain.Block, error
btxs := make([]bchain.Tx, len(body.Transactions))
for i := range body.Transactions {
tx := &body.Transactions[i]
btx, err := b.Parser.ethTxToTx(tx, &rpcReceipt{Logs: logs[tx.Hash]}, &internalData[i], bbh.Time, uint32(bbh.Confirmations), true)
btx, err := b.Parser.ethTxToTx(tx, &bchain.RpcReceipt{Logs: logs[tx.Hash]}, &internalData[i], bbh.Time, uint32(bbh.Confirmations), true)
if err != nil {
return nil, errors.Annotatef(err, "hash %v, height %v, txid %v", hash, height, tx.Hash)
}
@ -671,7 +671,7 @@ func (b *EthereumRPC) GetTransactionForMempool(txid string) (*bchain.Tx, error)
func (b *EthereumRPC) GetTransaction(txid string) (*bchain.Tx, error) {
ctx, cancel := context.WithTimeout(context.Background(), b.timeout)
defer cancel()
var tx *rpcTransaction
var tx *bchain.RpcTransaction
hash := ethcommon.HexToHash(txid)
err := b.rpc.CallContext(ctx, &tx, "eth_getTransactionByHash", hash)
if err != nil {
@ -705,7 +705,7 @@ func (b *EthereumRPC) GetTransaction(txid string) (*bchain.Tx, error) {
if time, err = ethNumber(ht.Time); err != nil {
return nil, errors.Annotatef(err, "txid %v", txid)
}
var receipt rpcReceipt
var receipt bchain.RpcReceipt
err = b.rpc.CallContext(ctx, &receipt, "eth_getTransactionReceipt", hash)
if err != nil {
return nil, errors.Annotatef(err, "txid %v", txid)
@ -733,13 +733,13 @@ func (b *EthereumRPC) GetTransaction(txid string) (*bchain.Tx, error) {
// GetTransactionSpecific returns json as returned by backend, with all coin specific data
func (b *EthereumRPC) GetTransactionSpecific(tx *bchain.Tx) (json.RawMessage, error) {
csd, ok := tx.CoinSpecificData.(completeTransaction)
csd, ok := tx.CoinSpecificData.(bchain.EthereumSpecificData)
if !ok {
ntx, err := b.GetTransaction(tx.Txid)
if err != nil {
return nil, err
}
csd, ok = ntx.CoinSpecificData.(completeTransaction)
csd, ok = ntx.CoinSpecificData.(bchain.EthereumSpecificData)
if !ok {
return nil, errors.New("Cannot get CoinSpecificData")
}

View File

@ -200,49 +200,6 @@ func AddressDescriptorFromString(s string) (AddressDescriptor, error) {
return nil, errors.New("invalid address descriptor")
}
// EthereumType specific
// EthereumInternalTransfer contains data about internal transfer
type EthereumInternalTransfer struct {
Type EthereumInternalTransactionType `json:"type"`
From string `json:"from"`
To string `json:"to"`
Value big.Int `json:"value"`
}
// EthereumInternalTransactionType - type of ethereum transaction from internal data
type EthereumInternalTransactionType int
// EthereumInternalTransactionType enumeration
const (
CALL = EthereumInternalTransactionType(iota)
CREATE
SELFDESTRUCT
)
// EthereumInternalTransaction contains internal transfers
type EthereumInternalData struct {
Type EthereumInternalTransactionType `json:"type"`
Contract string `json:"contract,omitempty"`
Transfers []EthereumInternalTransfer `json:"transfers,omitempty"`
}
// Erc20Contract contains info about ERC20 contract
type Erc20Contract struct {
Contract string `json:"contract"`
Name string `json:"name"`
Symbol string `json:"symbol"`
Decimals int `json:"decimals"`
}
// Erc20Transfer contains a single ERC20 token transfer
type Erc20Transfer struct {
Contract string
From string
To string
Tokens big.Int
}
// MempoolTxidEntry contains mempool txid with first seen time
type MempoolTxidEntry struct {
Txid string

View File

@ -0,0 +1,85 @@
package bchain
import "math/big"
// EthereumType specific
// EthereumInternalTransfer contains data about internal transfer
type EthereumInternalTransfer struct {
Type EthereumInternalTransactionType `json:"type"`
From string `json:"from"`
To string `json:"to"`
Value big.Int `json:"value"`
}
// EthereumInternalTransactionType - type of ethereum transaction from internal data
type EthereumInternalTransactionType int
// EthereumInternalTransactionType enumeration
const (
CALL = EthereumInternalTransactionType(iota)
CREATE
SELFDESTRUCT
)
// EthereumInternalTransaction contains internal transfers
type EthereumInternalData struct {
Type EthereumInternalTransactionType `json:"type"`
Contract string `json:"contract,omitempty"`
Transfers []EthereumInternalTransfer `json:"transfers,omitempty"`
}
// Erc20Contract contains info about ERC20 contract
type Erc20Contract struct {
Contract string `json:"contract"`
Name string `json:"name"`
Symbol string `json:"symbol"`
Decimals int `json:"decimals"`
}
// Erc20Transfer contains a single ERC20 token transfer
type Erc20Transfer struct {
Contract string
From string
To string
Tokens big.Int
}
// RpcTransaction is returned by eth_getTransactionByHash
type RpcTransaction struct {
AccountNonce string `json:"nonce"`
GasPrice string `json:"gasPrice"`
GasLimit string `json:"gas"`
To string `json:"to"` // nil means contract creation
Value string `json:"value"`
Payload string `json:"input"`
Hash string `json:"hash"`
BlockNumber string `json:"blockNumber"`
BlockHash string `json:"blockHash,omitempty"`
From string `json:"from"`
TransactionIndex string `json:"transactionIndex"`
// Signature values - ignored
// V string `json:"v"`
// R string `json:"r"`
// S string `json:"s"`
}
// RpcLog is returned by eth_getLogs
type RpcLog struct {
Address string `json:"address"`
Topics []string `json:"topics"`
Data string `json:"data"`
}
// RpcLog is returned by eth_getTransactionReceipt
type RpcReceipt struct {
GasUsed string `json:"gasUsed"`
Status string `json:"status"`
Logs []*RpcLog `json:"logs"`
}
type EthereumSpecificData struct {
Tx *RpcTransaction `json:"tx"`
InternalData *EthereumInternalData `json:"internalData,omitempty"`
Receipt *RpcReceipt `json:"receipt,omitempty"`
}

View File

@ -22,7 +22,7 @@ import (
"github.com/trezor/blockbook/common"
)
const dbVersion = 5
const dbVersion = 6
const packedHeightBytes = 4
const maxAddrDescLen = 1024
@ -112,6 +112,8 @@ const (
cfTxAddresses
// EthereumType
cfAddressContracts = cfAddressBalance
cfInternalData
cfContracts
)
// common columns
@ -120,7 +122,7 @@ var cfBaseNames = []string{"default", "height", "addresses", "blockTxs", "transa
// type specific columns
var cfNamesBitcoinType = []string{"addressBalance", "txAddresses"}
var cfNamesEthereumType = []string{"addressContracts"}
var cfNamesEthereumType = []string{"addressContracts", "internalData", "contracts"}
func openDB(path string, c *gorocksdb.Cache, openFiles int) (*gorocksdb.DB, []*gorocksdb.ColumnFamilyHandle, error) {
// opts with bloom filter

View File

@ -22,6 +22,7 @@ type AddrContract struct {
type AddrContracts struct {
TotalTxs uint
NonContractTxs uint
InternalTxs uint
Contracts []AddrContract
}
@ -30,7 +31,7 @@ func (d *RocksDB) storeAddressContracts(wb *gorocksdb.WriteBatch, acm map[string
varBuf := make([]byte, vlq.MaxLen64)
for addrDesc, acs := range acm {
// address with 0 contracts is removed from db - happens on disconnect
if acs == nil || (acs.NonContractTxs == 0 && len(acs.Contracts) == 0) {
if acs == nil || (acs.NonContractTxs == 0 && acs.InternalTxs == 0 && len(acs.Contracts) == 0) {
wb.DeleteCF(d.cfh[cfAddressContracts], bchain.AddressDescriptor(addrDesc))
} else {
buf = buf[:0]
@ -38,6 +39,8 @@ func (d *RocksDB) storeAddressContracts(wb *gorocksdb.WriteBatch, acm map[string
buf = append(buf, varBuf[:l]...)
l = packVaruint(acs.NonContractTxs, varBuf)
buf = append(buf, varBuf[:l]...)
l = packVaruint(acs.InternalTxs, varBuf)
buf = append(buf, varBuf[:l]...)
for _, ac := range acs.Contracts {
buf = append(buf, ac.Contract...)
l = packVaruint(ac.Txs, varBuf)
@ -64,6 +67,8 @@ func (d *RocksDB) GetAddrDescContracts(addrDesc bchain.AddressDescriptor) (*Addr
buf = buf[l:]
nct, l := unpackVaruint(buf)
buf = buf[l:]
ict, l := unpackVaruint(buf)
buf = buf[l:]
c := make([]AddrContract, 0, 4)
for len(buf) > 0 {
if len(buf) < eth.EthereumTypeAddressDescriptorLen {
@ -80,6 +85,7 @@ func (d *RocksDB) GetAddrDescContracts(addrDesc bchain.AddressDescriptor) (*Addr
return &AddrContracts{
TotalTxs: tt,
NonContractTxs: nct,
InternalTxs: ict,
Contracts: c,
}, nil
}

View File

@ -44,10 +44,10 @@ func verifyAfterEthereumTypeBlock1(t *testing.T, d *RocksDB, afterDisconnect boo
}
if err := checkColumn(d, cfAddressContracts, []keyPair{
{dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr3e, d.chainParser), "0101", nil},
{dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr55, d.chainParser), "0201" + dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddrContract4a, d.chainParser) + "01", nil},
{dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr20, d.chainParser), "0101" + dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddrContract4a, d.chainParser) + "01", nil},
{dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddrContract4a, d.chainParser), "0101", nil},
{dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr3e, d.chainParser), "010100", 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.EthAddrContract4a, d.chainParser), "010100", nil},
}); err != nil {
{
t.Fatal(err)
@ -113,14 +113,14 @@ func verifyAfterEthereumTypeBlock2(t *testing.T, d *RocksDB) {
}
if err := checkColumn(d, cfAddressContracts, []keyPair{
{dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr3e, d.chainParser), "0101", nil},
{dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr55, d.chainParser), "0402" + dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddrContract4a, d.chainParser) + "02" + dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddrContract0d, d.chainParser) + "01", nil},
{dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr20, d.chainParser), "0101" + dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddrContract4a, d.chainParser) + "01", nil},
{dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddrContract4a, d.chainParser), "0101", nil},
{dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr9f, d.chainParser), "0101", nil},
{dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr4b, d.chainParser), "0101" + dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddrContract0d, d.chainParser) + "02" + dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddrContract4a, d.chainParser) + "02", nil},
{dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr7b, d.chainParser), "0100" + dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddrContract4a, d.chainParser) + "01" + dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddrContract0d, d.chainParser) + "01", nil},
{dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddrContract47, d.chainParser), "0101", nil},
{dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr3e, d.chainParser), "010100", 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.EthAddrContract4a, d.chainParser), "010100", nil},
{dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddr9f, d.chainParser), "010100", 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.EthAddr7b, d.chainParser), "010000" + dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddrContract4a, d.chainParser) + "01" + dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddrContract0d, d.chainParser) + "01", nil},
{dbtestdata.AddressToPubKeyHex(dbtestdata.EthAddrContract47, d.chainParser), "010100", nil},
}); err != nil {
{
t.Fatal(err)

View File

@ -84,9 +84,9 @@ Column families used only by **Ethereum type** coins:
- **addressContracts** (used only by Ethereum type coins)
Maps *addrDesc* to *total number of transactions*, *number of non contract transactions* and array of *contracts* with *number of transfers* of given address.
Maps *addrDesc* to *total number of transactions*, *number of non contract transactions*, *number of internal transactions* and array of *contracts* with *number of transfers* of given address.
```
(addrDesc []byte) -> (total_txs vuint)+(non-contract_txs vuint)+[]((contractAddrDesc []byte)+(nr_transfers vuint))
(addrDesc []byte) -> (total_txs vuint)+(non-contract_txs vuint)+(internal_txs vuint)+[]((contractAddrDesc []byte)+(nr_transfers vuint))
```
- **blockTxs**

File diff suppressed because one or more lines are too long