Fix api.GetTransaction for EthereumType blockchain

This commit is contained in:
Martin Boehm 2018-11-07 00:24:53 +01:00
parent 4448c57ba8
commit 1ac7a7abca
5 changed files with 107 additions and 58 deletions

View File

@ -20,6 +20,7 @@ type Worker struct {
txCache *db.TxCache txCache *db.TxCache
chain bchain.BlockChain chain bchain.BlockChain
chainParser bchain.BlockChainParser chainParser bchain.BlockChainParser
chainType bchain.ChainType
is *common.InternalState is *common.InternalState
} }
@ -30,6 +31,7 @@ func NewWorker(db *db.RocksDB, chain bchain.BlockChain, txCache *db.TxCache, is
txCache: txCache, txCache: txCache,
chain: chain, chain: chain,
chainParser: chain.GetChainParser(), chainParser: chain.GetChainParser(),
chainType: chain.GetChainParser().GetChainType(),
is: is, is: is,
} }
return w, nil return w, nil
@ -105,10 +107,12 @@ func (w *Worker) GetTransaction(txid string, spendingTxs bool) (*Tx, error) {
var ta *db.TxAddresses var ta *db.TxAddresses
var blockhash string var blockhash string
if bchainTx.Confirmations > 0 { if bchainTx.Confirmations > 0 {
if w.chainType == bchain.ChainBitcoinType {
ta, err = w.db.GetTxAddresses(txid) ta, err = w.db.GetTxAddresses(txid)
if err != nil { if err != nil {
return nil, errors.Annotatef(err, "GetTxAddresses %v", txid) return nil, errors.Annotatef(err, "GetTxAddresses %v", txid)
} }
}
blockhash, err = w.db.GetBlockHash(height) blockhash, err = w.db.GetBlockHash(height)
if err != nil { if err != nil {
return nil, errors.Annotatef(err, "GetBlockHash %v", height) return nil, errors.Annotatef(err, "GetBlockHash %v", height)
@ -124,6 +128,7 @@ func (w *Worker) GetTransaction(txid string, spendingTxs bool) (*Tx, error) {
vin.Vout = bchainVin.Vout vin.Vout = bchainVin.Vout
vin.Sequence = int64(bchainVin.Sequence) vin.Sequence = int64(bchainVin.Sequence)
vin.ScriptSig.Hex = bchainVin.ScriptSig.Hex vin.ScriptSig.Hex = bchainVin.ScriptSig.Hex
if w.chainType == bchain.ChainBitcoinType {
// bchainVin.Txid=="" is coinbase transaction // bchainVin.Txid=="" is coinbase transaction
if bchainVin.Txid != "" { if bchainVin.Txid != "" {
// load spending addresses from TxAddresses // load spending addresses from TxAddresses
@ -164,6 +169,16 @@ func (w *Worker) GetTransaction(txid string, spendingTxs bool) (*Tx, error) {
vin.Value = w.chainParser.AmountToDecimalString(&vin.ValueSat) vin.Value = w.chainParser.AmountToDecimalString(&vin.ValueSat)
valInSat.Add(&valInSat, &vin.ValueSat) valInSat.Add(&valInSat, &vin.ValueSat)
} }
} else if w.chainType == bchain.ChainEthereumType {
if len(bchainVin.Addresses) > 0 {
vin.AddrDesc, err = w.chainParser.GetAddrDescFromAddress(bchainVin.Addresses[0])
if err != nil {
glog.Errorf("GetAddrDescFromAddress error %v, tx %v, bchainVin %v", err, bchainTx.Txid, bchainVin)
}
vin.Addresses = bchainVin.Addresses
vin.Searchable = true
}
}
} }
vouts := make([]Vout, len(bchainTx.Vout)) vouts := make([]Vout, len(bchainTx.Vout))
for i := range bchainTx.Vout { for i := range bchainTx.Vout {

View File

@ -291,7 +291,26 @@ func (p *EthereumParser) UnpackBlockHash(buf []byte) (string, error) {
return hexutil.Encode(buf), nil return hexutil.Encode(buf), nil
} }
// GetChainType returns TypeEthereum // GetChainType returns EthereumType
func (p *EthereumParser) GetChainType() bchain.ChainType { func (p *EthereumParser) GetChainType() bchain.ChainType {
return bchain.ChainEthereumType return bchain.ChainEthereumType
} }
// GetHeightFromTx returns ethereum specific data from bchain.Tx
func GetHeightFromTx(tx *bchain.Tx) (uint32, error) {
// TODO - temporary implementation - will use bchain.Tx.SpecificData field
b, err := hex.DecodeString(tx.Hex)
if err != nil {
return 0, err
}
var r rpcTransaction
var n uint64
err = json.Unmarshal(b, &r)
if err != nil {
return 0, err
}
if n, err = hexutil.DecodeUint64(r.BlockNumber); err != nil {
return 0, errors.Annotatef(err, "BlockNumber %v", r.BlockNumber)
}
return uint32(n), nil
}

View File

@ -15,7 +15,7 @@ type ChainType int
const ( const (
// ChainBitcoinType is blockchain derived from bitcoin // ChainBitcoinType is blockchain derived from bitcoin
ChainBitcoinType = ChainType(iota) ChainBitcoinType = ChainType(iota)
// TypeEthereum is blockchain derived from ethereum // ChainEthereumType is blockchain derived from ethereum
ChainEthereumType ChainEthereumType
) )

View File

@ -301,9 +301,11 @@ func (d *RocksDB) writeBlock(block *bchain.Block, op int) error {
return err return err
} }
} else if chainType == bchain.ChainEthereumType { } else if chainType == bchain.ChainEthereumType {
if err := d.writeAddressesTypeEthereum(wb, block, op); err != nil { if err := d.writeAddressesEthereumType(wb, block, op); err != nil {
return err return err
} }
} else {
return errors.New("Unknown chain type")
} }
return d.db.Write(d.wo, wb) return d.db.Write(d.wo, wb)
@ -861,7 +863,7 @@ func (d *RocksDB) addAddrDescToRecords(op int, wb *gorocksdb.WriteBatch, records
return nil return nil
} }
func (d *RocksDB) writeAddressesTypeEthereum(wb *gorocksdb.WriteBatch, block *bchain.Block, op int) error { func (d *RocksDB) writeAddressesEthereumType(wb *gorocksdb.WriteBatch, block *bchain.Block, op int) error {
addresses := make(map[string][]outpoint) addresses := make(map[string][]outpoint)
for _, tx := range block.Txs { for _, tx := range block.Txs {
btxID, err := d.chainParser.PackTxid(tx.Txid) btxID, err := d.chainParser.PackTxid(tx.Txid)

View File

@ -2,9 +2,11 @@ package db
import ( import (
"blockbook/bchain" "blockbook/bchain"
"blockbook/bchain/coins/eth"
"blockbook/common" "blockbook/common"
"github.com/golang/glog" "github.com/golang/glog"
"github.com/juju/errors"
) )
// TxCache is handle to TxCacheServer // TxCache is handle to TxCacheServer
@ -14,6 +16,7 @@ type TxCache struct {
metrics *common.Metrics metrics *common.Metrics
is *common.InternalState is *common.InternalState
enabled bool enabled bool
chainType bchain.ChainType
} }
// NewTxCache creates new TxCache interface and returns its handle // NewTxCache creates new TxCache interface and returns its handle
@ -27,6 +30,7 @@ func NewTxCache(db *RocksDB, chain bchain.BlockChain, metrics *common.Metrics, i
metrics: metrics, metrics: metrics,
is: is, is: is,
enabled: enabled, enabled: enabled,
chainType: chain.GetChainParser().GetChainType(),
}, nil }, nil
} }
@ -56,6 +60,7 @@ func (c *TxCache) GetTransaction(txid string) (*bchain.Tx, uint32, error) {
c.metrics.TxCacheEfficiency.With(common.Labels{"status": "miss"}).Inc() c.metrics.TxCacheEfficiency.With(common.Labels{"status": "miss"}).Inc()
// cache only confirmed transactions // cache only confirmed transactions
if tx.Confirmations > 0 { if tx.Confirmations > 0 {
if c.chainType == bchain.ChainBitcoinType {
ta, err := c.db.GetTxAddresses(txid) ta, err := c.db.GetTxAddresses(txid)
if err != nil { if err != nil {
return nil, 0, err return nil, 0, err
@ -69,6 +74,14 @@ func (c *TxCache) GetTransaction(txid string) (*bchain.Tx, uint32, error) {
} else { } else {
h = ta.Height h = ta.Height
} }
} else if c.chainType == bchain.ChainEthereumType {
h, err = eth.GetHeightFromTx(tx)
if err != nil {
return nil, 0, err
}
} else {
return nil, 0, errors.New("Unknown chain type")
}
if c.enabled { if c.enabled {
err = c.db.PutTx(tx, h, tx.Blocktime) err = c.db.PutTx(tx, h, tx.Blocktime)
// do not return caching error, only log it // do not return caching error, only log it