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:
parent
93d09014c1
commit
eae9b6b613
@ -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
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
417
bchain/coins/btc/bitcoinlikeparser.go
Normal file
417
bchain/coins/btc/bitcoinlikeparser.go
Normal 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
|
||||||
|
}
|
||||||
@ -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
|
|
||||||
}
|
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user