Handle error tx not found #94
This commit is contained in:
parent
8c4fcf4441
commit
3ca593aff1
@ -107,7 +107,10 @@ func (w *Worker) GetSpendingTxid(txid string, n int) (string, error) {
|
||||
func (w *Worker) GetTransaction(txid string, spendingTxs bool, specificJSON bool) (*Tx, error) {
|
||||
bchainTx, height, err := w.txCache.GetTransaction(txid)
|
||||
if err != nil {
|
||||
return nil, NewAPIError(fmt.Sprintf("Tx not found, %v", err), true)
|
||||
if err == bchain.ErrTxNotFound {
|
||||
return nil, NewAPIError(fmt.Sprintf("Transaction '%v' not found", txid), true)
|
||||
}
|
||||
return nil, NewAPIError(fmt.Sprintf("Transaction '%v' not found (%v)", txid, err), true)
|
||||
}
|
||||
return w.GetTransactionFromBchainTx(bchainTx, height, spendingTxs, specificJSON)
|
||||
}
|
||||
@ -158,6 +161,11 @@ func (w *Worker) GetTransactionFromBchainTx(bchainTx *bchain.Tx, height uint32,
|
||||
// try to load from backend
|
||||
otx, _, err := w.txCache.GetTransaction(bchainVin.Txid)
|
||||
if err != nil {
|
||||
if err == bchain.ErrTxNotFound {
|
||||
// try to get AddrDesc using coin specific handling and continue processing the tx
|
||||
vin.AddrDesc = w.chainParser.GetAddrDescForUnknownInput(bchainTx, i)
|
||||
continue
|
||||
}
|
||||
return nil, errors.Annotatef(err, "txCache.GetTransaction %v", bchainVin.Txid)
|
||||
}
|
||||
if len(otx.Vout) > int(vin.Vout) {
|
||||
|
||||
@ -28,12 +28,12 @@ func (p *BaseParser) ParseTx(b []byte) (*Tx, error) {
|
||||
}
|
||||
|
||||
// GetAddrDescForUnknownInput returns nil AddressDescriptor
|
||||
func (p *BaseParser) GetAddrDescForUnknownInput(block *Block, tx *Tx, input int) AddressDescriptor {
|
||||
func (p *BaseParser) GetAddrDescForUnknownInput(tx *Tx, input int) AddressDescriptor {
|
||||
var iTxid string
|
||||
if len(tx.Vin) > input {
|
||||
iTxid = tx.Vin[input].Txid
|
||||
}
|
||||
glog.Warningf("height %d, tx %v, input tx %v not found in txAddresses", block.Height, tx.Txid, iTxid)
|
||||
glog.Warningf("tx %v, input tx %v not found in txAddresses", tx.Txid, iTxid)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@ -154,6 +154,7 @@ func (p *BitcoinParser) outputScriptToAddresses(script []byte) ([]string, bool,
|
||||
return rv, s, nil
|
||||
}
|
||||
|
||||
// TxFromMsgTx converts bitcoin wire Tx to bchain.Tx
|
||||
func (p *BitcoinParser) TxFromMsgTx(t *wire.MsgTx, parseAddresses bool) bchain.Tx {
|
||||
vin := make([]bchain.Vin, len(t.TxIn))
|
||||
for i, in := range t.TxIn {
|
||||
|
||||
@ -633,6 +633,13 @@ func (b *BitcoinRPC) GetMempool() ([]string, error) {
|
||||
return res.Result, nil
|
||||
}
|
||||
|
||||
func isMissingTx(err *bchain.RPCError) bool {
|
||||
if err.Code == -5 { // "No such mempool or blockchain transaction"
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// GetTransactionForMempool returns a transaction by the transaction ID
|
||||
// It could be optimized for mempool, i.e. without block time and confirmations
|
||||
func (b *BitcoinRPC) GetTransactionForMempool(txid string) (*bchain.Tx, error) {
|
||||
@ -647,6 +654,9 @@ func (b *BitcoinRPC) GetTransactionForMempool(txid string) (*bchain.Tx, error) {
|
||||
return nil, errors.Annotatef(err, "txid %v", txid)
|
||||
}
|
||||
if res.Error != nil {
|
||||
if isMissingTx(res.Error) {
|
||||
return nil, bchain.ErrTxNotFound
|
||||
}
|
||||
return nil, errors.Annotatef(res.Error, "txid %v", txid)
|
||||
}
|
||||
data, err := hex.DecodeString(res.Result)
|
||||
@ -696,6 +706,9 @@ func (b *BitcoinRPC) getRawTransaction(txid string) (json.RawMessage, error) {
|
||||
return nil, errors.Annotatef(err, "txid %v", txid)
|
||||
}
|
||||
if res.Error != nil {
|
||||
if isMissingTx(res.Error) {
|
||||
return nil, bchain.ErrTxNotFound
|
||||
}
|
||||
return nil, errors.Annotatef(res.Error, "txid %v", txid)
|
||||
}
|
||||
return res.Result, nil
|
||||
|
||||
@ -520,7 +520,7 @@ func (b *EthereumRPC) GetBlockInfo(hash string) (*bchain.BlockInfo, error) {
|
||||
func (b *EthereumRPC) GetTransactionForMempool(txid string) (*bchain.Tx, error) {
|
||||
tx, err := b.GetTransaction(txid)
|
||||
// it there is an error getting the tx or the tx is confirmed, remove it from pending transactions
|
||||
if err != nil || (tx != nil && tx.Confirmations > 0) {
|
||||
if err == bchain.ErrTxNotFound || (tx != nil && tx.Confirmations > 0) {
|
||||
b.pendingTransactionsLock.Lock()
|
||||
delete(b.pendingTransactions, txid)
|
||||
b.pendingTransactionsLock.Unlock()
|
||||
@ -538,7 +538,7 @@ func (b *EthereumRPC) GetTransaction(txid string) (*bchain.Tx, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
} else if tx == nil {
|
||||
return nil, ethereum.NotFound
|
||||
return nil, bchain.ErrTxNotFound
|
||||
}
|
||||
var btx *bchain.Tx
|
||||
if tx.BlockNumber == "" {
|
||||
|
||||
@ -74,7 +74,7 @@ func (p *LiquidParser) UnpackTx(buf []byte) (*bchain.Tx, uint32, error) {
|
||||
|
||||
// GetAddrDescForUnknownInput processes inputs that were not found in txAddresses - they are bitcoin transactions
|
||||
// create a special script for the input in the form OP_INVALIDOPCODE <txid> <vout varint>
|
||||
func (p *LiquidParser) GetAddrDescForUnknownInput(block *bchain.Block, tx *bchain.Tx, input int) bchain.AddressDescriptor {
|
||||
func (p *LiquidParser) GetAddrDescForUnknownInput(tx *bchain.Tx, input int) bchain.AddressDescriptor {
|
||||
var iTxid string
|
||||
s := make([]byte, 0, 40)
|
||||
if len(tx.Vin) > input {
|
||||
@ -88,7 +88,7 @@ func (p *LiquidParser) GetAddrDescForUnknownInput(block *bchain.Block, tx *bchai
|
||||
s = append(s, buf[:l]...)
|
||||
}
|
||||
}
|
||||
glog.Info("height ", block.Height, ", tx ", tx.Txid, ", encountered Bitcoin tx ", iTxid)
|
||||
glog.Info("tx ", tx.Txid, ", encountered Bitcoin tx ", iTxid)
|
||||
return s
|
||||
}
|
||||
|
||||
|
||||
@ -31,6 +31,8 @@ var (
|
||||
// ErrTxidMissing is returned if txid is not specified
|
||||
// for example coinbase transactions in Bitcoin
|
||||
ErrTxidMissing = errors.New("Txid missing")
|
||||
// ErrTxNotFound is returned if transaction was not found
|
||||
ErrTxNotFound = errors.New("Tx not found")
|
||||
)
|
||||
|
||||
// Outpoint is txid together with output (or input) index
|
||||
@ -256,7 +258,7 @@ type BlockChainParser interface {
|
||||
ParseTxFromJson(json.RawMessage) (*Tx, error)
|
||||
PackTx(tx *Tx, height uint32, blockTime int64) ([]byte, error)
|
||||
UnpackTx(buf []byte) (*Tx, uint32, error)
|
||||
GetAddrDescForUnknownInput(block *Block, tx *Tx, input int) AddressDescriptor
|
||||
GetAddrDescForUnknownInput(tx *Tx, input int) AddressDescriptor
|
||||
// blocks
|
||||
PackBlockHash(hash string) ([]byte, error)
|
||||
UnpackBlockHash(buf []byte) (string, error)
|
||||
|
||||
@ -491,7 +491,7 @@ func (d *RocksDB) processAddressesBitcoinType(block *bchain.Block, addresses add
|
||||
}
|
||||
if ita == nil {
|
||||
// allow parser to process unknown input, some coins may implement special handling, default is to log warning
|
||||
tai.AddrDesc = d.chainParser.GetAddrDescForUnknownInput(block, tx, i)
|
||||
tai.AddrDesc = d.chainParser.GetAddrDescForUnknownInput(tx, i)
|
||||
continue
|
||||
}
|
||||
txAddressesMap[stxID] = ita
|
||||
|
||||
@ -19,7 +19,7 @@ import (
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/martinboehm/btcutil/chaincfg"
|
||||
"github.com/martinboehm/golang-socketio"
|
||||
gosocketio "github.com/martinboehm/golang-socketio"
|
||||
"github.com/martinboehm/golang-socketio/transport"
|
||||
)
|
||||
|
||||
@ -388,7 +388,7 @@ func httpTests_BitcoinType(t *testing.T, ts *httptest.Server) {
|
||||
status: http.StatusBadRequest,
|
||||
contentType: "application/json; charset=utf-8",
|
||||
body: []string{
|
||||
`{"error":"Tx not found, Not found"}`,
|
||||
`{"error":"Transaction '1232e48aeabdd9b75def7b48d756ba304713c2aba7b522bf9dbc893fc4231b07' not found"}`,
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -406,7 +406,7 @@ func httpTests_BitcoinType(t *testing.T, ts *httptest.Server) {
|
||||
status: http.StatusBadRequest,
|
||||
contentType: "application/json; charset=utf-8",
|
||||
body: []string{
|
||||
`{"error":"Tx not found, Not found"}`,
|
||||
`{"error":"Transaction '1232e48aeabdd9b75def7b48d756ba304713c2aba7b522bf9dbc893fc4231b07' not found"}`,
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@ -138,7 +138,7 @@ func (c *fakeBlockChain) GetTransaction(txid string) (v *bchain.Tx, err error) {
|
||||
if v != nil {
|
||||
return v, nil
|
||||
}
|
||||
return nil, errors.New("Not found")
|
||||
return nil, bchain.ErrTxNotFound
|
||||
}
|
||||
|
||||
func (c *fakeBlockChain) GetTransactionSpecific(tx *bchain.Tx) (v json.RawMessage, err error) {
|
||||
|
||||
@ -11,7 +11,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/deckarep/golang-set"
|
||||
mapset "github.com/deckarep/golang-set"
|
||||
"github.com/juju/errors"
|
||||
)
|
||||
|
||||
@ -351,7 +351,7 @@ func getTxid2addrs(t *testing.T, h *TestHandler, txs []string) map[string][]stri
|
||||
for i := range txs {
|
||||
tx, err := h.Chain.GetTransactionForMempool(txs[i])
|
||||
if err != nil {
|
||||
if isMissingTx(err) {
|
||||
if err == bchain.ErrTxNotFound {
|
||||
continue
|
||||
}
|
||||
t.Fatal(err)
|
||||
@ -370,20 +370,6 @@ func getTxid2addrs(t *testing.T, h *TestHandler, txs []string) map[string][]stri
|
||||
return txid2addrs
|
||||
}
|
||||
|
||||
func isMissingTx(err error) bool {
|
||||
switch e1 := err.(type) {
|
||||
case *errors.Err:
|
||||
switch e2 := e1.Cause().(type) {
|
||||
case *bchain.RPCError:
|
||||
if e2.Code == -5 { // "No such mempool or blockchain transaction"
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func intersect(a, b []string) []string {
|
||||
setA := mapset.NewSet()
|
||||
for _, v := range a {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user