Handle Bitcoin vout addresses after upgrade to bitcoind 22.0.0

It was necessary to split the composition chain in other coins
from BitcoinParser to BitcoinLikeParser to keep backwards compatibility
This commit is contained in:
Martin Boehm 2021-09-21 23:54:08 +02:00
parent 93d09014c1
commit eae9b6b613
40 changed files with 578 additions and 477 deletions

View File

@ -53,7 +53,7 @@ func init() {
// BCashParser handle // BCashParser handle
type BCashParser struct { type BCashParser struct {
*btc.BitcoinParser *btc.BitcoinLikeParser
AddressFormat AddressFormat AddressFormat AddressFormat
} }
@ -71,8 +71,8 @@ func NewBCashParser(params *chaincfg.Params, c *btc.Configuration) (*BCashParser
return nil, fmt.Errorf("Unknown address format: %s", c.AddressFormat) return nil, fmt.Errorf("Unknown address format: %s", c.AddressFormat)
} }
p := &BCashParser{ p := &BCashParser{
BitcoinParser: btc.NewBitcoinParser(params, c), BitcoinLikeParser: btc.NewBitcoinLikeParser(params, c),
AddressFormat: format, AddressFormat: format,
} }
p.OutputScriptToAddressesFunc = p.outputScriptToAddresses p.OutputScriptToAddressesFunc = p.outputScriptToAddresses
return p, nil return p, nil

View File

@ -34,12 +34,12 @@ func init() {
// BellcoinParser handle // BellcoinParser handle
type BellcoinParser struct { type BellcoinParser struct {
*btc.BitcoinParser *btc.BitcoinLikeParser
} }
// NewBellcoinParser returns new BellcoinParser instance // NewBellcoinParser returns new BellcoinParser instance
func NewBellcoinParser(params *chaincfg.Params, c *btc.Configuration) *BellcoinParser { func NewBellcoinParser(params *chaincfg.Params, c *btc.Configuration) *BellcoinParser {
return &BellcoinParser{BitcoinParser: btc.NewBitcoinParser(params, c)} return &BellcoinParser{BitcoinLikeParser: btc.NewBitcoinLikeParser(params, c)}
} }
// GetChainParams contains network parameters for the main Bellcoin network, // GetChainParams contains network parameters for the main Bellcoin network,

View File

@ -39,15 +39,15 @@ func init() {
// BitcoreParser handle // BitcoreParser handle
type BitcoreParser struct { type BitcoreParser struct {
*btc.BitcoinParser *btc.BitcoinLikeParser
baseparser *bchain.BaseParser baseparser *bchain.BaseParser
} }
// NewBitcoreParser returns new BitcoreParser instance // NewBitcoreParser returns new BitcoreParser instance
func NewBitcoreParser(params *chaincfg.Params, c *btc.Configuration) *BitcoreParser { func NewBitcoreParser(params *chaincfg.Params, c *btc.Configuration) *BitcoreParser {
return &BitcoreParser{ return &BitcoreParser{
BitcoinParser: btc.NewBitcoinParser(params, c), BitcoinLikeParser: btc.NewBitcoinLikeParser(params, c),
baseparser: &bchain.BaseParser{}, baseparser: &bchain.BaseParser{},
} }
} }

View File

@ -35,12 +35,12 @@ func init() {
// BitZenyParser handle // BitZenyParser handle
type BitZenyParser struct { type BitZenyParser struct {
*btc.BitcoinParser *btc.BitcoinLikeParser
} }
// NewBitZenyParser returns new BitZenyParser instance // NewBitZenyParser returns new BitZenyParser instance
func NewBitZenyParser(params *chaincfg.Params, c *btc.Configuration) *BitZenyParser { func NewBitZenyParser(params *chaincfg.Params, c *btc.Configuration) *BitZenyParser {
return &BitZenyParser{BitcoinParser: btc.NewBitcoinParser(params, c)} return &BitZenyParser{BitcoinLikeParser: btc.NewBitcoinLikeParser(params, c)}
} }
// GetChainParams contains network parameters for the main BitZeny network, // GetChainParams contains network parameters for the main BitZeny network,

View File

@ -0,0 +1,417 @@
package btc
import (
"bytes"
"encoding/binary"
"encoding/hex"
"math/big"
"strconv"
"unicode/utf8"
vlq "github.com/bsm/go-vlq"
"github.com/juju/errors"
"github.com/martinboehm/btcd/blockchain"
"github.com/martinboehm/btcd/wire"
"github.com/martinboehm/btcutil"
"github.com/martinboehm/btcutil/chaincfg"
"github.com/martinboehm/btcutil/hdkeychain"
"github.com/martinboehm/btcutil/txscript"
"github.com/trezor/blockbook/bchain"
)
// OutputScriptToAddressesFunc converts ScriptPubKey to bitcoin addresses
type OutputScriptToAddressesFunc func(script []byte) ([]string, bool, error)
// BitcoinLikeParser handle
type BitcoinLikeParser struct {
*bchain.BaseParser
Params *chaincfg.Params
OutputScriptToAddressesFunc OutputScriptToAddressesFunc
XPubMagic uint32
XPubMagicSegwitP2sh uint32
XPubMagicSegwitNative uint32
Slip44 uint32
minimumCoinbaseConfirmations int
}
// NewBitcoinLikeParser returns new BitcoinLikeParser instance
func NewBitcoinLikeParser(params *chaincfg.Params, c *Configuration) *BitcoinLikeParser {
p := &BitcoinLikeParser{
BaseParser: &bchain.BaseParser{
BlockAddressesToKeep: c.BlockAddressesToKeep,
AmountDecimalPoint: 8,
},
Params: params,
XPubMagic: c.XPubMagic,
XPubMagicSegwitP2sh: c.XPubMagicSegwitP2sh,
XPubMagicSegwitNative: c.XPubMagicSegwitNative,
Slip44: c.Slip44,
minimumCoinbaseConfirmations: c.MinimumCoinbaseConfirmations,
}
p.OutputScriptToAddressesFunc = p.outputScriptToAddresses
return p
}
// GetAddrDescFromVout returns internal address representation (descriptor) of given transaction output
func (p *BitcoinLikeParser) GetAddrDescFromVout(output *bchain.Vout) (bchain.AddressDescriptor, error) {
ad, err := hex.DecodeString(output.ScriptPubKey.Hex)
if err != nil {
return ad, err
}
// convert possible P2PK script to P2PKH
// so that all transactions by given public key are indexed together
return txscript.ConvertP2PKtoP2PKH(p.Params.Base58CksumHasher, ad)
}
// GetAddrDescFromAddress returns internal address representation (descriptor) of given address
func (p *BitcoinLikeParser) GetAddrDescFromAddress(address string) (bchain.AddressDescriptor, error) {
return p.addressToOutputScript(address)
}
// GetAddressesFromAddrDesc returns addresses for given address descriptor with flag if the addresses are searchable
func (p *BitcoinLikeParser) GetAddressesFromAddrDesc(addrDesc bchain.AddressDescriptor) ([]string, bool, error) {
return p.OutputScriptToAddressesFunc(addrDesc)
}
// GetScriptFromAddrDesc returns output script for given address descriptor
func (p *BitcoinLikeParser) GetScriptFromAddrDesc(addrDesc bchain.AddressDescriptor) ([]byte, error) {
return addrDesc, nil
}
// IsAddrDescIndexable returns true if AddressDescriptor should be added to index
// empty or OP_RETURN scripts are not indexed
func (p *BitcoinLikeParser) IsAddrDescIndexable(addrDesc bchain.AddressDescriptor) bool {
if len(addrDesc) == 0 || addrDesc[0] == txscript.OP_RETURN {
return false
}
return true
}
// addressToOutputScript converts bitcoin address to ScriptPubKey
func (p *BitcoinLikeParser) addressToOutputScript(address string) ([]byte, error) {
da, err := btcutil.DecodeAddress(address, p.Params)
if err != nil {
return nil, err
}
script, err := txscript.PayToAddrScript(da)
if err != nil {
return nil, err
}
return script, nil
}
// TryParseOPReturn tries to process OP_RETURN script and return its string representation
func (p *BitcoinLikeParser) TryParseOPReturn(script []byte) string {
if len(script) > 1 && script[0] == txscript.OP_RETURN {
// trying 2 variants of OP_RETURN data
// 1) OP_RETURN OP_PUSHDATA1 <datalen> <data>
// 2) OP_RETURN <datalen> <data>
// 3) OP_RETURN OP_PUSHDATA2 <datalenlow> <datalenhigh> <data>
var data []byte
var l int
if script[1] == txscript.OP_PUSHDATA1 && len(script) > 2 {
l = int(script[2])
data = script[3:]
if l != len(data) {
l = int(script[1])
data = script[2:]
}
} else if script[1] == txscript.OP_PUSHDATA2 && len(script) > 3 {
l = int(script[2]) + int(script[3])<<8
data = script[4:]
} else {
l = int(script[1])
data = script[2:]
}
if l == len(data) {
var ed string
ed = p.tryParseOmni(data)
if ed != "" {
return ed
}
if utf8.Valid(data) {
ed = "(" + string(data) + ")"
} else {
ed = hex.EncodeToString(data)
}
return "OP_RETURN " + ed
}
}
return ""
}
var omniCurrencyMap = map[uint32]string{
1: "Omni",
2: "Test Omni",
31: "TetherUS",
}
// tryParseOmni tries to extract Omni simple send transaction from script
func (p *BitcoinLikeParser) tryParseOmni(data []byte) string {
// currently only simple send transaction version 0 is supported, see
// https://github.com/OmniLayer/spec#transfer-coins-simple-send
if len(data) != 20 || data[0] != 'o' {
return ""
}
// omni (4) <tx_version> (2) <tx_type> (2)
omniHeader := []byte{'o', 'm', 'n', 'i', 0, 0, 0, 0}
if !bytes.Equal(data[0:8], omniHeader) {
return ""
}
currencyID := binary.BigEndian.Uint32(data[8:12])
currency, ok := omniCurrencyMap[currencyID]
if !ok {
return ""
}
amount := new(big.Int)
amount.SetBytes(data[12:])
amountStr := p.AmountToDecimalString(amount)
ed := "OMNI Simple Send: " + amountStr + " " + currency + " (#" + strconv.Itoa(int(currencyID)) + ")"
return ed
}
// outputScriptToAddresses converts ScriptPubKey to addresses with a flag that the addresses are searchable
func (p *BitcoinLikeParser) outputScriptToAddresses(script []byte) ([]string, bool, error) {
sc, addresses, _, err := txscript.ExtractPkScriptAddrs(script, p.Params)
if err != nil {
return nil, false, err
}
rv := make([]string, len(addresses))
for i, a := range addresses {
rv[i] = a.EncodeAddress()
}
var s bool
if sc == txscript.PubKeyHashTy || sc == txscript.WitnessV0PubKeyHashTy || sc == txscript.ScriptHashTy || sc == txscript.WitnessV0ScriptHashTy {
s = true
} else if len(rv) == 0 {
or := p.TryParseOPReturn(script)
if or != "" {
rv = []string{or}
}
}
return rv, s, nil
}
// TxFromMsgTx converts bitcoin wire Tx to bchain.Tx
func (p *BitcoinLikeParser) TxFromMsgTx(t *wire.MsgTx, parseAddresses bool) bchain.Tx {
vin := make([]bchain.Vin, len(t.TxIn))
for i, in := range t.TxIn {
if blockchain.IsCoinBaseTx(t) {
vin[i] = bchain.Vin{
Coinbase: hex.EncodeToString(in.SignatureScript),
Sequence: in.Sequence,
}
break
}
s := bchain.ScriptSig{
Hex: hex.EncodeToString(in.SignatureScript),
// missing: Asm,
}
vin[i] = bchain.Vin{
Txid: in.PreviousOutPoint.Hash.String(),
Vout: in.PreviousOutPoint.Index,
Sequence: in.Sequence,
ScriptSig: s,
}
}
vout := make([]bchain.Vout, len(t.TxOut))
for i, out := range t.TxOut {
addrs := []string{}
if parseAddresses {
addrs, _, _ = p.OutputScriptToAddressesFunc(out.PkScript)
}
s := bchain.ScriptPubKey{
Hex: hex.EncodeToString(out.PkScript),
Addresses: addrs,
// missing: Asm,
// missing: Type,
}
var vs big.Int
vs.SetInt64(out.Value)
vout[i] = bchain.Vout{
ValueSat: vs,
N: uint32(i),
ScriptPubKey: s,
}
}
tx := bchain.Tx{
Txid: t.TxHash().String(),
Version: t.Version,
LockTime: t.LockTime,
Vin: vin,
Vout: vout,
// skip: BlockHash,
// skip: Confirmations,
// skip: Time,
// skip: Blocktime,
}
return tx
}
// ParseTx parses byte array containing transaction and returns Tx struct
func (p *BitcoinLikeParser) ParseTx(b []byte) (*bchain.Tx, error) {
t := wire.MsgTx{}
r := bytes.NewReader(b)
if err := t.Deserialize(r); err != nil {
return nil, err
}
tx := p.TxFromMsgTx(&t, true)
tx.Hex = hex.EncodeToString(b)
return &tx, nil
}
// ParseBlock parses raw block to our Block struct
func (p *BitcoinLikeParser) ParseBlock(b []byte) (*bchain.Block, error) {
w := wire.MsgBlock{}
r := bytes.NewReader(b)
if err := w.Deserialize(r); err != nil {
return nil, err
}
txs := make([]bchain.Tx, len(w.Transactions))
for ti, t := range w.Transactions {
txs[ti] = p.TxFromMsgTx(t, false)
}
return &bchain.Block{
BlockHeader: bchain.BlockHeader{
Size: len(b),
Time: w.Header.Timestamp.Unix(),
},
Txs: txs,
}, nil
}
// PackTx packs transaction to byte array
func (p *BitcoinLikeParser) PackTx(tx *bchain.Tx, height uint32, blockTime int64) ([]byte, error) {
buf := make([]byte, 4+vlq.MaxLen64+len(tx.Hex)/2)
binary.BigEndian.PutUint32(buf[0:4], height)
vl := vlq.PutInt(buf[4:4+vlq.MaxLen64], blockTime)
hl, err := hex.Decode(buf[4+vl:], []byte(tx.Hex))
return buf[0 : 4+vl+hl], err
}
// UnpackTx unpacks transaction from byte array
func (p *BitcoinLikeParser) UnpackTx(buf []byte) (*bchain.Tx, uint32, error) {
height := binary.BigEndian.Uint32(buf)
bt, l := vlq.Int(buf[4:])
tx, err := p.ParseTx(buf[4+l:])
if err != nil {
return nil, 0, err
}
tx.Blocktime = bt
return tx, height, nil
}
// MinimumCoinbaseConfirmations returns minimum number of confirmations a coinbase transaction must have before it can be spent
func (p *BitcoinLikeParser) MinimumCoinbaseConfirmations() int {
return p.minimumCoinbaseConfirmations
}
func (p *BitcoinLikeParser) addrDescFromExtKey(extKey *hdkeychain.ExtendedKey) (bchain.AddressDescriptor, error) {
var a btcutil.Address
var err error
if extKey.Version() == p.XPubMagicSegwitP2sh {
// redeemScript <witness version: OP_0><len pubKeyHash: 20><20-byte-pubKeyHash>
pubKeyHash := btcutil.Hash160(extKey.PubKeyBytes())
redeemScript := make([]byte, len(pubKeyHash)+2)
redeemScript[0] = 0
redeemScript[1] = byte(len(pubKeyHash))
copy(redeemScript[2:], pubKeyHash)
hash := btcutil.Hash160(redeemScript)
a, err = btcutil.NewAddressScriptHashFromHash(hash, p.Params)
} else if extKey.Version() == p.XPubMagicSegwitNative {
a, err = btcutil.NewAddressWitnessPubKeyHash(btcutil.Hash160(extKey.PubKeyBytes()), p.Params)
} else {
// default to P2PKH address
a, err = extKey.Address(p.Params)
}
if err != nil {
return nil, err
}
return txscript.PayToAddrScript(a)
}
// DeriveAddressDescriptors derives address descriptors from given xpub for listed indexes
func (p *BitcoinLikeParser) DeriveAddressDescriptors(xpub string, change uint32, indexes []uint32) ([]bchain.AddressDescriptor, error) {
extKey, err := hdkeychain.NewKeyFromString(xpub, p.Params.Base58CksumHasher)
if err != nil {
return nil, err
}
changeExtKey, err := extKey.Child(change)
if err != nil {
return nil, err
}
ad := make([]bchain.AddressDescriptor, len(indexes))
for i, index := range indexes {
indexExtKey, err := changeExtKey.Child(index)
if err != nil {
return nil, err
}
ad[i], err = p.addrDescFromExtKey(indexExtKey)
if err != nil {
return nil, err
}
}
return ad, nil
}
// DeriveAddressDescriptorsFromTo derives address descriptors from given xpub for addresses in index range
func (p *BitcoinLikeParser) DeriveAddressDescriptorsFromTo(xpub string, change uint32, fromIndex uint32, toIndex uint32) ([]bchain.AddressDescriptor, error) {
if toIndex <= fromIndex {
return nil, errors.New("toIndex<=fromIndex")
}
extKey, err := hdkeychain.NewKeyFromString(xpub, p.Params.Base58CksumHasher)
if err != nil {
return nil, err
}
changeExtKey, err := extKey.Child(change)
if err != nil {
return nil, err
}
ad := make([]bchain.AddressDescriptor, toIndex-fromIndex)
for index := fromIndex; index < toIndex; index++ {
indexExtKey, err := changeExtKey.Child(index)
if err != nil {
return nil, err
}
ad[index-fromIndex], err = p.addrDescFromExtKey(indexExtKey)
if err != nil {
return nil, err
}
}
return ad, nil
}
// DerivationBasePath returns base path of xpub
func (p *BitcoinLikeParser) DerivationBasePath(xpub string) (string, error) {
extKey, err := hdkeychain.NewKeyFromString(xpub, p.Params.Base58CksumHasher)
if err != nil {
return "", err
}
var c, bip string
cn := extKey.ChildNum()
if cn >= 0x80000000 {
cn -= 0x80000000
c = "'"
}
c = strconv.Itoa(int(cn)) + c
if extKey.Depth() != 3 {
return "unknown/" + c, nil
}
if extKey.Version() == p.XPubMagicSegwitP2sh {
bip = "49"
} else if extKey.Version() == p.XPubMagicSegwitNative {
bip = "84"
} else {
bip = "44"
}
return "m/" + bip + "'/" + strconv.Itoa(int(p.Slip44)) + "'/" + c, nil
}

View File

@ -1,22 +1,13 @@
package btc package btc
import ( import (
"bytes" "encoding/json"
"encoding/binary"
"encoding/hex"
"math/big" "math/big"
"strconv"
"unicode/utf8"
vlq "github.com/bsm/go-vlq"
"github.com/juju/errors"
"github.com/martinboehm/btcd/blockchain"
"github.com/martinboehm/btcd/wire" "github.com/martinboehm/btcd/wire"
"github.com/martinboehm/btcutil"
"github.com/martinboehm/btcutil/chaincfg" "github.com/martinboehm/btcutil/chaincfg"
"github.com/martinboehm/btcutil/hdkeychain"
"github.com/martinboehm/btcutil/txscript"
"github.com/trezor/blockbook/bchain" "github.com/trezor/blockbook/bchain"
"github.com/trezor/blockbook/common"
) )
// temp params for signet(wait btcd commit) // temp params for signet(wait btcd commit)
@ -35,37 +26,16 @@ func init() {
SigNetParams.Net = SignetMagic SigNetParams.Net = SignetMagic
} }
// OutputScriptToAddressesFunc converts ScriptPubKey to bitcoin addresses
type OutputScriptToAddressesFunc func(script []byte) ([]string, bool, error)
// BitcoinParser handle // BitcoinParser handle
type BitcoinParser struct { type BitcoinParser struct {
*bchain.BaseParser *BitcoinLikeParser
Params *chaincfg.Params
OutputScriptToAddressesFunc OutputScriptToAddressesFunc
XPubMagic uint32
XPubMagicSegwitP2sh uint32
XPubMagicSegwitNative uint32
Slip44 uint32
minimumCoinbaseConfirmations int
} }
// NewBitcoinParser returns new BitcoinParser instance // NewBitcoinParser returns new BitcoinParser instance
func NewBitcoinParser(params *chaincfg.Params, c *Configuration) *BitcoinParser { func NewBitcoinParser(params *chaincfg.Params, c *Configuration) *BitcoinParser {
p := &BitcoinParser{ return &BitcoinParser{
BaseParser: &bchain.BaseParser{ BitcoinLikeParser: NewBitcoinLikeParser(params, c),
BlockAddressesToKeep: c.BlockAddressesToKeep,
AmountDecimalPoint: 8,
},
Params: params,
XPubMagic: c.XPubMagic,
XPubMagicSegwitP2sh: c.XPubMagicSegwitP2sh,
XPubMagicSegwitNative: c.XPubMagicSegwitNative,
Slip44: c.Slip44,
minimumCoinbaseConfirmations: c.MinimumCoinbaseConfirmations,
} }
p.OutputScriptToAddressesFunc = p.outputScriptToAddresses
return p
} }
// GetChainParams contains network parameters for the main Bitcoin network, // GetChainParams contains network parameters for the main Bitcoin network,
@ -86,366 +56,80 @@ func GetChainParams(chain string) *chaincfg.Params {
return &chaincfg.MainNetParams return &chaincfg.MainNetParams
} }
// GetAddrDescFromVout returns internal address representation (descriptor) of given transaction output // ScriptPubKey contains data about output script
func (p *BitcoinParser) GetAddrDescFromVout(output *bchain.Vout) (bchain.AddressDescriptor, error) { type ScriptPubKey struct {
ad, err := hex.DecodeString(output.ScriptPubKey.Hex) // Asm string `json:"asm"`
if err != nil { Hex string `json:"hex,omitempty"`
return ad, err // Type string `json:"type"`
} Addresses []string `json:"addresses"` // removed from Bitcoind 22.0.0
// convert possible P2PK script to P2PKH Address string `json:"address"` // used in Bitcoind 22.0.0
// so that all transactions by given public key are indexed together
return txscript.ConvertP2PKtoP2PKH(p.Params.Base58CksumHasher, ad)
} }
// GetAddrDescFromAddress returns internal address representation (descriptor) of given address // Vout contains data about tx output
func (p *BitcoinParser) GetAddrDescFromAddress(address string) (bchain.AddressDescriptor, error) { type Vout struct {
return p.addressToOutputScript(address) ValueSat big.Int
JsonValue common.JSONNumber `json:"value"`
N uint32 `json:"n"`
ScriptPubKey ScriptPubKey `json:"scriptPubKey"`
} }
// GetAddressesFromAddrDesc returns addresses for given address descriptor with flag if the addresses are searchable // Tx is blockchain transaction
func (p *BitcoinParser) GetAddressesFromAddrDesc(addrDesc bchain.AddressDescriptor) ([]string, bool, error) { // unnecessary fields are commented out to avoid overhead
return p.OutputScriptToAddressesFunc(addrDesc) type Tx struct {
Hex string `json:"hex"`
Txid string `json:"txid"`
Version int32 `json:"version"`
LockTime uint32 `json:"locktime"`
Vin []bchain.Vin `json:"vin"`
Vout []Vout `json:"vout"`
BlockHeight uint32 `json:"blockHeight,omitempty"`
// BlockHash string `json:"blockhash,omitempty"`
Confirmations uint32 `json:"confirmations,omitempty"`
Time int64 `json:"time,omitempty"`
Blocktime int64 `json:"blocktime,omitempty"`
CoinSpecificData interface{} `json:"-"`
} }
// GetScriptFromAddrDesc returns output script for given address descriptor // ParseTxFromJson parses JSON message containing transaction and returns Tx struct
func (p *BitcoinParser) GetScriptFromAddrDesc(addrDesc bchain.AddressDescriptor) ([]byte, error) { // Bitcoind version 22.0.0 removed ScriptPubKey.Addresses from the API and replaced it by a single Address
return addrDesc, nil func (p *BitcoinParser) ParseTxFromJson(msg json.RawMessage) (*bchain.Tx, error) {
} var bitcoinTx Tx
var tx bchain.Tx
// IsAddrDescIndexable returns true if AddressDescriptor should be added to index err := json.Unmarshal(msg, &bitcoinTx)
// empty or OP_RETURN scripts are not indexed
func (p *BitcoinParser) IsAddrDescIndexable(addrDesc bchain.AddressDescriptor) bool {
if len(addrDesc) == 0 || addrDesc[0] == txscript.OP_RETURN {
return false
}
return true
}
// addressToOutputScript converts bitcoin address to ScriptPubKey
func (p *BitcoinParser) addressToOutputScript(address string) ([]byte, error) {
da, err := btcutil.DecodeAddress(address, p.Params)
if err != nil { if err != nil {
return nil, err return nil, err
} }
script, err := txscript.PayToAddrScript(da)
if err != nil {
return nil, err
}
return script, nil
}
// TryParseOPReturn tries to process OP_RETURN script and return its string representation // it is necessary to copy bitcoinTx to Tx to make it compatible
func (p *BitcoinParser) TryParseOPReturn(script []byte) string { tx.Hex = bitcoinTx.Hex
if len(script) > 1 && script[0] == txscript.OP_RETURN { tx.Txid = bitcoinTx.Txid
// trying 2 variants of OP_RETURN data tx.Version = bitcoinTx.Version
// 1) OP_RETURN OP_PUSHDATA1 <datalen> <data> tx.LockTime = bitcoinTx.LockTime
// 2) OP_RETURN <datalen> <data> tx.Vin = bitcoinTx.Vin
// 3) OP_RETURN OP_PUSHDATA2 <datalenlow> <datalenhigh> <data> tx.BlockHeight = bitcoinTx.BlockHeight
var data []byte tx.Confirmations = bitcoinTx.Confirmations
var l int tx.Time = bitcoinTx.Time
if script[1] == txscript.OP_PUSHDATA1 && len(script) > 2 { tx.Blocktime = bitcoinTx.Blocktime
l = int(script[2]) tx.CoinSpecificData = bitcoinTx.CoinSpecificData
data = script[3:] tx.Vout = make([]bchain.Vout, len(bitcoinTx.Vout))
if l != len(data) {
l = int(script[1]) for i := range bitcoinTx.Vout {
data = script[2:] bitcoinVout := &bitcoinTx.Vout[i]
} vout := &tx.Vout[i]
} else if script[1] == txscript.OP_PUSHDATA2 && len(script) > 3 { // convert vout.JsonValue to big.Int and clear it, it is only temporary value used for unmarshal
l = int(script[2]) + int(script[3])<<8 vout.ValueSat, err = p.AmountToBigInt(bitcoinVout.JsonValue)
data = script[4:] if err != nil {
return nil, err
}
vout.N = bitcoinVout.N
vout.ScriptPubKey.Hex = bitcoinVout.ScriptPubKey.Hex
// convert single Address to Addresses if Addresses are empty
if len(bitcoinVout.ScriptPubKey.Addresses) == 0 {
vout.ScriptPubKey.Addresses = []string{bitcoinVout.ScriptPubKey.Address}
} else { } else {
l = int(script[1]) vout.ScriptPubKey.Addresses = bitcoinVout.ScriptPubKey.Addresses
data = script[2:]
}
if l == len(data) {
var ed string
ed = p.tryParseOmni(data)
if ed != "" {
return ed
}
if utf8.Valid(data) {
ed = "(" + string(data) + ")"
} else {
ed = hex.EncodeToString(data)
}
return "OP_RETURN " + ed
} }
} }
return ""
}
var omniCurrencyMap = map[uint32]string{
1: "Omni",
2: "Test Omni",
31: "TetherUS",
}
// tryParseOmni tries to extract Omni simple send transaction from script
func (p *BitcoinParser) tryParseOmni(data []byte) string {
// currently only simple send transaction version 0 is supported, see
// https://github.com/OmniLayer/spec#transfer-coins-simple-send
if len(data) != 20 || data[0] != 'o' {
return ""
}
// omni (4) <tx_version> (2) <tx_type> (2)
omniHeader := []byte{'o', 'm', 'n', 'i', 0, 0, 0, 0}
if bytes.Compare(data[0:8], omniHeader) != 0 {
return ""
}
currencyID := binary.BigEndian.Uint32(data[8:12])
currency, ok := omniCurrencyMap[currencyID]
if !ok {
return ""
}
amount := new(big.Int)
amount.SetBytes(data[12:])
amountStr := p.AmountToDecimalString(amount)
ed := "OMNI Simple Send: " + amountStr + " " + currency + " (#" + strconv.Itoa(int(currencyID)) + ")"
return ed
}
// outputScriptToAddresses converts ScriptPubKey to addresses with a flag that the addresses are searchable
func (p *BitcoinParser) outputScriptToAddresses(script []byte) ([]string, bool, error) {
sc, addresses, _, err := txscript.ExtractPkScriptAddrs(script, p.Params)
if err != nil {
return nil, false, err
}
rv := make([]string, len(addresses))
for i, a := range addresses {
rv[i] = a.EncodeAddress()
}
var s bool
if sc == txscript.PubKeyHashTy || sc == txscript.WitnessV0PubKeyHashTy || sc == txscript.ScriptHashTy || sc == txscript.WitnessV0ScriptHashTy {
s = true
} else if len(rv) == 0 {
or := p.TryParseOPReturn(script)
if or != "" {
rv = []string{or}
}
}
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 {
if blockchain.IsCoinBaseTx(t) {
vin[i] = bchain.Vin{
Coinbase: hex.EncodeToString(in.SignatureScript),
Sequence: in.Sequence,
}
break
}
s := bchain.ScriptSig{
Hex: hex.EncodeToString(in.SignatureScript),
// missing: Asm,
}
vin[i] = bchain.Vin{
Txid: in.PreviousOutPoint.Hash.String(),
Vout: in.PreviousOutPoint.Index,
Sequence: in.Sequence,
ScriptSig: s,
}
}
vout := make([]bchain.Vout, len(t.TxOut))
for i, out := range t.TxOut {
addrs := []string{}
if parseAddresses {
addrs, _, _ = p.OutputScriptToAddressesFunc(out.PkScript)
}
s := bchain.ScriptPubKey{
Hex: hex.EncodeToString(out.PkScript),
Addresses: addrs,
// missing: Asm,
// missing: Type,
}
var vs big.Int
vs.SetInt64(out.Value)
vout[i] = bchain.Vout{
ValueSat: vs,
N: uint32(i),
ScriptPubKey: s,
}
}
tx := bchain.Tx{
Txid: t.TxHash().String(),
Version: t.Version,
LockTime: t.LockTime,
Vin: vin,
Vout: vout,
// skip: BlockHash,
// skip: Confirmations,
// skip: Time,
// skip: Blocktime,
}
return tx
}
// ParseTx parses byte array containing transaction and returns Tx struct
func (p *BitcoinParser) ParseTx(b []byte) (*bchain.Tx, error) {
t := wire.MsgTx{}
r := bytes.NewReader(b)
if err := t.Deserialize(r); err != nil {
return nil, err
}
tx := p.TxFromMsgTx(&t, true)
tx.Hex = hex.EncodeToString(b)
return &tx, nil return &tx, nil
} }
// ParseBlock parses raw block to our Block struct
func (p *BitcoinParser) ParseBlock(b []byte) (*bchain.Block, error) {
w := wire.MsgBlock{}
r := bytes.NewReader(b)
if err := w.Deserialize(r); err != nil {
return nil, err
}
txs := make([]bchain.Tx, len(w.Transactions))
for ti, t := range w.Transactions {
txs[ti] = p.TxFromMsgTx(t, false)
}
return &bchain.Block{
BlockHeader: bchain.BlockHeader{
Size: len(b),
Time: w.Header.Timestamp.Unix(),
},
Txs: txs,
}, nil
}
// PackTx packs transaction to byte array
func (p *BitcoinParser) PackTx(tx *bchain.Tx, height uint32, blockTime int64) ([]byte, error) {
buf := make([]byte, 4+vlq.MaxLen64+len(tx.Hex)/2)
binary.BigEndian.PutUint32(buf[0:4], height)
vl := vlq.PutInt(buf[4:4+vlq.MaxLen64], blockTime)
hl, err := hex.Decode(buf[4+vl:], []byte(tx.Hex))
return buf[0 : 4+vl+hl], err
}
// UnpackTx unpacks transaction from byte array
func (p *BitcoinParser) UnpackTx(buf []byte) (*bchain.Tx, uint32, error) {
height := binary.BigEndian.Uint32(buf)
bt, l := vlq.Int(buf[4:])
tx, err := p.ParseTx(buf[4+l:])
if err != nil {
return nil, 0, err
}
tx.Blocktime = bt
return tx, height, nil
}
// MinimumCoinbaseConfirmations returns minimum number of confirmations a coinbase transaction must have before it can be spent
func (p *BitcoinParser) MinimumCoinbaseConfirmations() int {
return p.minimumCoinbaseConfirmations
}
func (p *BitcoinParser) addrDescFromExtKey(extKey *hdkeychain.ExtendedKey) (bchain.AddressDescriptor, error) {
var a btcutil.Address
var err error
if extKey.Version() == p.XPubMagicSegwitP2sh {
// redeemScript <witness version: OP_0><len pubKeyHash: 20><20-byte-pubKeyHash>
pubKeyHash := btcutil.Hash160(extKey.PubKeyBytes())
redeemScript := make([]byte, len(pubKeyHash)+2)
redeemScript[0] = 0
redeemScript[1] = byte(len(pubKeyHash))
copy(redeemScript[2:], pubKeyHash)
hash := btcutil.Hash160(redeemScript)
a, err = btcutil.NewAddressScriptHashFromHash(hash, p.Params)
} else if extKey.Version() == p.XPubMagicSegwitNative {
a, err = btcutil.NewAddressWitnessPubKeyHash(btcutil.Hash160(extKey.PubKeyBytes()), p.Params)
} else {
// default to P2PKH address
a, err = extKey.Address(p.Params)
}
if err != nil {
return nil, err
}
return txscript.PayToAddrScript(a)
}
// DeriveAddressDescriptors derives address descriptors from given xpub for listed indexes
func (p *BitcoinParser) DeriveAddressDescriptors(xpub string, change uint32, indexes []uint32) ([]bchain.AddressDescriptor, error) {
extKey, err := hdkeychain.NewKeyFromString(xpub, p.Params.Base58CksumHasher)
if err != nil {
return nil, err
}
changeExtKey, err := extKey.Child(change)
if err != nil {
return nil, err
}
ad := make([]bchain.AddressDescriptor, len(indexes))
for i, index := range indexes {
indexExtKey, err := changeExtKey.Child(index)
if err != nil {
return nil, err
}
ad[i], err = p.addrDescFromExtKey(indexExtKey)
if err != nil {
return nil, err
}
}
return ad, nil
}
// DeriveAddressDescriptorsFromTo derives address descriptors from given xpub for addresses in index range
func (p *BitcoinParser) DeriveAddressDescriptorsFromTo(xpub string, change uint32, fromIndex uint32, toIndex uint32) ([]bchain.AddressDescriptor, error) {
if toIndex <= fromIndex {
return nil, errors.New("toIndex<=fromIndex")
}
extKey, err := hdkeychain.NewKeyFromString(xpub, p.Params.Base58CksumHasher)
if err != nil {
return nil, err
}
changeExtKey, err := extKey.Child(change)
if err != nil {
return nil, err
}
ad := make([]bchain.AddressDescriptor, toIndex-fromIndex)
for index := fromIndex; index < toIndex; index++ {
indexExtKey, err := changeExtKey.Child(index)
if err != nil {
return nil, err
}
ad[index-fromIndex], err = p.addrDescFromExtKey(indexExtKey)
if err != nil {
return nil, err
}
}
return ad, nil
}
// DerivationBasePath returns base path of xpub
func (p *BitcoinParser) DerivationBasePath(xpub string) (string, error) {
extKey, err := hdkeychain.NewKeyFromString(xpub, p.Params.Base58CksumHasher)
if err != nil {
return "", err
}
var c, bip string
cn := extKey.ChildNum()
if cn >= 0x80000000 {
cn -= 0x80000000
c = "'"
}
c = strconv.Itoa(int(cn)) + c
if extKey.Depth() != 3 {
return "unknown/" + c, nil
}
if extKey.Version() == p.XPubMagicSegwitP2sh {
bip = "49"
} else if extKey.Version() == p.XPubMagicSegwitNative {
bip = "84"
} else {
bip = "44"
}
return "m/" + bip + "'/" + strconv.Itoa(int(p.Slip44)) + "'/" + c, nil
}

View File

@ -47,12 +47,12 @@ func init() {
// BGoldParser handle // BGoldParser handle
type BGoldParser struct { type BGoldParser struct {
*btc.BitcoinParser *btc.BitcoinLikeParser
} }
// NewBGoldParser returns new BGoldParser instance // NewBGoldParser returns new BGoldParser instance
func NewBGoldParser(params *chaincfg.Params, c *btc.Configuration) *BGoldParser { func NewBGoldParser(params *chaincfg.Params, c *btc.Configuration) *BGoldParser {
return &BGoldParser{BitcoinParser: btc.NewBitcoinParser(params, c)} return &BGoldParser{BitcoinLikeParser: btc.NewBitcoinLikeParser(params, c)}
} }
// GetChainParams contains network parameters for the main Bitcoin Cash network, // GetChainParams contains network parameters for the main Bitcoin Cash network,

View File

@ -34,12 +34,12 @@ func init() {
// CPUchainParser handle // CPUchainParser handle
type CPUchainParser struct { type CPUchainParser struct {
*btc.BitcoinParser *btc.BitcoinLikeParser
} }
// NewCPUchainParser returns new CPUchainParser instance // NewCPUchainParser returns new CPUchainParser instance
func NewCPUchainParser(params *chaincfg.Params, c *btc.Configuration) *CPUchainParser { func NewCPUchainParser(params *chaincfg.Params, c *btc.Configuration) *CPUchainParser {
return &CPUchainParser{BitcoinParser: btc.NewBitcoinParser(params, c)} return &CPUchainParser{BitcoinLikeParser: btc.NewBitcoinLikeParser(params, c)}
} }
// GetChainParams contains network parameters for the main CPUchain network, // GetChainParams contains network parameters for the main CPUchain network,

View File

@ -50,15 +50,15 @@ func init() {
// DashParser handle // DashParser handle
type DashParser struct { type DashParser struct {
*btc.BitcoinParser *btc.BitcoinLikeParser
baseparser *bchain.BaseParser baseparser *bchain.BaseParser
} }
// NewDashParser returns new DashParser instance // NewDashParser returns new DashParser instance
func NewDashParser(params *chaincfg.Params, c *btc.Configuration) *DashParser { func NewDashParser(params *chaincfg.Params, c *btc.Configuration) *DashParser {
return &DashParser{ return &DashParser{
BitcoinParser: btc.NewBitcoinParser(params, c), BitcoinLikeParser: btc.NewBitcoinLikeParser(params, c),
baseparser: &bchain.BaseParser{}, baseparser: &bchain.BaseParser{},
} }
} }

View File

@ -52,7 +52,7 @@ func init() {
// DecredParser handle // DecredParser handle
type DecredParser struct { type DecredParser struct {
*btc.BitcoinParser *btc.BitcoinLikeParser
baseParser *bchain.BaseParser baseParser *bchain.BaseParser
netConfig *cfg.Params netConfig *cfg.Params
} }
@ -60,11 +60,11 @@ type DecredParser struct {
// NewDecredParser returns new DecredParser instance // NewDecredParser returns new DecredParser instance
func NewDecredParser(params *chaincfg.Params, c *btc.Configuration) *DecredParser { func NewDecredParser(params *chaincfg.Params, c *btc.Configuration) *DecredParser {
d := &DecredParser{ d := &DecredParser{
BitcoinParser: btc.NewBitcoinParser(params, c), BitcoinLikeParser: btc.NewBitcoinLikeParser(params, c),
baseParser: &bchain.BaseParser{}, baseParser: &bchain.BaseParser{},
} }
switch d.BitcoinParser.Params.Name { switch d.BitcoinLikeParser.Params.Name {
case "testnet3": case "testnet3":
d.netConfig = cfg.TestNet3Params() d.netConfig = cfg.TestNet3Params()
default: default:
@ -213,7 +213,7 @@ func (p *DecredParser) GetAddrDescFromVout(output *bchain.Vout) (bchain.AddressD
} }
if scriptClass.String() == "nulldata" { if scriptClass.String() == "nulldata" {
if parsedOPReturn := p.BitcoinParser.TryParseOPReturn(script); parsedOPReturn != "" { if parsedOPReturn := p.BitcoinLikeParser.TryParseOPReturn(script); parsedOPReturn != "" {
return []byte(parsedOPReturn), nil return []byte(parsedOPReturn), nil
} }
} }

View File

@ -27,15 +27,15 @@ func init() {
// DeepOnionParser handle // DeepOnionParser handle
type DeepOnionParser struct { type DeepOnionParser struct {
*btc.BitcoinParser *btc.BitcoinLikeParser
baseparser *bchain.BaseParser baseparser *bchain.BaseParser
} }
// NewDeepOnionParser returns new DeepOnionParser instance // NewDeepOnionParser returns new DeepOnionParser instance
func NewDeepOnionParser(params *chaincfg.Params, c *btc.Configuration) *DeepOnionParser { func NewDeepOnionParser(params *chaincfg.Params, c *btc.Configuration) *DeepOnionParser {
return &DeepOnionParser{ return &DeepOnionParser{
BitcoinParser: btc.NewBitcoinParser(params, c), BitcoinLikeParser: btc.NewBitcoinLikeParser(params, c),
baseparser: &bchain.BaseParser{}, baseparser: &bchain.BaseParser{},
} }
} }

View File

@ -34,12 +34,12 @@ func init() {
// DigiByteParser handle // DigiByteParser handle
type DigiByteParser struct { type DigiByteParser struct {
*btc.BitcoinParser *btc.BitcoinLikeParser
} }
// NewDigiByteParser returns new DigiByteParser instance // NewDigiByteParser returns new DigiByteParser instance
func NewDigiByteParser(params *chaincfg.Params, c *btc.Configuration) *DigiByteParser { func NewDigiByteParser(params *chaincfg.Params, c *btc.Configuration) *DigiByteParser {
return &DigiByteParser{BitcoinParser: btc.NewBitcoinParser(params, c)} return &DigiByteParser{BitcoinLikeParser: btc.NewBitcoinLikeParser(params, c)}
} }
// GetChainParams contains network parameters for the main DigiByte network // GetChainParams contains network parameters for the main DigiByte network

View File

@ -37,7 +37,7 @@ func init() {
// DivicoinParser handle // DivicoinParser handle
type DivicoinParser struct { type DivicoinParser struct {
*btc.BitcoinParser *btc.BitcoinLikeParser
baseparser *bchain.BaseParser baseparser *bchain.BaseParser
BitcoinOutputScriptToAddressesFunc btc.OutputScriptToAddressesFunc BitcoinOutputScriptToAddressesFunc btc.OutputScriptToAddressesFunc
} }
@ -45,8 +45,8 @@ type DivicoinParser struct {
// NewDiviParser returns new DivicoinParser instance // NewDiviParser returns new DivicoinParser instance
func NewDiviParser(params *chaincfg.Params, c *btc.Configuration) *DivicoinParser { func NewDiviParser(params *chaincfg.Params, c *btc.Configuration) *DivicoinParser {
p := &DivicoinParser{ p := &DivicoinParser{
BitcoinParser: btc.NewBitcoinParser(params, c), BitcoinLikeParser: btc.NewBitcoinLikeParser(params, c),
baseparser: &bchain.BaseParser{}, baseparser: &bchain.BaseParser{},
} }
p.BitcoinOutputScriptToAddressesFunc = p.OutputScriptToAddressesFunc p.BitcoinOutputScriptToAddressesFunc = p.OutputScriptToAddressesFunc
p.OutputScriptToAddressesFunc = p.outputScriptToAddresses p.OutputScriptToAddressesFunc = p.outputScriptToAddresses

View File

@ -36,12 +36,12 @@ func init() {
// DogecoinParser handle // DogecoinParser handle
type DogecoinParser struct { type DogecoinParser struct {
*btc.BitcoinParser *btc.BitcoinLikeParser
} }
// NewDogecoinParser returns new DogecoinParser instance // NewDogecoinParser returns new DogecoinParser instance
func NewDogecoinParser(params *chaincfg.Params, c *btc.Configuration) *DogecoinParser { func NewDogecoinParser(params *chaincfg.Params, c *btc.Configuration) *DogecoinParser {
return &DogecoinParser{BitcoinParser: btc.NewBitcoinParser(params, c)} return &DogecoinParser{BitcoinLikeParser: btc.NewBitcoinLikeParser(params, c)}
} }
// GetChainParams contains network parameters for the main Dogecoin network, // GetChainParams contains network parameters for the main Dogecoin network,

View File

@ -65,13 +65,13 @@ func init() {
// FiroParser handle // FiroParser handle
type FiroParser struct { type FiroParser struct {
*btc.BitcoinParser *btc.BitcoinLikeParser
} }
// NewFiroParser returns new FiroParser instance // NewFiroParser returns new FiroParser instance
func NewFiroParser(params *chaincfg.Params, c *btc.Configuration) *FiroParser { func NewFiroParser(params *chaincfg.Params, c *btc.Configuration) *FiroParser {
return &FiroParser{ return &FiroParser{
BitcoinParser: btc.NewBitcoinParser(params, c), BitcoinLikeParser: btc.NewBitcoinLikeParser(params, c),
} }
} }

View File

@ -36,15 +36,15 @@ func init() {
// FloParser handle // FloParser handle
type FloParser struct { type FloParser struct {
*btc.BitcoinParser *btc.BitcoinLikeParser
baseparser *bchain.BaseParser baseparser *bchain.BaseParser
} }
// NewFloParser returns new FloParser instance // NewFloParser returns new FloParser instance
func NewFloParser(params *chaincfg.Params, c *btc.Configuration) *FloParser { func NewFloParser(params *chaincfg.Params, c *btc.Configuration) *FloParser {
return &FloParser{ return &FloParser{
BitcoinParser: btc.NewBitcoinParser(params, c), BitcoinLikeParser: btc.NewBitcoinLikeParser(params, c),
baseparser: &bchain.BaseParser{}, baseparser: &bchain.BaseParser{},
} }
} }

View File

@ -38,12 +38,12 @@ func init() {
// FujicoinParser handle // FujicoinParser handle
type FujicoinParser struct { type FujicoinParser struct {
*btc.BitcoinParser *btc.BitcoinLikeParser
} }
// NewFujicoinParser returns new FujicoinParser instance // NewFujicoinParser returns new FujicoinParser instance
func NewFujicoinParser(params *chaincfg.Params, c *btc.Configuration) *FujicoinParser { func NewFujicoinParser(params *chaincfg.Params, c *btc.Configuration) *FujicoinParser {
return &FujicoinParser{BitcoinParser: btc.NewBitcoinParser(params, c)} return &FujicoinParser{BitcoinLikeParser: btc.NewBitcoinLikeParser(params, c)}
} }
// GetChainParams contains network parameters for the main Fujicoin network, // GetChainParams contains network parameters for the main Fujicoin network,

View File

@ -35,12 +35,12 @@ func init() {
// GameCreditsParser handle // GameCreditsParser handle
type GameCreditsParser struct { type GameCreditsParser struct {
*btc.BitcoinParser *btc.BitcoinLikeParser
} }
// NewGameCreditsParser returns new GameCreditsParser instance // NewGameCreditsParser returns new GameCreditsParser instance
func NewGameCreditsParser(params *chaincfg.Params, c *btc.Configuration) *GameCreditsParser { func NewGameCreditsParser(params *chaincfg.Params, c *btc.Configuration) *GameCreditsParser {
return &GameCreditsParser{BitcoinParser: btc.NewBitcoinParser(params, c)} return &GameCreditsParser{BitcoinLikeParser: btc.NewBitcoinLikeParser(params, c)}
} }
// GetChainParams contains network parameters for the main GameCredits network, // GetChainParams contains network parameters for the main GameCredits network,

View File

@ -42,15 +42,15 @@ func init() {
// GroestlcoinParser handle // GroestlcoinParser handle
type GroestlcoinParser struct { type GroestlcoinParser struct {
*btc.BitcoinParser *btc.BitcoinLikeParser
baseparser *bchain.BaseParser baseparser *bchain.BaseParser
} }
// NewGroestlcoinParser returns new GroestlcoinParser instance // NewGroestlcoinParser returns new GroestlcoinParser instance
func NewGroestlcoinParser(params *chaincfg.Params, c *btc.Configuration) *GroestlcoinParser { func NewGroestlcoinParser(params *chaincfg.Params, c *btc.Configuration) *GroestlcoinParser {
return &GroestlcoinParser{ return &GroestlcoinParser{
BitcoinParser: btc.NewBitcoinParser(params, c), BitcoinLikeParser: btc.NewBitcoinLikeParser(params, c),
baseparser: &bchain.BaseParser{}, baseparser: &bchain.BaseParser{},
} }
} }

View File

@ -44,15 +44,15 @@ func init() {
// KotoParser handle // KotoParser handle
type KotoParser struct { type KotoParser struct {
*btc.BitcoinParser *btc.BitcoinLikeParser
baseparser *bchain.BaseParser baseparser *bchain.BaseParser
} }
// NewKotoParser returns new KotoParser instance // NewKotoParser returns new KotoParser instance
func NewKotoParser(params *chaincfg.Params, c *btc.Configuration) *KotoParser { func NewKotoParser(params *chaincfg.Params, c *btc.Configuration) *KotoParser {
return &KotoParser{ return &KotoParser{
BitcoinParser: btc.NewBitcoinParser(params, c), BitcoinLikeParser: btc.NewBitcoinLikeParser(params, c),
baseparser: &bchain.BaseParser{}, baseparser: &bchain.BaseParser{},
} }
} }

View File

@ -32,7 +32,7 @@ func init() {
// LiquidParser handle // LiquidParser handle
type LiquidParser struct { type LiquidParser struct {
*btc.BitcoinParser *btc.BitcoinLikeParser
baseparser *bchain.BaseParser baseparser *bchain.BaseParser
origOutputScriptToAddressesFunc btc.OutputScriptToAddressesFunc origOutputScriptToAddressesFunc btc.OutputScriptToAddressesFunc
} }
@ -40,8 +40,8 @@ type LiquidParser struct {
// NewLiquidParser returns new LiquidParser instance // NewLiquidParser returns new LiquidParser instance
func NewLiquidParser(params *chaincfg.Params, c *btc.Configuration) *LiquidParser { func NewLiquidParser(params *chaincfg.Params, c *btc.Configuration) *LiquidParser {
p := &LiquidParser{ p := &LiquidParser{
BitcoinParser: btc.NewBitcoinParser(params, c), BitcoinLikeParser: btc.NewBitcoinLikeParser(params, c),
baseparser: &bchain.BaseParser{}, baseparser: &bchain.BaseParser{},
} }
p.origOutputScriptToAddressesFunc = p.OutputScriptToAddressesFunc p.origOutputScriptToAddressesFunc = p.OutputScriptToAddressesFunc
p.OutputScriptToAddressesFunc = p.outputScriptToAddresses p.OutputScriptToAddressesFunc = p.outputScriptToAddresses

View File

@ -35,12 +35,12 @@ func init() {
// LitecoinParser handle // LitecoinParser handle
type LitecoinParser struct { type LitecoinParser struct {
*btc.BitcoinParser *btc.BitcoinLikeParser
} }
// NewLitecoinParser returns new LitecoinParser instance // NewLitecoinParser returns new LitecoinParser instance
func NewLitecoinParser(params *chaincfg.Params, c *btc.Configuration) *LitecoinParser { func NewLitecoinParser(params *chaincfg.Params, c *btc.Configuration) *LitecoinParser {
return &LitecoinParser{BitcoinParser: btc.NewBitcoinParser(params, c)} return &LitecoinParser{BitcoinLikeParser: btc.NewBitcoinLikeParser(params, c)}
} }
// GetChainParams contains network parameters for the main Litecoin network, // GetChainParams contains network parameters for the main Litecoin network,

View File

@ -34,12 +34,12 @@ func init() {
// MonacoinParser handle // MonacoinParser handle
type MonacoinParser struct { type MonacoinParser struct {
*btc.BitcoinParser *btc.BitcoinLikeParser
} }
// NewMonacoinParser returns new MonacoinParser instance // NewMonacoinParser returns new MonacoinParser instance
func NewMonacoinParser(params *chaincfg.Params, c *btc.Configuration) *MonacoinParser { func NewMonacoinParser(params *chaincfg.Params, c *btc.Configuration) *MonacoinParser {
return &MonacoinParser{BitcoinParser: btc.NewBitcoinParser(params, c)} return &MonacoinParser{BitcoinLikeParser: btc.NewBitcoinLikeParser(params, c)}
} }
// GetChainParams contains network parameters for the main Monacoin network, // GetChainParams contains network parameters for the main Monacoin network,

View File

@ -43,7 +43,7 @@ func init() {
// MonetaryUnitParser handle // MonetaryUnitParser handle
type MonetaryUnitParser struct { type MonetaryUnitParser struct {
*btc.BitcoinParser *btc.BitcoinLikeParser
baseparser *bchain.BaseParser baseparser *bchain.BaseParser
BitcoinOutputScriptToAddressesFunc btc.OutputScriptToAddressesFunc BitcoinOutputScriptToAddressesFunc btc.OutputScriptToAddressesFunc
} }
@ -51,8 +51,8 @@ type MonetaryUnitParser struct {
// NewMonetaryUnitParser returns new MonetaryUnitParser instance // NewMonetaryUnitParser returns new MonetaryUnitParser instance
func NewMonetaryUnitParser(params *chaincfg.Params, c *btc.Configuration) *MonetaryUnitParser { func NewMonetaryUnitParser(params *chaincfg.Params, c *btc.Configuration) *MonetaryUnitParser {
p := &MonetaryUnitParser{ p := &MonetaryUnitParser{
BitcoinParser: btc.NewBitcoinParser(params, c), BitcoinLikeParser: btc.NewBitcoinLikeParser(params, c),
baseparser: &bchain.BaseParser{}, baseparser: &bchain.BaseParser{},
} }
p.BitcoinOutputScriptToAddressesFunc = p.OutputScriptToAddressesFunc p.BitcoinOutputScriptToAddressesFunc = p.OutputScriptToAddressesFunc
p.OutputScriptToAddressesFunc = p.outputScriptToAddresses p.OutputScriptToAddressesFunc = p.outputScriptToAddresses

View File

@ -35,12 +35,12 @@ func init() {
// MyriadParser handle // MyriadParser handle
type MyriadParser struct { type MyriadParser struct {
*btc.BitcoinParser *btc.BitcoinLikeParser
} }
// NewMyriadParser returns new MyriadParser instance // NewMyriadParser returns new MyriadParser instance
func NewMyriadParser(params *chaincfg.Params, c *btc.Configuration) *MyriadParser { func NewMyriadParser(params *chaincfg.Params, c *btc.Configuration) *MyriadParser {
return &MyriadParser{BitcoinParser: btc.NewBitcoinParser(params, c)} return &MyriadParser{BitcoinLikeParser: btc.NewBitcoinLikeParser(params, c)}
} }
// GetChainParams contains network parameters for the main Myriad network // GetChainParams contains network parameters for the main Myriad network

View File

@ -29,12 +29,12 @@ func init() {
// NamecoinParser handle // NamecoinParser handle
type NamecoinParser struct { type NamecoinParser struct {
*btc.BitcoinParser *btc.BitcoinLikeParser
} }
// NewNamecoinParser returns new NamecoinParser instance // NewNamecoinParser returns new NamecoinParser instance
func NewNamecoinParser(params *chaincfg.Params, c *btc.Configuration) *NamecoinParser { func NewNamecoinParser(params *chaincfg.Params, c *btc.Configuration) *NamecoinParser {
return &NamecoinParser{BitcoinParser: btc.NewBitcoinParser(params, c)} return &NamecoinParser{BitcoinLikeParser: btc.NewBitcoinLikeParser(params, c)}
} }
// GetChainParams contains network parameters for the main Namecoin network, // GetChainParams contains network parameters for the main Namecoin network,

View File

@ -59,12 +59,12 @@ func init() {
// NulsParser handle // NulsParser handle
type NulsParser struct { type NulsParser struct {
*btc.BitcoinParser *btc.BitcoinLikeParser
} }
// NewNulsParser returns new NulsParser instance // NewNulsParser returns new NulsParser instance
func NewNulsParser(params *chaincfg.Params, c *btc.Configuration) *NulsParser { func NewNulsParser(params *chaincfg.Params, c *btc.Configuration) *NulsParser {
return &NulsParser{BitcoinParser: btc.NewBitcoinParser(params, c)} return &NulsParser{BitcoinLikeParser: btc.NewBitcoinLikeParser(params, c)}
} }
// GetChainParams contains network parameters for the main Gincoin network, // GetChainParams contains network parameters for the main Gincoin network,

View File

@ -50,7 +50,7 @@ func init() {
// OmotenashiCoinParser handle // OmotenashiCoinParser handle
type OmotenashiCoinParser struct { type OmotenashiCoinParser struct {
*btc.BitcoinParser *btc.BitcoinLikeParser
baseparser *bchain.BaseParser baseparser *bchain.BaseParser
BitcoinOutputScriptToAddressesFunc btc.OutputScriptToAddressesFunc BitcoinOutputScriptToAddressesFunc btc.OutputScriptToAddressesFunc
} }
@ -58,8 +58,8 @@ type OmotenashiCoinParser struct {
// NewOmotenashiCoinParser returns new OmotenashiCoinParser instance // NewOmotenashiCoinParser returns new OmotenashiCoinParser instance
func NewOmotenashiCoinParser(params *chaincfg.Params, c *btc.Configuration) *OmotenashiCoinParser { func NewOmotenashiCoinParser(params *chaincfg.Params, c *btc.Configuration) *OmotenashiCoinParser {
p := &OmotenashiCoinParser{ p := &OmotenashiCoinParser{
BitcoinParser: btc.NewBitcoinParser(params, c), BitcoinLikeParser: btc.NewBitcoinLikeParser(params, c),
baseparser: &bchain.BaseParser{}, baseparser: &bchain.BaseParser{},
} }
p.BitcoinOutputScriptToAddressesFunc = p.OutputScriptToAddressesFunc p.BitcoinOutputScriptToAddressesFunc = p.OutputScriptToAddressesFunc
p.OutputScriptToAddressesFunc = p.outputScriptToAddresses p.OutputScriptToAddressesFunc = p.outputScriptToAddresses

View File

@ -50,7 +50,7 @@ func init() {
// PivXParser handle // PivXParser handle
type PivXParser struct { type PivXParser struct {
*btc.BitcoinParser *btc.BitcoinLikeParser
baseparser *bchain.BaseParser baseparser *bchain.BaseParser
BitcoinOutputScriptToAddressesFunc btc.OutputScriptToAddressesFunc BitcoinOutputScriptToAddressesFunc btc.OutputScriptToAddressesFunc
} }
@ -58,8 +58,8 @@ type PivXParser struct {
// NewPivXParser returns new PivXParser instance // NewPivXParser returns new PivXParser instance
func NewPivXParser(params *chaincfg.Params, c *btc.Configuration) *PivXParser { func NewPivXParser(params *chaincfg.Params, c *btc.Configuration) *PivXParser {
p := &PivXParser{ p := &PivXParser{
BitcoinParser: btc.NewBitcoinParser(params, c), BitcoinLikeParser: btc.NewBitcoinLikeParser(params, c),
baseparser: &bchain.BaseParser{}, baseparser: &bchain.BaseParser{},
} }
p.BitcoinOutputScriptToAddressesFunc = p.OutputScriptToAddressesFunc p.BitcoinOutputScriptToAddressesFunc = p.OutputScriptToAddressesFunc
p.OutputScriptToAddressesFunc = p.outputScriptToAddresses p.OutputScriptToAddressesFunc = p.outputScriptToAddresses

View File

@ -45,12 +45,12 @@ func init() {
// PolisParser handle // PolisParser handle
type PolisParser struct { type PolisParser struct {
*btc.BitcoinParser *btc.BitcoinLikeParser
} }
// NewPolisParser returns new PolisParser instance // NewPolisParser returns new PolisParser instance
func NewPolisParser(params *chaincfg.Params, c *btc.Configuration) *PolisParser { func NewPolisParser(params *chaincfg.Params, c *btc.Configuration) *PolisParser {
return &PolisParser{BitcoinParser: btc.NewBitcoinParser(params, c)} return &PolisParser{BitcoinLikeParser: btc.NewBitcoinLikeParser(params, c)}
} }
// GetChainParams contains network parameters for the main Polis network, // GetChainParams contains network parameters for the main Polis network,

View File

@ -40,13 +40,13 @@ func init() {
// QtumParser handle // QtumParser handle
type QtumParser struct { type QtumParser struct {
*btc.BitcoinParser *btc.BitcoinLikeParser
} }
// NewQtumParser returns new DashParser instance // NewQtumParser returns new DashParser instance
func NewQtumParser(params *chaincfg.Params, c *btc.Configuration) *QtumParser { func NewQtumParser(params *chaincfg.Params, c *btc.Configuration) *QtumParser {
return &QtumParser{ return &QtumParser{
BitcoinParser: btc.NewBitcoinParser(params, c), BitcoinLikeParser: btc.NewBitcoinLikeParser(params, c),
} }
} }

View File

@ -33,15 +33,15 @@ func init() {
// RavencoinParser handle // RavencoinParser handle
type RavencoinParser struct { type RavencoinParser struct {
*btc.BitcoinParser *btc.BitcoinLikeParser
baseparser *bchain.BaseParser baseparser *bchain.BaseParser
} }
// NewRavencoinParser returns new RavencoinParser instance // NewRavencoinParser returns new RavencoinParser instance
func NewRavencoinParser(params *chaincfg.Params, c *btc.Configuration) *RavencoinParser { func NewRavencoinParser(params *chaincfg.Params, c *btc.Configuration) *RavencoinParser {
return &RavencoinParser{ return &RavencoinParser{
BitcoinParser: btc.NewBitcoinParser(params, c), BitcoinLikeParser: btc.NewBitcoinLikeParser(params, c),
baseparser: &bchain.BaseParser{}, baseparser: &bchain.BaseParser{},
} }
} }

View File

@ -36,12 +36,12 @@ func init() {
// RitocoinParser handle // RitocoinParser handle
type RitocoinParser struct { type RitocoinParser struct {
*btc.BitcoinParser *btc.BitcoinLikeParser
} }
// NewRitocoinParser returns new RitocoinParser instance // NewRitocoinParser returns new RitocoinParser instance
func NewRitocoinParser(params *chaincfg.Params, c *btc.Configuration) *RitocoinParser { func NewRitocoinParser(params *chaincfg.Params, c *btc.Configuration) *RitocoinParser {
return &RitocoinParser{BitcoinParser: btc.NewBitcoinParser(params, c)} return &RitocoinParser{BitcoinLikeParser: btc.NewBitcoinLikeParser(params, c)}
} }
// GetChainParams contains network parameters // GetChainParams contains network parameters

View File

@ -49,15 +49,15 @@ func init() {
// SnowGemParser handle // SnowGemParser handle
type SnowGemParser struct { type SnowGemParser struct {
*btc.BitcoinParser *btc.BitcoinLikeParser
baseparser *bchain.BaseParser baseparser *bchain.BaseParser
} }
// NewSnowGemParser returns new SnowGemParser instance // NewSnowGemParser returns new SnowGemParser instance
func NewSnowGemParser(params *chaincfg.Params, c *btc.Configuration) *SnowGemParser { func NewSnowGemParser(params *chaincfg.Params, c *btc.Configuration) *SnowGemParser {
return &SnowGemParser{ return &SnowGemParser{
BitcoinParser: btc.NewBitcoinParser(params, c), BitcoinLikeParser: btc.NewBitcoinLikeParser(params, c),
baseparser: &bchain.BaseParser{}, baseparser: &bchain.BaseParser{},
} }
} }

View File

@ -26,15 +26,15 @@ func init() {
// TrezarcoinParser handle // TrezarcoinParser handle
type TrezarcoinParser struct { type TrezarcoinParser struct {
*btc.BitcoinParser *btc.BitcoinLikeParser
baseparser *bchain.BaseParser baseparser *bchain.BaseParser
} }
// NewTrezarcoinParser returns new TrezarcoinParser instance // NewTrezarcoinParser returns new TrezarcoinParser instance
func NewTrezarcoinParser(params *chaincfg.Params, c *btc.Configuration) *TrezarcoinParser { func NewTrezarcoinParser(params *chaincfg.Params, c *btc.Configuration) *TrezarcoinParser {
return &TrezarcoinParser{ return &TrezarcoinParser{
BitcoinParser: btc.NewBitcoinParser(params, c), BitcoinLikeParser: btc.NewBitcoinLikeParser(params, c),
baseparser: &bchain.BaseParser{}, baseparser: &bchain.BaseParser{},
} }
} }

View File

@ -31,12 +31,12 @@ func init() {
// UnobtaniumParser handle // UnobtaniumParser handle
type UnobtaniumParser struct { type UnobtaniumParser struct {
*btc.BitcoinParser *btc.BitcoinLikeParser
} }
// NewUnobtaniumParser returns new UnobtaniumParser instance // NewUnobtaniumParser returns new UnobtaniumParser instance
func NewUnobtaniumParser(params *chaincfg.Params, c *btc.Configuration) *UnobtaniumParser { func NewUnobtaniumParser(params *chaincfg.Params, c *btc.Configuration) *UnobtaniumParser {
return &UnobtaniumParser{BitcoinParser: btc.NewBitcoinParser(params, c)} return &UnobtaniumParser{BitcoinLikeParser: btc.NewBitcoinLikeParser(params, c)}
} }
// GetChainParams returns network parameters // GetChainParams returns network parameters

View File

@ -35,12 +35,12 @@ func init() {
// VertcoinParser handle // VertcoinParser handle
type VertcoinParser struct { type VertcoinParser struct {
*btc.BitcoinParser *btc.BitcoinLikeParser
} }
// NewVertcoinParser returns new VertcoinParser instance // NewVertcoinParser returns new VertcoinParser instance
func NewVertcoinParser(params *chaincfg.Params, c *btc.Configuration) *VertcoinParser { func NewVertcoinParser(params *chaincfg.Params, c *btc.Configuration) *VertcoinParser {
return &VertcoinParser{BitcoinParser: btc.NewBitcoinParser(params, c)} return &VertcoinParser{BitcoinLikeParser: btc.NewBitcoinLikeParser(params, c)}
} }
// GetChainParams contains network parameters for the main Vertcoin network, // GetChainParams contains network parameters for the main Vertcoin network,

View File

@ -42,12 +42,12 @@ func init() {
// ViacoinParser handle // ViacoinParser handle
type ViacoinParser struct { type ViacoinParser struct {
*btc.BitcoinParser *btc.BitcoinLikeParser
} }
// NewViacoinParser returns new VertcoinParser instance // NewViacoinParser returns new VertcoinParser instance
func NewViacoinParser(params *chaincfg.Params, c *btc.Configuration) *ViacoinParser { func NewViacoinParser(params *chaincfg.Params, c *btc.Configuration) *ViacoinParser {
return &ViacoinParser{BitcoinParser: btc.NewBitcoinParser(params, c)} return &ViacoinParser{BitcoinLikeParser: btc.NewBitcoinLikeParser(params, c)}
} }
// GetChainParams returns network parameters // GetChainParams returns network parameters

View File

@ -40,12 +40,12 @@ func init() {
// VIPSTARCOINParser handle // VIPSTARCOINParser handle
type VIPSTARCOINParser struct { type VIPSTARCOINParser struct {
*btc.BitcoinParser *btc.BitcoinLikeParser
} }
// NewVIPSTARCOINParser returns new VIPSTARCOINParser instance // NewVIPSTARCOINParser returns new VIPSTARCOINParser instance
func NewVIPSTARCOINParser(params *chaincfg.Params, c *btc.Configuration) *VIPSTARCOINParser { func NewVIPSTARCOINParser(params *chaincfg.Params, c *btc.Configuration) *VIPSTARCOINParser {
return &VIPSTARCOINParser{BitcoinParser: btc.NewBitcoinParser(params, c)} return &VIPSTARCOINParser{BitcoinLikeParser: btc.NewBitcoinLikeParser(params, c)}
} }
// GetChainParams contains network parameters for the main VIPSTARCOIN network, // GetChainParams contains network parameters for the main VIPSTARCOIN network,

View File

@ -48,15 +48,15 @@ func init() {
// ZCashParser handle // ZCashParser handle
type ZCashParser struct { type ZCashParser struct {
*btc.BitcoinParser *btc.BitcoinLikeParser
baseparser *bchain.BaseParser baseparser *bchain.BaseParser
} }
// NewZCashParser returns new ZCashParser instance // NewZCashParser returns new ZCashParser instance
func NewZCashParser(params *chaincfg.Params, c *btc.Configuration) *ZCashParser { func NewZCashParser(params *chaincfg.Params, c *btc.Configuration) *ZCashParser {
return &ZCashParser{ return &ZCashParser{
BitcoinParser: btc.NewBitcoinParser(params, c), BitcoinLikeParser: btc.NewBitcoinLikeParser(params, c),
baseparser: &bchain.BaseParser{}, baseparser: &bchain.BaseParser{},
} }
} }