CashAddr decoding optimization - doesn't support multisig
This commit is contained in:
parent
79ba6abadd
commit
092aeef2ed
@ -19,11 +19,6 @@ func (p *BaseParser) AddressToOutputScript(address string) ([]byte, error) {
|
|||||||
return nil, errors.New("AddressToOutputScript: not implemented")
|
return nil, errors.New("AddressToOutputScript: not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
// OutputScriptToAddresses converts ScriptPubKey to addresses - currently not implemented
|
|
||||||
func (p *BaseParser) OutputScriptToAddresses(script []byte) ([]string, error) {
|
|
||||||
return nil, errors.New("OutputScriptToAddresses: not implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
// ParseBlock parses raw block to our Block struct - currently not implemented
|
// ParseBlock parses raw block to our Block struct - currently not implemented
|
||||||
func (p *BaseParser) ParseBlock(b []byte) (*Block, error) {
|
func (p *BaseParser) ParseBlock(b []byte) (*Block, error) {
|
||||||
return nil, errors.New("ParseBlock: not implemented")
|
return nil, errors.New("ParseBlock: not implemented")
|
||||||
|
|||||||
@ -4,7 +4,6 @@ import (
|
|||||||
"blockbook/bchain"
|
"blockbook/bchain"
|
||||||
"blockbook/bchain/coins/btc"
|
"blockbook/bchain/coins/btc"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/chaincfg"
|
"github.com/btcsuite/btcd/chaincfg"
|
||||||
"github.com/btcsuite/btcd/txscript"
|
"github.com/btcsuite/btcd/txscript"
|
||||||
@ -20,7 +19,11 @@ const (
|
|||||||
CashAddr
|
CashAddr
|
||||||
)
|
)
|
||||||
|
|
||||||
var prefixes = []string{"bitcoincash", "bchtest", "bchreg"}
|
const (
|
||||||
|
MainNetPrefix = "bitcoincash:"
|
||||||
|
TestNetPrefix = "bchtest:"
|
||||||
|
RegTestPrefix = "bchreg:"
|
||||||
|
)
|
||||||
|
|
||||||
// BCashParser handle
|
// BCashParser handle
|
||||||
type BCashParser struct {
|
type BCashParser struct {
|
||||||
@ -44,10 +47,11 @@ func NewBCashParser(params *chaincfg.Params, c *btc.Configuration) (*BCashParser
|
|||||||
p := &BCashParser{
|
p := &BCashParser{
|
||||||
BitcoinParser: &btc.BitcoinParser{
|
BitcoinParser: &btc.BitcoinParser{
|
||||||
BaseParser: &bchain.BaseParser{
|
BaseParser: &bchain.BaseParser{
|
||||||
AddressFactory: func(addr string) (bchain.Address, error) { return newBCashAddress(addr, params, format) },
|
AddressFactory: func(addr string) (bchain.Address, error) { return newBCashAddress(addr, format) },
|
||||||
BlockAddressesToKeep: c.BlockAddressesToKeep,
|
BlockAddressesToKeep: c.BlockAddressesToKeep,
|
||||||
},
|
},
|
||||||
Params: params,
|
Params: params,
|
||||||
|
OutputScriptToAddresses: outputScriptToAddresses,
|
||||||
},
|
},
|
||||||
AddressFormat: format,
|
AddressFormat: format,
|
||||||
}
|
}
|
||||||
@ -105,42 +109,37 @@ func (p *BCashParser) AddressToOutputScript(address string) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func isCashAddr(addr string) bool {
|
func isCashAddr(addr string) bool {
|
||||||
slice := strings.Split(addr, ":")
|
n := len(addr)
|
||||||
if len(slice) != 2 {
|
switch {
|
||||||
return false
|
case n > len(MainNetPrefix) && addr[0:len(MainNetPrefix)] == MainNetPrefix:
|
||||||
}
|
return true
|
||||||
for _, prefix := range prefixes {
|
case n > len(TestNetPrefix) && addr[0:len(TestNetPrefix)] == TestNetPrefix:
|
||||||
if slice[0] == prefix {
|
return true
|
||||||
return true
|
case n > len(RegTestPrefix) && addr[0:len(RegTestPrefix)] == RegTestPrefix:
|
||||||
}
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *BCashParser) UnpackTx(buf []byte) (tx *bchain.Tx, height uint32, err error) {
|
// outputScriptToAddresses converts ScriptPubKey to bitcoin addresses
|
||||||
tx, height, err = p.BitcoinParser.UnpackTx(buf)
|
func outputScriptToAddresses(script []byte, params *chaincfg.Params) ([]string, error) {
|
||||||
|
a, err := bchutil.ExtractPkScriptAddrs(script, params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return nil, err
|
||||||
}
|
}
|
||||||
|
return []string{a.EncodeAddress()}, nil
|
||||||
for i, vout := range tx.Vout {
|
|
||||||
if len(vout.ScriptPubKey.Addresses) == 1 {
|
|
||||||
a, err := newBCashAddress(vout.ScriptPubKey.Addresses[0], p.Params, p.AddressFormat)
|
|
||||||
if err != nil {
|
|
||||||
return nil, 0, err
|
|
||||||
}
|
|
||||||
tx.Vout[i].Address = a
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type bcashAddress struct {
|
type bcashAddress struct {
|
||||||
addr string
|
addr string
|
||||||
}
|
}
|
||||||
|
|
||||||
func newBCashAddress(addr string, net *chaincfg.Params, format AddressFormat) (*bcashAddress, error) {
|
func newBCashAddress(addr string, format AddressFormat) (*bcashAddress, error) {
|
||||||
|
if isCashAddr(addr) && format == CashAddr {
|
||||||
|
return &bcashAddress{addr: addr}, nil
|
||||||
|
}
|
||||||
|
|
||||||
da, err := address.NewFromString(addr)
|
da, err := address.NewFromString(addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@ -10,7 +10,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestBcashAddressEncodeAddress(t *testing.T) {
|
func TestBcashAddressEncodeAddress(t *testing.T) {
|
||||||
addr1, err := newBCashAddress("13zMwGC5bxRn9ckJ1mgxf7UR8qbbNe2iji", GetChainParams("main"), Legacy)
|
addr1, err := newBCashAddress("13zMwGC5bxRn9ckJ1mgxf7UR8qbbNe2iji", Legacy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("newBCashAddress() error = %v", err)
|
t.Errorf("newBCashAddress() error = %v", err)
|
||||||
return
|
return
|
||||||
@ -19,7 +19,7 @@ func TestBcashAddressEncodeAddress(t *testing.T) {
|
|||||||
if got1 != "13zMwGC5bxRn9ckJ1mgxf7UR8qbbNe2iji" {
|
if got1 != "13zMwGC5bxRn9ckJ1mgxf7UR8qbbNe2iji" {
|
||||||
t.Errorf("String() got1 = %v, want %v", got1, "13zMwGC5bxRn9ckJ1mgxf7UR8qbbNe2iji")
|
t.Errorf("String() got1 = %v, want %v", got1, "13zMwGC5bxRn9ckJ1mgxf7UR8qbbNe2iji")
|
||||||
}
|
}
|
||||||
addr2, err := newBCashAddress("13zMwGC5bxRn9ckJ1mgxf7UR8qbbNe2iji", GetChainParams("main"), CashAddr)
|
addr2, err := newBCashAddress("13zMwGC5bxRn9ckJ1mgxf7UR8qbbNe2iji", CashAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("newBCashAddress() error = %v", err)
|
t.Errorf("newBCashAddress() error = %v", err)
|
||||||
return
|
return
|
||||||
@ -31,12 +31,12 @@ func TestBcashAddressEncodeAddress(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestBcashAddressAreEqual(t *testing.T) {
|
func TestBcashAddressAreEqual(t *testing.T) {
|
||||||
addr1, err := newBCashAddress("13zMwGC5bxRn9ckJ1mgxf7UR8qbbNe2iji", GetChainParams("main"), Legacy)
|
addr1, err := newBCashAddress("13zMwGC5bxRn9ckJ1mgxf7UR8qbbNe2iji", Legacy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("newBCashAddress() error = %v", err)
|
t.Errorf("newBCashAddress() error = %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
addr2, err := newBCashAddress("13zMwGC5bxRn9ckJ1mgxf7UR8qbbNe2iji", GetChainParams("main"), CashAddr)
|
addr2, err := newBCashAddress("13zMwGC5bxRn9ckJ1mgxf7UR8qbbNe2iji", CashAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("newBCashAddress() error = %v", err)
|
t.Errorf("newBCashAddress() error = %v", err)
|
||||||
return
|
return
|
||||||
@ -60,12 +60,12 @@ func TestBcashAddressAreEqual(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestBcashAddressInSlice(t *testing.T) {
|
func TestBcashAddressInSlice(t *testing.T) {
|
||||||
addr1, err := newBCashAddress("13zMwGC5bxRn9ckJ1mgxf7UR8qbbNe2iji", GetChainParams("main"), Legacy)
|
addr1, err := newBCashAddress("13zMwGC5bxRn9ckJ1mgxf7UR8qbbNe2iji", Legacy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("newBCashAddress() error = %v", err)
|
t.Errorf("newBCashAddress() error = %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
addr2, err := newBCashAddress("13zMwGC5bxRn9ckJ1mgxf7UR8qbbNe2iji", GetChainParams("main"), CashAddr)
|
addr2, err := newBCashAddress("13zMwGC5bxRn9ckJ1mgxf7UR8qbbNe2iji", CashAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("newBCashAddress() error = %v", err)
|
t.Errorf("newBCashAddress() error = %v", err)
|
||||||
return
|
return
|
||||||
@ -128,12 +128,12 @@ func init() {
|
|||||||
addr1, addr2, addr3 bchain.Address
|
addr1, addr2, addr3 bchain.Address
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
addr1, err = newBCashAddress("3AZKvpKhSh1o8t1QrX3UeXG9d2BhCRnbcK", GetChainParams("main"), Legacy)
|
addr1, err = newBCashAddress("3AZKvpKhSh1o8t1QrX3UeXG9d2BhCRnbcK", Legacy)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
addr2, err = newBCashAddress("2NByHN6A8QYkBATzxf4pRGbCSHD5CEN2TRu", GetChainParams("test"), Legacy)
|
addr2, err = newBCashAddress("2NByHN6A8QYkBATzxf4pRGbCSHD5CEN2TRu", Legacy)
|
||||||
}
|
}
|
||||||
if err == nil {
|
if err == nil {
|
||||||
addr3, err = newBCashAddress("2MvZguYaGjM7JihBgNqgLF2Ca2Enb76Hj9D", GetChainParams("test"), Legacy)
|
addr3, err = newBCashAddress("2MvZguYaGjM7JihBgNqgLF2Ca2Enb76Hj9D", Legacy)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
@ -161,7 +161,7 @@ func init() {
|
|||||||
ScriptPubKey: bchain.ScriptPubKey{
|
ScriptPubKey: bchain.ScriptPubKey{
|
||||||
Hex: "a9146144d57c8aff48492c9dfb914e120b20bad72d6f87",
|
Hex: "a9146144d57c8aff48492c9dfb914e120b20bad72d6f87",
|
||||||
Addresses: []string{
|
Addresses: []string{
|
||||||
"3AZKvpKhSh1o8t1QrX3UeXG9d2BhCRnbcK",
|
"bitcoincash:pps5f4tu3tl5sjfvnhaeznsjpvst44eddugfcnqpy9",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Address: addr1,
|
Address: addr1,
|
||||||
@ -191,7 +191,7 @@ func init() {
|
|||||||
ScriptPubKey: bchain.ScriptPubKey{
|
ScriptPubKey: bchain.ScriptPubKey{
|
||||||
Hex: "a914cd668d781ece600efa4b2404dc91fd26b8b8aed887",
|
Hex: "a914cd668d781ece600efa4b2404dc91fd26b8b8aed887",
|
||||||
Addresses: []string{
|
Addresses: []string{
|
||||||
"2NByHN6A8QYkBATzxf4pRGbCSHD5CEN2TRu",
|
"bchtest:prxkdrtcrm8xqrh6fvjqfhy3l5nt3w9wmq9fmsvkmz",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Address: addr2,
|
Address: addr2,
|
||||||
@ -202,7 +202,7 @@ func init() {
|
|||||||
ScriptPubKey: bchain.ScriptPubKey{
|
ScriptPubKey: bchain.ScriptPubKey{
|
||||||
Hex: "a914246655bdbd54c7e477d0ea2375e86e0db2b8f80a87",
|
Hex: "a914246655bdbd54c7e477d0ea2375e86e0db2b8f80a87",
|
||||||
Addresses: []string{
|
Addresses: []string{
|
||||||
"2MvZguYaGjM7JihBgNqgLF2Ca2Enb76Hj9D",
|
"bchtest:pqjxv4dah42v0erh6r4zxa0gdcxm9w8cpg0qw8tqf6",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Address: addr3,
|
Address: addr3,
|
||||||
|
|||||||
@ -14,10 +14,14 @@ import (
|
|||||||
"github.com/btcsuite/btcutil"
|
"github.com/btcsuite/btcutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// OutputScriptToAddressesFunc converts ScriptPubKey to bitcoin addresses
|
||||||
|
type OutputScriptToAddressesFunc func(script []byte, params *chaincfg.Params) ([]string, error)
|
||||||
|
|
||||||
// BitcoinParser handle
|
// BitcoinParser handle
|
||||||
type BitcoinParser struct {
|
type BitcoinParser struct {
|
||||||
*bchain.BaseParser
|
*bchain.BaseParser
|
||||||
Params *chaincfg.Params
|
Params *chaincfg.Params
|
||||||
|
OutputScriptToAddresses OutputScriptToAddressesFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewBitcoinParser returns new BitcoinParser instance
|
// NewBitcoinParser returns new BitcoinParser instance
|
||||||
@ -28,6 +32,7 @@ func NewBitcoinParser(params *chaincfg.Params, c *Configuration) *BitcoinParser
|
|||||||
BlockAddressesToKeep: c.BlockAddressesToKeep,
|
BlockAddressesToKeep: c.BlockAddressesToKeep,
|
||||||
},
|
},
|
||||||
params,
|
params,
|
||||||
|
outputScriptToAddresses,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,9 +72,9 @@ func (p *BitcoinParser) AddressToOutputScript(address string) ([]byte, error) {
|
|||||||
return script, nil
|
return script, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// OutputScriptToAddresses converts ScriptPubKey to bitcoin addresses
|
// outputScriptToAddresses converts ScriptPubKey to bitcoin addresses
|
||||||
func (p *BitcoinParser) OutputScriptToAddresses(script []byte) ([]string, error) {
|
func outputScriptToAddresses(script []byte, params *chaincfg.Params) ([]string, error) {
|
||||||
_, addresses, _, err := txscript.ExtractPkScriptAddrs(script, p.Params)
|
_, addresses, _, err := txscript.ExtractPkScriptAddrs(script, params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -105,7 +110,7 @@ func (p *BitcoinParser) txFromMsgTx(t *wire.MsgTx, parseAddresses bool) bchain.T
|
|||||||
for i, out := range t.TxOut {
|
for i, out := range t.TxOut {
|
||||||
addrs := []string{}
|
addrs := []string{}
|
||||||
if parseAddresses {
|
if parseAddresses {
|
||||||
addrs, _ = p.OutputScriptToAddresses(out.PkScript)
|
addrs, _ = p.OutputScriptToAddresses(out.PkScript, p.Params)
|
||||||
}
|
}
|
||||||
s := bchain.ScriptPubKey{
|
s := bchain.ScriptPubKey{
|
||||||
Hex: hex.EncodeToString(out.PkScript),
|
Hex: hex.EncodeToString(out.PkScript),
|
||||||
|
|||||||
@ -94,17 +94,16 @@ func TestOutputScriptToAddresses(t *testing.T) {
|
|||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
parser := NewBitcoinParser(GetChainParams("main"), &Configuration{})
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
b, _ := hex.DecodeString(tt.args.script)
|
b, _ := hex.DecodeString(tt.args.script)
|
||||||
got, err := parser.OutputScriptToAddresses(b)
|
got, err := outputScriptToAddresses(b, GetChainParams("main"))
|
||||||
if (err != nil) != tt.wantErr {
|
if (err != nil) != tt.wantErr {
|
||||||
t.Errorf("OutputScriptToAddresses() error = %v, wantErr %v", err, tt.wantErr)
|
t.Errorf("outputScriptToAddresses() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(got, tt.want) {
|
if !reflect.DeepEqual(got, tt.want) {
|
||||||
t.Errorf("OutputScriptToAddresses() = %v, want %v", got, tt.want)
|
t.Errorf("outputScriptToAddresses() = %v, want %v", got, tt.want)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@ -156,7 +156,6 @@ type BlockChainParser interface {
|
|||||||
GetAddrIDFromAddress(address string) ([]byte, error)
|
GetAddrIDFromAddress(address string) ([]byte, error)
|
||||||
// address to output script conversions
|
// address to output script conversions
|
||||||
AddressToOutputScript(address string) ([]byte, error)
|
AddressToOutputScript(address string) ([]byte, error)
|
||||||
OutputScriptToAddresses(script []byte) ([]string, error)
|
|
||||||
// transactions
|
// transactions
|
||||||
PackedTxidLen() int
|
PackedTxidLen() int
|
||||||
PackTxid(txid string) ([]byte, error)
|
PackTxid(txid string) ([]byte, error)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user