diff --git a/Gopkg.lock b/Gopkg.lock index cfbfc254..d3306553 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -109,6 +109,12 @@ revision = "3247c84500bff8d9fb6d579d800f20b3e091582c" version = "v1.0.0" +[[projects]] + branch = "master" + name = "github.com/mr-tron/base58" + packages = ["base58"] + revision = "c1bdf7c52f59d6685ca597b9955a443ff95eeee6" + [[projects]] branch = "master" name = "github.com/pebbe/zmq4" @@ -145,6 +151,12 @@ revision = "feef513b9575b32f84bafa580aad89b011259019" version = "v1.3.0" +[[projects]] + name = "github.com/schancel/cashaddr-converter" + packages = ["address","baseconv","cashaddress","legacy"] + revision = "0a38f5822f795dc3727b4caacc298e02938d9eb1" + version = "v9" + [[projects]] branch = "master" name = "github.com/syndtr/goleveldb" @@ -190,6 +202,6 @@ [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "3a5adb167369a6d82fec8664beb93b7e7c8109b31c9f19ecd8ce1142755d621f" + inputs-digest = "97b5e11b3aa46e6b54a5c3fd7835c49f324f9821a1c641e5682f60ee6716d8c2" solver-name = "gps-cdcl" solver-version = 1 diff --git a/bchain/baseparser.go b/bchain/baseparser.go index 16ec5fab..dfba4ea9 100644 --- a/bchain/baseparser.go +++ b/bchain/baseparser.go @@ -3,7 +3,6 @@ package bchain import ( "encoding/hex" "encoding/json" - "fmt" "github.com/gogo/protobuf/proto" "github.com/juju/errors" @@ -20,11 +19,6 @@ func (p *BaseParser) AddressToOutputScript(address string) ([]byte, error) { 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 func (p *BaseParser) ParseBlock(b []byte) (*Block, error) { return nil, errors.New("ParseBlock: not implemented") @@ -215,30 +209,16 @@ func (a baseAddress) String() string { return a.addr } -func (a baseAddress) EncodeAddress(format AddressFormat) (string, error) { - if format != DefaultAddress { - return "", fmt.Errorf("Unknown address format: %d", format) - } - return a.addr, nil +func (a baseAddress) AreEqual(addr string) bool { + return a.String() == addr } -func (a baseAddress) AreEqual(addr string) (bool, error) { - ea, err := a.EncodeAddress(0) - if err != nil { - return false, err - } - return ea == addr, nil -} - -func (a baseAddress) InSlice(addrs []string) (bool, error) { +func (a baseAddress) InSlice(addrs []string) bool { + ea := a.String() for _, addr := range addrs { - eq, err := a.AreEqual(addr) - if err != nil { - return false, err - } - if eq { - return true, nil + if ea == addr { + return true } } - return false, nil + return false } diff --git a/bchain/coins/bch/bcashparser.go b/bchain/coins/bch/bcashparser.go index f854169c..2be69fa4 100644 --- a/bchain/coins/bch/bcashparser.go +++ b/bchain/coins/bch/bcashparser.go @@ -4,32 +4,58 @@ import ( "blockbook/bchain" "blockbook/bchain/coins/btc" "fmt" - "strings" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcutil" "github.com/cpacia/bchutil" + "github.com/schancel/cashaddr-converter/address" ) -var prefixes = []string{"bitcoincash", "bchtest", "bchreg"} +type AddressFormat = uint8 + +const ( + Legacy AddressFormat = iota + CashAddr +) + +const ( + MainNetPrefix = "bitcoincash:" + TestNetPrefix = "bchtest:" + RegTestPrefix = "bchreg:" +) // BCashParser handle type BCashParser struct { *btc.BitcoinParser + AddressFormat AddressFormat } // NewBCashParser returns new BCashParser instance -func NewBCashParser(params *chaincfg.Params, c *btc.Configuration) *BCashParser { - return &BCashParser{ +func NewBCashParser(params *chaincfg.Params, c *btc.Configuration) (*BCashParser, error) { + var format AddressFormat + switch c.AddressFormat { + case "": + fallthrough + case "cashaddr": + format = CashAddr + case "legacy": + format = Legacy + default: + return nil, fmt.Errorf("Unknown address format: %s", c.AddressFormat) + } + p := &BCashParser{ BitcoinParser: &btc.BitcoinParser{ BaseParser: &bchain.BaseParser{ - AddressFactory: func(addr string) (bchain.Address, error) { return newBCashAddress(addr, params) }, + AddressFactory: func(addr string) (bchain.Address, error) { return newBCashAddress(addr, format) }, BlockAddressesToKeep: c.BlockAddressesToKeep, }, - Params: params, + Params: params, + OutputScriptToAddresses: outputScriptToAddresses, }, + AddressFormat: format, } + return p, nil } // GetChainParams contains network parameters for the main Bitcoin Cash network, @@ -83,128 +109,82 @@ func (p *BCashParser) AddressToOutputScript(address string) ([]byte, error) { } func isCashAddr(addr string) bool { - slice := strings.Split(addr, ":") - if len(slice) != 2 { - return false + n := len(addr) + switch { + case n > len(MainNetPrefix) && addr[0:len(MainNetPrefix)] == MainNetPrefix: + return true + case n > len(TestNetPrefix) && addr[0:len(TestNetPrefix)] == TestNetPrefix: + return true + case n > len(RegTestPrefix) && addr[0:len(RegTestPrefix)] == RegTestPrefix: + return true } - for _, prefix := range prefixes { - if slice[0] == prefix { + + return false +} + +// outputScriptToAddresses converts ScriptPubKey to bitcoin addresses +func outputScriptToAddresses(script []byte, params *chaincfg.Params) ([]string, error) { + a, err := bchutil.ExtractPkScriptAddrs(script, params) + if err != nil { + return nil, err + } + return []string{a.EncodeAddress()}, nil +} + +type bcashAddress struct { + addr string +} + +func newBCashAddress(addr string, format AddressFormat) (*bcashAddress, error) { + if isCashAddr(addr) && format == CashAddr { + return &bcashAddress{addr: addr}, nil + } + + da, err := address.NewFromString(addr) + if err != nil { + return nil, err + } + var ea string + switch format { + case CashAddr: + if a, err := da.CashAddress(); err != nil { + return nil, err + } else { + ea, err = a.Encode() + if err != nil { + return nil, err + } + } + + case Legacy: + if a, err := da.Legacy(); err != nil { + return nil, err + } else { + ea, err = a.Encode() + if err != nil { + return nil, err + } + } + default: + return nil, fmt.Errorf("Unknown address format: %d", format) + } + return &bcashAddress{addr: ea}, nil +} + +func (a *bcashAddress) String() string { + return a.addr +} + +func (a *bcashAddress) AreEqual(addr string) bool { + return a.String() == addr +} + +func (a *bcashAddress) InSlice(addrs []string) bool { + ea := a.String() + for _, addr := range addrs { + if ea == addr { return true } } return false } - -func (p *BCashParser) UnpackTx(buf []byte) (tx *bchain.Tx, height uint32, err error) { - tx, height, err = p.BitcoinParser.UnpackTx(buf) - if err != nil { - return - } - - for i, vout := range tx.Vout { - if len(vout.ScriptPubKey.Addresses) == 1 { - a, err := newBCashAddress(vout.ScriptPubKey.Addresses[0], p.Params) - if err != nil { - return nil, 0, err - } - tx.Vout[i].Address = a - } - } - - return -} - -type bcashAddress struct { - addr btcutil.Address - net *chaincfg.Params -} - -func newBCashAddress(addr string, net *chaincfg.Params) (*bcashAddress, error) { - var ( - da btcutil.Address - err error - ) - if isCashAddr(addr) { - // for cashaddr we need to convert it to the legacy form (i.e. to btcutil's Address) - // because bchutil doesn't allow later conversions - da, err = bchutil.DecodeAddress(addr, net) - if err != nil { - return nil, err - } - switch ca := da.(type) { - case *bchutil.CashAddressPubKeyHash: - da, err = btcutil.NewAddressPubKeyHash(ca.Hash160()[:], net) - case *bchutil.CashAddressScriptHash: - da, err = btcutil.NewAddressScriptHash(ca.Hash160()[:], net) - default: - err = fmt.Errorf("Unknown address type: %T", da) - } - if err != nil { - return nil, err - } - } else { - da, err = btcutil.DecodeAddress(addr, net) - if err != nil { - return nil, err - } - } - return &bcashAddress{addr: da, net: net}, nil -} - -func (a *bcashAddress) String() string { - return a.addr.String() -} - -func (a *bcashAddress) EncodeAddress(format bchain.AddressFormat) (string, error) { - switch format { - case bchain.DefaultAddress: - return a.String(), nil - case bchain.BCashAddress: - var ( - ca btcutil.Address - err error - ) - switch da := a.addr.(type) { - case *btcutil.AddressPubKeyHash: - ca, err = bchutil.NewCashAddressPubKeyHash(da.Hash160()[:], a.net) - case *btcutil.AddressScriptHash: - ca, err = bchutil.NewCashAddressScriptHash(da.Hash160()[:], a.net) - default: - err = fmt.Errorf("Unknown address type: %T", da) - } - if err != nil { - return "", err - } - return ca.String(), nil - - default: - return "", fmt.Errorf("Unknown address format: %d", format) - } -} - -func (a *bcashAddress) AreEqual(addr string) (bool, error) { - var format bchain.AddressFormat - if isCashAddr(addr) { - format = bchain.BCashAddress - } else { - format = bchain.DefaultAddress - } - ea, err := a.EncodeAddress(format) - if err != nil { - return false, err - } - return ea == addr, nil -} - -func (a *bcashAddress) InSlice(addrs []string) (bool, error) { - for _, addr := range addrs { - eq, err := a.AreEqual(addr) - if err != nil { - return false, err - } - if eq { - return true, nil - } - } - return false, nil -} diff --git a/bchain/coins/bch/bcashparser_test.go b/bchain/coins/bch/bcashparser_test.go index 26cdc1d9..5ef506f7 100644 --- a/bchain/coins/bch/bcashparser_test.go +++ b/bchain/coins/bch/bcashparser_test.go @@ -10,111 +10,90 @@ import ( ) func TestBcashAddressEncodeAddress(t *testing.T) { - addr, err := newBCashAddress("13zMwGC5bxRn9ckJ1mgxf7UR8qbbNe2iji", GetChainParams("main")) + addr1, err := newBCashAddress("13zMwGC5bxRn9ckJ1mgxf7UR8qbbNe2iji", Legacy) if err != nil { t.Errorf("newBCashAddress() error = %v", err) return } - got1, err := addr.EncodeAddress(bchain.DefaultAddress) - if err != nil { - t.Errorf("EncodeAddress() error = %v", err) - return - } + got1 := addr1.String() if got1 != "13zMwGC5bxRn9ckJ1mgxf7UR8qbbNe2iji" { - t.Errorf("EncodeAddress() got1 = %v, want %v", got1, "13zMwGC5bxRn9ckJ1mgxf7UR8qbbNe2iji") + t.Errorf("String() got1 = %v, want %v", got1, "13zMwGC5bxRn9ckJ1mgxf7UR8qbbNe2iji") } - got2, err := addr.EncodeAddress(bchain.BCashAddress) + addr2, err := newBCashAddress("13zMwGC5bxRn9ckJ1mgxf7UR8qbbNe2iji", CashAddr) if err != nil { - t.Errorf("EncodeAddress() error = %v", err) + t.Errorf("newBCashAddress() error = %v", err) return } + got2 := addr2.String() if got2 != "bitcoincash:qqsvjuqqwgyzvz7zz9xcvxent0ul2xjs6y4d9qvsrf" { - t.Errorf("EncodeAddress() got2 = %v, want %v", got2, "bitcoincash:qqsvjuqqwgyzvz7zz9xcvxent0ul2xjs6y4d9qvsrf") + t.Errorf("String() got2 = %v, want %v", got2, "bitcoincash:qqsvjuqqwgyzvz7zz9xcvxent0ul2xjs6y4d9qvsrf") } } func TestBcashAddressAreEqual(t *testing.T) { - addr, err := newBCashAddress("13zMwGC5bxRn9ckJ1mgxf7UR8qbbNe2iji", GetChainParams("main")) + addr1, err := newBCashAddress("13zMwGC5bxRn9ckJ1mgxf7UR8qbbNe2iji", Legacy) if err != nil { t.Errorf("newBCashAddress() error = %v", err) return } - got1, err := addr.AreEqual("13zMwGC5bxRn9ckJ1mgxf7UR8qbbNe2iji") + addr2, err := newBCashAddress("13zMwGC5bxRn9ckJ1mgxf7UR8qbbNe2iji", CashAddr) if err != nil { - t.Errorf("AreEqual() error = %v", err) + t.Errorf("newBCashAddress() error = %v", err) return } + got1 := addr1.AreEqual("13zMwGC5bxRn9ckJ1mgxf7UR8qbbNe2iji") if got1 != true { t.Errorf("AreEqual() got1 = %v, want %v", got1, true) } - got2, err := addr.AreEqual("bitcoincash:qqsvjuqqwgyzvz7zz9xcvxent0ul2xjs6y4d9qvsrf") - if err != nil { - t.Errorf("AreEqual() error = %v", err) - return - } + got2 := addr2.AreEqual("bitcoincash:qqsvjuqqwgyzvz7zz9xcvxent0ul2xjs6y4d9qvsrf") if got2 != true { t.Errorf("AreEqual() got2 = %v, want %v", got2, true) } - got3, err := addr.AreEqual("1HoKgKQh7ZNomWURmS9Tk3z8JM2MWm7S1w") - if err != nil { - t.Errorf("AreEqual() error = %v", err) - return - } + got3 := addr1.AreEqual("1HoKgKQh7ZNomWURmS9Tk3z8JM2MWm7S1w") if got3 != false { t.Errorf("AreEqual() got3 = %v, want %v", got3, false) } - got4, err := addr.AreEqual("bitcoincash:qzuyf0gpqj7q5wfck3nyghhklju7r0k3ksmq6d0vch") - if err != nil { - t.Errorf("AreEqual() error = %v", err) - return - } + got4 := addr2.AreEqual("bitcoincash:qzuyf0gpqj7q5wfck3nyghhklju7r0k3ksmq6d0vch") if got4 != false { t.Errorf("AreEqual() got4 = %v, want %v", got4, false) } } func TestBcashAddressInSlice(t *testing.T) { - addr, err := newBCashAddress("13zMwGC5bxRn9ckJ1mgxf7UR8qbbNe2iji", GetChainParams("main")) + addr1, err := newBCashAddress("13zMwGC5bxRn9ckJ1mgxf7UR8qbbNe2iji", Legacy) if err != nil { t.Errorf("newBCashAddress() error = %v", err) return } - got1, err := addr.InSlice([]string{"13zMwGC5bxRn9ckJ1mgxf7UR8qbbNe2iji", "bitcoincash:qzuyf0gpqj7q5wfck3nyghhklju7r0k3ksmq6d0vch"}) + addr2, err := newBCashAddress("13zMwGC5bxRn9ckJ1mgxf7UR8qbbNe2iji", CashAddr) if err != nil { - t.Errorf("InSlice() error = %v", err) + t.Errorf("newBCashAddress() error = %v", err) return } + got1 := addr1.InSlice([]string{"13zMwGC5bxRn9ckJ1mgxf7UR8qbbNe2iji", "1HoKgKQh7ZNomWURmS9Tk3z8JM2MWm7S1w"}) if got1 != true { t.Errorf("InSlice() got1 = %v, want %v", got1, true) } - got2, err := addr.InSlice([]string{"1HoKgKQh7ZNomWURmS9Tk3z8JM2MWm7S1w", "bitcoincash:qqsvjuqqwgyzvz7zz9xcvxent0ul2xjs6y4d9qvsrf"}) - if err != nil { - t.Errorf("InSlice() error = %v", err) - return - } + got2 := addr2.InSlice([]string{"bitcoincash:qzuyf0gpqj7q5wfck3nyghhklju7r0k3ksmq6d0vch", "bitcoincash:qqsvjuqqwgyzvz7zz9xcvxent0ul2xjs6y4d9qvsrf"}) if got2 != true { t.Errorf("InSlice() got2 = %v, want %v", got2, true) } - got3, err := addr.InSlice([]string{"1HoKgKQh7ZNomWURmS9Tk3z8JM2MWm7S1w", "1E6Np6dUPYpBSdLMLuwBF8sRQ3cngdaRRY"}) - if err != nil { - t.Errorf("InSlice() error = %v", err) - return - } + got3 := addr1.InSlice([]string{"1HoKgKQh7ZNomWURmS9Tk3z8JM2MWm7S1w", "1E6Np6dUPYpBSdLMLuwBF8sRQ3cngdaRRY"}) if got3 != false { t.Errorf("InSlice() got3 = %v, want %v", got3, false) } - got4, err := addr.InSlice([]string{"bitcoincash:qzuyf0gpqj7q5wfck3nyghhklju7r0k3ksmq6d0vch", "bitcoincash:qz8emmpenqgeg7et8xsz8prvhy6cqcalyyjcamt7e9"}) - if err != nil { - t.Errorf("InSlice() error = %v", err) - return - } + got4 := addr2.InSlice([]string{"bitcoincash:qzuyf0gpqj7q5wfck3nyghhklju7r0k3ksmq6d0vch", "bitcoincash:qz8emmpenqgeg7et8xsz8prvhy6cqcalyyjcamt7e9"}) if got4 != false { t.Errorf("InSlice() got4 = %v, want %v", got4, false) } } func TestAddressToOutputScript(t *testing.T) { - parser := NewBCashParser(GetChainParams("test"), &btc.Configuration{}) + parser, err := NewBCashParser(GetChainParams("test"), &btc.Configuration{AddressFormat: "legacy"}) + if err != nil { + t.Errorf("NewBCashParser() error = %v", err) + return + } want, err := hex.DecodeString("76a9144fa927fd3bcf57d4e3c582c3d2eb2bd3df8df47c88ac") if err != nil { panic(err) @@ -149,12 +128,12 @@ func init() { addr1, addr2, addr3 bchain.Address err error ) - addr1, err = newBCashAddress("3AZKvpKhSh1o8t1QrX3UeXG9d2BhCRnbcK", GetChainParams("main")) + addr1, err = newBCashAddress("3AZKvpKhSh1o8t1QrX3UeXG9d2BhCRnbcK", Legacy) if err == nil { - addr2, err = newBCashAddress("2NByHN6A8QYkBATzxf4pRGbCSHD5CEN2TRu", GetChainParams("test")) + addr2, err = newBCashAddress("2NByHN6A8QYkBATzxf4pRGbCSHD5CEN2TRu", Legacy) } if err == nil { - addr3, err = newBCashAddress("2MvZguYaGjM7JihBgNqgLF2Ca2Enb76Hj9D", GetChainParams("test")) + addr3, err = newBCashAddress("2MvZguYaGjM7JihBgNqgLF2Ca2Enb76Hj9D", Legacy) } if err != nil { panic(err) @@ -182,7 +161,7 @@ func init() { ScriptPubKey: bchain.ScriptPubKey{ Hex: "a9146144d57c8aff48492c9dfb914e120b20bad72d6f87", Addresses: []string{ - "3AZKvpKhSh1o8t1QrX3UeXG9d2BhCRnbcK", + "bitcoincash:pps5f4tu3tl5sjfvnhaeznsjpvst44eddugfcnqpy9", }, }, Address: addr1, @@ -212,7 +191,7 @@ func init() { ScriptPubKey: bchain.ScriptPubKey{ Hex: "a914cd668d781ece600efa4b2404dc91fd26b8b8aed887", Addresses: []string{ - "2NByHN6A8QYkBATzxf4pRGbCSHD5CEN2TRu", + "bchtest:prxkdrtcrm8xqrh6fvjqfhy3l5nt3w9wmq9fmsvkmz", }, }, Address: addr2, @@ -223,7 +202,7 @@ func init() { ScriptPubKey: bchain.ScriptPubKey{ Hex: "a914246655bdbd54c7e477d0ea2375e86e0db2b8f80a87", Addresses: []string{ - "2MvZguYaGjM7JihBgNqgLF2Ca2Enb76Hj9D", + "bchtest:pqjxv4dah42v0erh6r4zxa0gdcxm9w8cpg0qw8tqf6", }, }, Address: addr3, @@ -233,6 +212,17 @@ func init() { } func Test_UnpackTx(t *testing.T) { + parser1, err := NewBCashParser(GetChainParams("main"), &btc.Configuration{AddressFormat: "legacy"}) + if err != nil { + t.Errorf("NewBCashParser() error = %v", err) + return + } + parser2, err := NewBCashParser(GetChainParams("test"), &btc.Configuration{AddressFormat: "legacy"}) + if err != nil { + t.Errorf("NewBCashParser() error = %v", err) + return + } + type args struct { packedTx string parser *BCashParser @@ -248,7 +238,7 @@ func Test_UnpackTx(t *testing.T) { name: "btc-1", args: args{ packedTx: testTxPacked1, - parser: NewBCashParser(GetChainParams("main"), &btc.Configuration{}), + parser: parser1, }, want: &testTx1, want1: 123456, @@ -258,7 +248,7 @@ func Test_UnpackTx(t *testing.T) { name: "testnet-1", args: args{ packedTx: testTxPacked2, - parser: NewBCashParser(GetChainParams("test"), &btc.Configuration{}), + parser: parser2, }, want: &testTx2, want1: 510234, diff --git a/bchain/coins/bch/bcashrpc.go b/bchain/coins/bch/bcashrpc.go index b148b019..4ed4f834 100644 --- a/bchain/coins/bch/bcashrpc.go +++ b/bchain/coins/bch/bcashrpc.go @@ -32,7 +32,6 @@ func NewBCashRPC(config json.RawMessage, pushHandler func(bchain.NotificationTyp // Initialize initializes BCashRPC instance. func (b *BCashRPC) Initialize() error { - chainName, err := b.GetChainInfoAndInitializeMempool(b) if err != nil { return err @@ -41,7 +40,11 @@ func (b *BCashRPC) Initialize() error { params := GetChainParams(chainName) // always create parser - b.Parser = NewBCashParser(params, b.ChainConfig) + b.Parser, err = NewBCashParser(params, b.ChainConfig) + + if err != nil { + return err + } // parameters for getInfo request if params.Net == bchutil.MainnetMagic { diff --git a/bchain/coins/btc/bitcoinparser.go b/bchain/coins/btc/bitcoinparser.go index 442bcfa5..aa8ceffe 100644 --- a/bchain/coins/btc/bitcoinparser.go +++ b/bchain/coins/btc/bitcoinparser.go @@ -14,10 +14,14 @@ import ( "github.com/btcsuite/btcutil" ) +// OutputScriptToAddressesFunc converts ScriptPubKey to bitcoin addresses +type OutputScriptToAddressesFunc func(script []byte, params *chaincfg.Params) ([]string, error) + // BitcoinParser handle type BitcoinParser struct { *bchain.BaseParser - Params *chaincfg.Params + Params *chaincfg.Params + OutputScriptToAddresses OutputScriptToAddressesFunc } // NewBitcoinParser returns new BitcoinParser instance @@ -28,6 +32,7 @@ func NewBitcoinParser(params *chaincfg.Params, c *Configuration) *BitcoinParser BlockAddressesToKeep: c.BlockAddressesToKeep, }, params, + outputScriptToAddresses, } } @@ -67,9 +72,9 @@ func (p *BitcoinParser) AddressToOutputScript(address string) ([]byte, error) { return script, nil } -// OutputScriptToAddresses converts ScriptPubKey to bitcoin addresses -func (p *BitcoinParser) OutputScriptToAddresses(script []byte) ([]string, error) { - _, addresses, _, err := txscript.ExtractPkScriptAddrs(script, p.Params) +// outputScriptToAddresses converts ScriptPubKey to bitcoin addresses +func outputScriptToAddresses(script []byte, params *chaincfg.Params) ([]string, error) { + _, addresses, _, err := txscript.ExtractPkScriptAddrs(script, params) if err != nil { return nil, err } @@ -105,7 +110,7 @@ func (p *BitcoinParser) txFromMsgTx(t *wire.MsgTx, parseAddresses bool) bchain.T for i, out := range t.TxOut { addrs := []string{} if parseAddresses { - addrs, _ = p.OutputScriptToAddresses(out.PkScript) + addrs, _ = p.OutputScriptToAddresses(out.PkScript, p.Params) } s := bchain.ScriptPubKey{ Hex: hex.EncodeToString(out.PkScript), diff --git a/bchain/coins/btc/bitcoinparser_test.go b/bchain/coins/btc/bitcoinparser_test.go index 6c3606d4..669a4927 100644 --- a/bchain/coins/btc/bitcoinparser_test.go +++ b/bchain/coins/btc/bitcoinparser_test.go @@ -94,17 +94,16 @@ func TestOutputScriptToAddresses(t *testing.T) { wantErr: false, }, } - parser := NewBitcoinParser(GetChainParams("main"), &Configuration{}) for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { b, _ := hex.DecodeString(tt.args.script) - got, err := parser.OutputScriptToAddresses(b) + got, err := outputScriptToAddresses(b, GetChainParams("main")) 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 } if !reflect.DeepEqual(got, tt.want) { - t.Errorf("OutputScriptToAddresses() = %v, want %v", got, tt.want) + t.Errorf("outputScriptToAddresses() = %v, want %v", got, tt.want) } }) } diff --git a/bchain/coins/btc/bitcoinrpc.go b/bchain/coins/btc/bitcoinrpc.go index 86bdae2d..eb3eee6a 100644 --- a/bchain/coins/btc/bitcoinrpc.go +++ b/bchain/coins/btc/bitcoinrpc.go @@ -44,6 +44,7 @@ type Configuration struct { BlockAddressesToKeep int `json:"blockAddressesToKeep"` MempoolWorkers int `json:"mempoolWorkers"` MempoolSubWorkers int `json:"mempoolSubWorkers"` + AddressFormat string `json:"addressFormat"` } // NewBitcoinRPC returns new BitcoinRPC instance. diff --git a/bchain/types.go b/bchain/types.go index f8b4c88d..0edd8ef7 100644 --- a/bchain/types.go +++ b/bchain/types.go @@ -41,18 +41,10 @@ type ScriptPubKey struct { Addresses []string `json:"addresses,omitempty"` } -type AddressFormat = uint8 - -const ( - DefaultAddress AddressFormat = iota - BCashAddress -) - type Address interface { String() string - EncodeAddress(format AddressFormat) (string, error) - AreEqual(addr string) (bool, error) - InSlice(addrs []string) (bool, error) + AreEqual(addr string) bool + InSlice(addrs []string) bool } type Vout struct { @@ -164,7 +156,6 @@ type BlockChainParser interface { GetAddrIDFromAddress(address string) ([]byte, error) // address to output script conversions AddressToOutputScript(address string) ([]byte, error) - OutputScriptToAddresses(script []byte) ([]string, error) // transactions PackedTxidLen() int PackTxid(txid string) ([]byte, error) diff --git a/configs/bch-testnet.json b/configs/bch-testnet.json index 51731adc..d79c870e 100644 --- a/configs/bch-testnet.json +++ b/configs/bch-testnet.json @@ -8,5 +8,6 @@ "subversion": "/Bitcoin ABC:0.17.1/", "mempoolWorkers": 8, "mempoolSubWorkers": 2, - "blockAddressesToKeep": 300 + "blockAddressesToKeep": 300, + "addressFormat": "legacy" } diff --git a/configs/bch.json b/configs/bch.json index 31ecda0b..a0450eef 100644 --- a/configs/bch.json +++ b/configs/bch.json @@ -8,5 +8,6 @@ "subversion": "/Bitcoin ABC:0.17.1/", "mempoolWorkers": 8, "mempoolSubWorkers": 2, - "blockAddressesToKeep": 300 + "blockAddressesToKeep": 300, + "addressFormat": "legacy" } diff --git a/server/socketio.go b/server/socketio.go index 9dbf7ad9..7be24718 100644 --- a/server/socketio.go +++ b/server/socketio.go @@ -208,16 +208,11 @@ func (s *SocketIoServer) apiBlockIndex(w http.ResponseWriter, r *http.Request) { } type addrOpts struct { - Start int `json:"start"` - End int `json:"end"` - QueryMempoolOnly bool `json:"queryMempoolOnly"` - From int `json:"from"` - To int `json:"to"` - AddressFormat uint8 `json:"addressFormat"` -} - -type txOpts struct { - AddressFormat uint8 `json:"addressFormat"` + Start int `json:"start"` + End int `json:"end"` + QueryMempoolOnly bool `json:"queryMempoolOnly"` + From int `json:"from"` + To int `json:"to"` } var onMessageHandlers = map[string]func(*SocketIoServer, json.RawMessage) (interface{}, error){ @@ -260,9 +255,9 @@ var onMessageHandlers = map[string]func(*SocketIoServer, json.RawMessage) (inter return s.getInfo() }, "getDetailedTransaction": func(s *SocketIoServer, params json.RawMessage) (rv interface{}, err error) { - txid, opts, err := unmarshalGetDetailedTransaction(params) + txid, err := unmarshalGetDetailedTransaction(params) if err == nil { - rv, err = s.getDetailedTransaction(txid, opts) + rv, err = s.getDetailedTransaction(txid) } return }, @@ -483,16 +478,9 @@ func (s *SocketIoServer) getAddressHistory(addr []string, opts *addrOpts) (res r Script: &aoh, } if vout.Address != nil { - a, err := vout.Address.EncodeAddress(opts.AddressFormat) - if err != nil { - return res, err - } + a := vout.Address.String() ao.Address = &a - found, err := vout.Address.InSlice(addr) - if err != nil { - return res, err - } - if found { + if vout.Address.InSlice(addr) { hi, ok := ads[a] if ok { hi.OutputIndexes = append(hi.OutputIndexes, int(vout.N)) @@ -693,13 +681,13 @@ func unmarshalStringParameter(params []byte) (s string, err error) { return } -func unmarshalGetDetailedTransaction(params []byte) (txid string, opts txOpts, err error) { +func unmarshalGetDetailedTransaction(params []byte) (txid string, err error) { var p []json.RawMessage err = json.Unmarshal(params, &p) if err != nil { return } - if len(p) < 1 || len(p) > 2 { + if len(p) != 1 { err = errors.New("incorrect number of parameters") return } @@ -707,9 +695,6 @@ func unmarshalGetDetailedTransaction(params []byte) (txid string, opts txOpts, e if err != nil { return } - if len(p) > 1 { - err = json.Unmarshal(p[1], &opts) - } return } @@ -717,7 +702,7 @@ type resultGetDetailedTransaction struct { Result resTx `json:"result"` } -func (s *SocketIoServer) getDetailedTransaction(txid string, opts txOpts) (res resultGetDetailedTransaction, err error) { +func (s *SocketIoServer) getDetailedTransaction(txid string) (res resultGetDetailedTransaction, err error) { bestheight, _, err := s.db.GetBestBlock() if err != nil { return @@ -743,10 +728,7 @@ func (s *SocketIoServer) getDetailedTransaction(txid string, opts txOpts) (res r if len(otx.Vout) > int(vin.Vout) { vout := otx.Vout[vin.Vout] if vout.Address != nil { - a, err := vout.Address.EncodeAddress(opts.AddressFormat) - if err != nil { - return res, err - } + a := vout.Address.String() ai.Address = &a } ai.Satoshis = int64(vout.Value*1E8 + 0.5) @@ -761,10 +743,7 @@ func (s *SocketIoServer) getDetailedTransaction(txid string, opts txOpts) (res r Script: &aos, } if vout.Address != nil { - a, err := vout.Address.EncodeAddress(opts.AddressFormat) - if err != nil { - return res, err - } + a := vout.Address.String() ao.Address = &a } ho = append(ho, ao) diff --git a/static/test.html b/static/test.html index c911fe34..2d0d1733 100644 --- a/static/test.html +++ b/static/test.html @@ -56,15 +56,14 @@ var addresses = document.getElementById('getAddressHistoryAddresses').value.split(","); addresses = addresses.map(s => s.trim()); var mempool = document.getElementById("getAddressHistoryMempool").checked; - var format = document.getElementById("getAddressHistoryFormat").value; - lookupAddressHistories(addresses, 0, 5, mempool, 20000000, 0, format, function (result) { + lookupAddressHistories(addresses, 0, 5, mempool, 20000000, 0, function (result) { console.log('getAddressHistory sent successfully'); console.log(result); document.getElementById('getAddressHistoryResult').innerText = JSON.stringify(result).replace(/,/g, ", "); }); } - function lookupAddressHistories(addresses, from, to, mempool, start, end, format, f) { + function lookupAddressHistories(addresses, from, to, mempool, start, end, f) { const method = 'getAddressHistory'; const opts = mempool ? { start, // needed for older bitcores (so we don't load all history if bitcore-node < 3.1.3) @@ -81,7 +80,6 @@ ...opts, from, to, - addressFormat: parseInt(format), }, ]; return socket.send({ method, params }, f); @@ -172,28 +170,18 @@ function getDetailedTransaction() { var hash = document.getElementById('getDetailedTransactionHash').value.trim(); - var format = document.getElementById("getDetailedTransactionFormat").value; - lookupDetailedTransaction(hash, format, function (result) { + lookupDetailedTransaction(hash, function (result) { console.log('getDetailedTransaction sent successfully'); console.log(result); document.getElementById('getDetailedTransactionResult').innerText = JSON.stringify(result).replace(/,/g, ", "); }); } - function lookupDetailedTransaction(hash, format, f) { + function lookupDetailedTransaction(hash, f) { const method = 'getDetailedTransaction'; - const af = parseInt(format) var params = [ hash, ]; - if (af !== 0) { - params = [ - hash, - { - addressFormat: af, - }, - ]; - } return socket.send({ method, params }, f); } @@ -302,14 +290,6 @@ -
-