Add custom handling of unknown input txs during BitcoinType block import
parent
d77fb35bb5
commit
341bf331c1
|
@ -7,6 +7,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/gogo/protobuf/proto"
|
||||
"github.com/golang/glog"
|
||||
"github.com/juju/errors"
|
||||
)
|
||||
|
||||
|
@ -26,6 +27,16 @@ func (p *BaseParser) ParseTx(b []byte) (*Tx, error) {
|
|||
return nil, errors.New("ParseTx: not implemented")
|
||||
}
|
||||
|
||||
// GetAddrDescForUnknownInput returns nil AddressDescriptor
|
||||
func (p *BaseParser) GetAddrDescForUnknownInput(block *Block, 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)
|
||||
return nil
|
||||
}
|
||||
|
||||
const zeros = "0000000000000000000000000000000000000000"
|
||||
|
||||
// AmountToBigInt converts amount in json.Number (string) to big.Int
|
||||
|
|
|
@ -3,7 +3,12 @@ package liquid
|
|||
import (
|
||||
"blockbook/bchain"
|
||||
"blockbook/bchain/coins/btc"
|
||||
"strconv"
|
||||
|
||||
vlq "github.com/bsm/go-vlq"
|
||||
"github.com/golang/glog"
|
||||
|
||||
"github.com/martinboehm/btcd/txscript"
|
||||
"github.com/martinboehm/btcd/wire"
|
||||
"github.com/martinboehm/btcutil/chaincfg"
|
||||
)
|
||||
|
@ -27,15 +32,19 @@ func init() {
|
|||
// LiquidParser handle
|
||||
type LiquidParser struct {
|
||||
*btc.BitcoinParser
|
||||
baseparser *bchain.BaseParser
|
||||
baseparser *bchain.BaseParser
|
||||
origOutputScriptToAddressesFunc btc.OutputScriptToAddressesFunc
|
||||
}
|
||||
|
||||
// NewLiquidParser returns new LiquidParser instance
|
||||
func NewLiquidParser(params *chaincfg.Params, c *btc.Configuration) *LiquidParser {
|
||||
return &LiquidParser{
|
||||
p := &LiquidParser{
|
||||
BitcoinParser: btc.NewBitcoinParser(params, c),
|
||||
baseparser: &bchain.BaseParser{},
|
||||
}
|
||||
p.origOutputScriptToAddressesFunc = p.OutputScriptToAddressesFunc
|
||||
p.OutputScriptToAddressesFunc = p.outputScriptToAddresses
|
||||
return p
|
||||
}
|
||||
|
||||
// GetChainParams contains network parameters for the main GameCredits network,
|
||||
|
@ -62,3 +71,36 @@ func (p *LiquidParser) PackTx(tx *bchain.Tx, height uint32, blockTime int64) ([]
|
|||
func (p *LiquidParser) UnpackTx(buf []byte) (*bchain.Tx, uint32, error) {
|
||||
return p.baseparser.UnpackTx(buf)
|
||||
}
|
||||
|
||||
// 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 {
|
||||
var iTxid string
|
||||
s := make([]byte, 0, 40)
|
||||
if len(tx.Vin) > input {
|
||||
iTxid = tx.Vin[input].Txid
|
||||
btxID, err := p.PackTxid(iTxid)
|
||||
if err == nil {
|
||||
buf := make([]byte, vlq.MaxLen64)
|
||||
l := vlq.PutInt(buf, int64(tx.Vin[input].Vout))
|
||||
s = append(s, txscript.OP_INVALIDOPCODE)
|
||||
s = append(s, btxID...)
|
||||
s = append(s, buf[:l]...)
|
||||
}
|
||||
}
|
||||
glog.Info("height ", block.Height, ", tx ", tx.Txid, ", encountered Bitcoin tx ", iTxid)
|
||||
return s
|
||||
}
|
||||
|
||||
// outputScriptToAddresses converts ScriptPubKey to bitcoin addresses
|
||||
func (p *LiquidParser) outputScriptToAddresses(script []byte) ([]string, bool, error) {
|
||||
// minimum length of the special script OP_INVALIDOPCODE <txid> <index varint> is 34 bytes (1 byte opcode, 32 bytes tx, 1 byte vout)
|
||||
if len(script) > 33 && script[0] == txscript.OP_INVALIDOPCODE {
|
||||
txid, _ := p.UnpackTxid(script[1:33])
|
||||
vout, _ := vlq.Int(script[33:])
|
||||
return []string{
|
||||
"Bitcoin tx " + txid + ":" + strconv.Itoa(int(vout)),
|
||||
}, false, nil
|
||||
}
|
||||
return p.origOutputScriptToAddressesFunc(script)
|
||||
}
|
||||
|
|
|
@ -256,6 +256,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
|
||||
// blocks
|
||||
PackBlockHash(hash string) ([]byte, error)
|
||||
UnpackBlockHash(buf []byte) (string, error)
|
||||
|
|
|
@ -13,7 +13,7 @@ import (
|
|||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/bsm/go-vlq"
|
||||
vlq "github.com/bsm/go-vlq"
|
||||
"github.com/golang/glog"
|
||||
"github.com/juju/errors"
|
||||
"github.com/tecbot/gorocksdb"
|
||||
|
@ -490,7 +490,8 @@ func (d *RocksDB) processAddressesBitcoinType(block *bchain.Block, addresses add
|
|||
return err
|
||||
}
|
||||
if ita == nil {
|
||||
glog.Warningf("rocksdb: height %d, tx %v, input tx %v not found in txAddresses", block.Height, tx.Txid, input.Txid)
|
||||
// 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)
|
||||
continue
|
||||
}
|
||||
txAddressesMap[stxID] = ita
|
||||
|
|
Loading…
Reference in New Issue