github.com/viacoin/blockbook@v0.3.2-0.20200124170434-77b4f2555a4b/db/txcache.go (about) 1 package db 2 3 import ( 4 "blockbook/bchain" 5 "blockbook/bchain/coins/eth" 6 "blockbook/common" 7 8 "github.com/golang/glog" 9 "github.com/juju/errors" 10 ) 11 12 // TxCache is handle to TxCacheServer 13 type TxCache struct { 14 db *RocksDB 15 chain bchain.BlockChain 16 metrics *common.Metrics 17 is *common.InternalState 18 enabled bool 19 chainType bchain.ChainType 20 } 21 22 // NewTxCache creates new TxCache interface and returns its handle 23 func NewTxCache(db *RocksDB, chain bchain.BlockChain, metrics *common.Metrics, is *common.InternalState, enabled bool) (*TxCache, error) { 24 if !enabled { 25 glog.Info("txcache: disabled") 26 } 27 return &TxCache{ 28 db: db, 29 chain: chain, 30 metrics: metrics, 31 is: is, 32 enabled: enabled, 33 chainType: chain.GetChainParser().GetChainType(), 34 }, nil 35 } 36 37 // GetTransaction returns transaction either from RocksDB or if not present from blockchain 38 // it the transaction is confirmed, it is stored in the RocksDB 39 func (c *TxCache) GetTransaction(txid string) (*bchain.Tx, int, error) { 40 var tx *bchain.Tx 41 var h uint32 42 var err error 43 if c.enabled { 44 tx, h, err = c.db.GetTx(txid) 45 if err != nil { 46 return nil, 0, err 47 } 48 if tx != nil { 49 // number of confirmations is not stored in cache, they change all the time 50 _, bestheight, _ := c.is.GetSyncState() 51 tx.Confirmations = bestheight - h + 1 52 c.metrics.TxCacheEfficiency.With(common.Labels{"status": "hit"}).Inc() 53 return tx, int(h), nil 54 } 55 } 56 tx, err = c.chain.GetTransaction(txid) 57 if err != nil { 58 return nil, 0, err 59 } 60 c.metrics.TxCacheEfficiency.With(common.Labels{"status": "miss"}).Inc() 61 // cache only confirmed transactions 62 if tx.Confirmations > 0 { 63 if c.chainType == bchain.ChainBitcoinType { 64 ta, err := c.db.GetTxAddresses(txid) 65 if err != nil { 66 return nil, 0, err 67 } 68 switch { 69 case ta == nil: 70 // the transaction may not yet be indexed, in that case: 71 if tx.BlockHeight > 0 { 72 // Check if the tx height value is set. 73 h = tx.BlockHeight 74 } else { 75 // Get the height from the backend's bestblock. 76 h, err = c.chain.GetBestBlockHeight() 77 if err != nil { 78 return nil, 0, err 79 } 80 } 81 default: 82 h = ta.Height 83 } 84 } else if c.chainType == bchain.ChainEthereumType { 85 h, err = eth.GetHeightFromTx(tx) 86 if err != nil { 87 return nil, 0, err 88 } 89 } else { 90 return nil, 0, errors.New("Unknown chain type") 91 } 92 if c.enabled { 93 err = c.db.PutTx(tx, h, tx.Blocktime) 94 // do not return caching error, only log it 95 if err != nil { 96 glog.Error("PutTx error ", err) 97 } 98 } 99 } else { 100 return tx, -1, nil 101 } 102 return tx, int(h), nil 103 }