From ea3cfd2d6ac586d54d2b81dbd14adfe4423b2972 Mon Sep 17 00:00:00 2001 From: Jakub Matys Date: Tue, 29 May 2018 14:15:27 +0200 Subject: [PATCH] Address format is set in configuration instead of RPC options --- bchain/baseparser.go | 18 +++----- bchain/coins/bch/bcashparser.go | 68 ++++++++++++++++++---------- bchain/coins/bch/bcashparser_test.go | 51 +++++++++++++-------- bchain/coins/btc/bitcoinrpc.go | 1 + bchain/types.go | 9 +--- configs/bch-testnet.json | 3 +- configs/bch.json | 3 +- server/socketio.go | 34 ++++++-------- static/test.html | 38 ++-------------- 9 files changed, 109 insertions(+), 116 deletions(-) diff --git a/bchain/baseparser.go b/bchain/baseparser.go index 16ec5fab..7fc52728 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" @@ -215,15 +214,12 @@ 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) - } +func (a baseAddress) EncodeAddress() (string, error) { return a.addr, nil } func (a baseAddress) AreEqual(addr string) (bool, error) { - ea, err := a.EncodeAddress(0) + ea, err := a.EncodeAddress() if err != nil { return false, err } @@ -231,12 +227,12 @@ func (a baseAddress) AreEqual(addr string) (bool, error) { } func (a baseAddress) InSlice(addrs []string) (bool, error) { + ea, err := a.EncodeAddress() + if err != nil { + return false, err + } for _, addr := range addrs { - eq, err := a.AreEqual(addr) - if err != nil { - return false, err - } - if eq { + if ea == addr { return true, nil } } diff --git a/bchain/coins/bch/bcashparser.go b/bchain/coins/bch/bcashparser.go index f854169c..3861e5e5 100644 --- a/bchain/coins/bch/bcashparser.go +++ b/bchain/coins/bch/bcashparser.go @@ -12,23 +12,45 @@ import ( "github.com/cpacia/bchutil" ) +type AddressFormat = uint8 + +const ( + Legacy AddressFormat = iota + CashAddr +) + var prefixes = []string{"bitcoincash", "bchtest", "bchreg"} // BCashParser handle type BCashParser struct { *btc.BitcoinParser + AddressFormat AddressFormat } // NewBCashParser returns new BCashParser instance func NewBCashParser(params *chaincfg.Params, c *btc.Configuration) *BCashParser { + var format AddressFormat + switch c.AddressFormat { + case "": + fallthrough + case "cashaddr": + format = CashAddr + case "legacy": + format = Legacy + default: + // XXX + e := fmt.Errorf("Unknown address format: %s", c.AddressFormat) + panic(e) + } return &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, params, format) }, BlockAddressesToKeep: c.BlockAddressesToKeep, }, Params: params, }, + AddressFormat: format, } } @@ -103,7 +125,7 @@ func (p *BCashParser) UnpackTx(buf []byte) (tx *bchain.Tx, height uint32, err er for i, vout := range tx.Vout { if len(vout.ScriptPubKey.Addresses) == 1 { - a, err := newBCashAddress(vout.ScriptPubKey.Addresses[0], p.Params) + a, err := newBCashAddress(vout.ScriptPubKey.Addresses[0], p.Params, p.AddressFormat) if err != nil { return nil, 0, err } @@ -115,11 +137,12 @@ func (p *BCashParser) UnpackTx(buf []byte) (tx *bchain.Tx, height uint32, err er } type bcashAddress struct { - addr btcutil.Address - net *chaincfg.Params + addr btcutil.Address + net *chaincfg.Params + format AddressFormat } -func newBCashAddress(addr string, net *chaincfg.Params) (*bcashAddress, error) { +func newBCashAddress(addr string, net *chaincfg.Params, format AddressFormat) (*bcashAddress, error) { var ( da btcutil.Address err error @@ -148,18 +171,23 @@ func newBCashAddress(addr string, net *chaincfg.Params) (*bcashAddress, error) { return nil, err } } - return &bcashAddress{addr: da, net: net}, nil + switch format { + case Legacy, CashAddr: + default: + return nil, fmt.Errorf("Unknown address format: %d", format) + } + return &bcashAddress{addr: da, net: net, format: format}, nil } func (a *bcashAddress) String() string { return a.addr.String() } -func (a *bcashAddress) EncodeAddress(format bchain.AddressFormat) (string, error) { - switch format { - case bchain.DefaultAddress: +func (a *bcashAddress) EncodeAddress() (string, error) { + switch a.format { + case Legacy: return a.String(), nil - case bchain.BCashAddress: + case CashAddr: var ( ca btcutil.Address err error @@ -178,18 +206,12 @@ func (a *bcashAddress) EncodeAddress(format bchain.AddressFormat) (string, error return ca.String(), nil default: - return "", fmt.Errorf("Unknown address format: %d", format) + return "", fmt.Errorf("Unknown address format: %d", a.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) + ea, err := a.EncodeAddress() if err != nil { return false, err } @@ -197,12 +219,12 @@ func (a *bcashAddress) AreEqual(addr string) (bool, error) { } func (a *bcashAddress) InSlice(addrs []string) (bool, error) { + ea, err := a.EncodeAddress() + if err != nil { + return false, err + } for _, addr := range addrs { - eq, err := a.AreEqual(addr) - if err != nil { - return false, err - } - if eq { + if ea == addr { return true, nil } } diff --git a/bchain/coins/bch/bcashparser_test.go b/bchain/coins/bch/bcashparser_test.go index 26cdc1d9..e918fe8b 100644 --- a/bchain/coins/bch/bcashparser_test.go +++ b/bchain/coins/bch/bcashparser_test.go @@ -10,12 +10,12 @@ import ( ) func TestBcashAddressEncodeAddress(t *testing.T) { - addr, err := newBCashAddress("13zMwGC5bxRn9ckJ1mgxf7UR8qbbNe2iji", GetChainParams("main")) + addr1, err := newBCashAddress("13zMwGC5bxRn9ckJ1mgxf7UR8qbbNe2iji", GetChainParams("main"), Legacy) if err != nil { t.Errorf("newBCashAddress() error = %v", err) return } - got1, err := addr.EncodeAddress(bchain.DefaultAddress) + got1, err := addr1.EncodeAddress() if err != nil { t.Errorf("EncodeAddress() error = %v", err) return @@ -23,7 +23,12 @@ func TestBcashAddressEncodeAddress(t *testing.T) { if got1 != "13zMwGC5bxRn9ckJ1mgxf7UR8qbbNe2iji" { t.Errorf("EncodeAddress() got1 = %v, want %v", got1, "13zMwGC5bxRn9ckJ1mgxf7UR8qbbNe2iji") } - got2, err := addr.EncodeAddress(bchain.BCashAddress) + addr2, err := newBCashAddress("13zMwGC5bxRn9ckJ1mgxf7UR8qbbNe2iji", GetChainParams("main"), CashAddr) + if err != nil { + t.Errorf("newBCashAddress() error = %v", err) + return + } + got2, err := addr2.EncodeAddress() if err != nil { t.Errorf("EncodeAddress() error = %v", err) return @@ -34,12 +39,17 @@ func TestBcashAddressEncodeAddress(t *testing.T) { } func TestBcashAddressAreEqual(t *testing.T) { - addr, err := newBCashAddress("13zMwGC5bxRn9ckJ1mgxf7UR8qbbNe2iji", GetChainParams("main")) + addr1, err := newBCashAddress("13zMwGC5bxRn9ckJ1mgxf7UR8qbbNe2iji", GetChainParams("main"), Legacy) if err != nil { t.Errorf("newBCashAddress() error = %v", err) return } - got1, err := addr.AreEqual("13zMwGC5bxRn9ckJ1mgxf7UR8qbbNe2iji") + addr2, err := newBCashAddress("13zMwGC5bxRn9ckJ1mgxf7UR8qbbNe2iji", GetChainParams("main"), CashAddr) + if err != nil { + t.Errorf("newBCashAddress() error = %v", err) + return + } + got1, err := addr1.AreEqual("13zMwGC5bxRn9ckJ1mgxf7UR8qbbNe2iji") if err != nil { t.Errorf("AreEqual() error = %v", err) return @@ -47,7 +57,7 @@ func TestBcashAddressAreEqual(t *testing.T) { if got1 != true { t.Errorf("AreEqual() got1 = %v, want %v", got1, true) } - got2, err := addr.AreEqual("bitcoincash:qqsvjuqqwgyzvz7zz9xcvxent0ul2xjs6y4d9qvsrf") + got2, err := addr2.AreEqual("bitcoincash:qqsvjuqqwgyzvz7zz9xcvxent0ul2xjs6y4d9qvsrf") if err != nil { t.Errorf("AreEqual() error = %v", err) return @@ -55,7 +65,7 @@ func TestBcashAddressAreEqual(t *testing.T) { if got2 != true { t.Errorf("AreEqual() got2 = %v, want %v", got2, true) } - got3, err := addr.AreEqual("1HoKgKQh7ZNomWURmS9Tk3z8JM2MWm7S1w") + got3, err := addr1.AreEqual("1HoKgKQh7ZNomWURmS9Tk3z8JM2MWm7S1w") if err != nil { t.Errorf("AreEqual() error = %v", err) return @@ -63,7 +73,7 @@ func TestBcashAddressAreEqual(t *testing.T) { if got3 != false { t.Errorf("AreEqual() got3 = %v, want %v", got3, false) } - got4, err := addr.AreEqual("bitcoincash:qzuyf0gpqj7q5wfck3nyghhklju7r0k3ksmq6d0vch") + got4, err := addr2.AreEqual("bitcoincash:qzuyf0gpqj7q5wfck3nyghhklju7r0k3ksmq6d0vch") if err != nil { t.Errorf("AreEqual() error = %v", err) return @@ -74,12 +84,17 @@ func TestBcashAddressAreEqual(t *testing.T) { } func TestBcashAddressInSlice(t *testing.T) { - addr, err := newBCashAddress("13zMwGC5bxRn9ckJ1mgxf7UR8qbbNe2iji", GetChainParams("main")) + addr1, err := newBCashAddress("13zMwGC5bxRn9ckJ1mgxf7UR8qbbNe2iji", GetChainParams("main"), Legacy) if err != nil { t.Errorf("newBCashAddress() error = %v", err) return } - got1, err := addr.InSlice([]string{"13zMwGC5bxRn9ckJ1mgxf7UR8qbbNe2iji", "bitcoincash:qzuyf0gpqj7q5wfck3nyghhklju7r0k3ksmq6d0vch"}) + addr2, err := newBCashAddress("13zMwGC5bxRn9ckJ1mgxf7UR8qbbNe2iji", GetChainParams("main"), CashAddr) + if err != nil { + t.Errorf("newBCashAddress() error = %v", err) + return + } + got1, err := addr1.InSlice([]string{"13zMwGC5bxRn9ckJ1mgxf7UR8qbbNe2iji", "1HoKgKQh7ZNomWURmS9Tk3z8JM2MWm7S1w"}) if err != nil { t.Errorf("InSlice() error = %v", err) return @@ -87,7 +102,7 @@ func TestBcashAddressInSlice(t *testing.T) { if got1 != true { t.Errorf("InSlice() got1 = %v, want %v", got1, true) } - got2, err := addr.InSlice([]string{"1HoKgKQh7ZNomWURmS9Tk3z8JM2MWm7S1w", "bitcoincash:qqsvjuqqwgyzvz7zz9xcvxent0ul2xjs6y4d9qvsrf"}) + got2, err := addr2.InSlice([]string{"bitcoincash:qzuyf0gpqj7q5wfck3nyghhklju7r0k3ksmq6d0vch", "bitcoincash:qqsvjuqqwgyzvz7zz9xcvxent0ul2xjs6y4d9qvsrf"}) if err != nil { t.Errorf("InSlice() error = %v", err) return @@ -95,7 +110,7 @@ func TestBcashAddressInSlice(t *testing.T) { if got2 != true { t.Errorf("InSlice() got2 = %v, want %v", got2, true) } - got3, err := addr.InSlice([]string{"1HoKgKQh7ZNomWURmS9Tk3z8JM2MWm7S1w", "1E6Np6dUPYpBSdLMLuwBF8sRQ3cngdaRRY"}) + got3, err := addr1.InSlice([]string{"1HoKgKQh7ZNomWURmS9Tk3z8JM2MWm7S1w", "1E6Np6dUPYpBSdLMLuwBF8sRQ3cngdaRRY"}) if err != nil { t.Errorf("InSlice() error = %v", err) return @@ -103,7 +118,7 @@ func TestBcashAddressInSlice(t *testing.T) { if got3 != false { t.Errorf("InSlice() got3 = %v, want %v", got3, false) } - got4, err := addr.InSlice([]string{"bitcoincash:qzuyf0gpqj7q5wfck3nyghhklju7r0k3ksmq6d0vch", "bitcoincash:qz8emmpenqgeg7et8xsz8prvhy6cqcalyyjcamt7e9"}) + got4, err := addr2.InSlice([]string{"bitcoincash:qzuyf0gpqj7q5wfck3nyghhklju7r0k3ksmq6d0vch", "bitcoincash:qz8emmpenqgeg7et8xsz8prvhy6cqcalyyjcamt7e9"}) if err != nil { t.Errorf("InSlice() error = %v", err) return @@ -149,12 +164,12 @@ func init() { addr1, addr2, addr3 bchain.Address err error ) - addr1, err = newBCashAddress("3AZKvpKhSh1o8t1QrX3UeXG9d2BhCRnbcK", GetChainParams("main")) + addr1, err = newBCashAddress("3AZKvpKhSh1o8t1QrX3UeXG9d2BhCRnbcK", GetChainParams("main"), Legacy) if err == nil { - addr2, err = newBCashAddress("2NByHN6A8QYkBATzxf4pRGbCSHD5CEN2TRu", GetChainParams("test")) + addr2, err = newBCashAddress("2NByHN6A8QYkBATzxf4pRGbCSHD5CEN2TRu", GetChainParams("test"), Legacy) } if err == nil { - addr3, err = newBCashAddress("2MvZguYaGjM7JihBgNqgLF2Ca2Enb76Hj9D", GetChainParams("test")) + addr3, err = newBCashAddress("2MvZguYaGjM7JihBgNqgLF2Ca2Enb76Hj9D", GetChainParams("test"), Legacy) } if err != nil { panic(err) @@ -248,7 +263,7 @@ func Test_UnpackTx(t *testing.T) { name: "btc-1", args: args{ packedTx: testTxPacked1, - parser: NewBCashParser(GetChainParams("main"), &btc.Configuration{}), + parser: NewBCashParser(GetChainParams("main"), &btc.Configuration{AddressFormat: "legacy"}), }, want: &testTx1, want1: 123456, @@ -258,7 +273,7 @@ func Test_UnpackTx(t *testing.T) { name: "testnet-1", args: args{ packedTx: testTxPacked2, - parser: NewBCashParser(GetChainParams("test"), &btc.Configuration{}), + parser: NewBCashParser(GetChainParams("test"), &btc.Configuration{AddressFormat: "legacy"}), }, want: &testTx2, want1: 510234, 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..de78ed19 100644 --- a/bchain/types.go +++ b/bchain/types.go @@ -41,16 +41,9 @@ 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) + EncodeAddress() (string, error) AreEqual(addr string) (bool, error) InSlice(addrs []string) (bool, 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 b1ade76a..899059b1 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,7 +478,7 @@ func (s *SocketIoServer) getAddressHistory(addr []string, opts *addrOpts) (res r Script: &aoh, } if vout.Address != nil { - a, err := vout.Address.EncodeAddress(opts.AddressFormat) + a, err := vout.Address.EncodeAddress() if err != nil { return res, err } @@ -693,13 +688,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 +702,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 +709,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,7 +735,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) + a, err := vout.Address.EncodeAddress() if err != nil { return res, err } @@ -761,7 +753,7 @@ func (s *SocketIoServer) getDetailedTransaction(txid string, opts txOpts) (res r Script: &aos, } if vout.Address != nil { - a, err := vout.Address.EncodeAddress(opts.AddressFormat) + a, err := vout.Address.EncodeAddress() if err != nil { return res, err } 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 @@   -
-
-   - -
@@ -373,14 +353,6 @@
-
-
-   - -
@@ -443,4 +415,4 @@ document.getElementById('serverAddress').value = window.location.protocol.replace("http", "ws") + "//" + window.location.host; - \ No newline at end of file +