diff --git a/bchain/coins/btc/bitcoinparser.go b/bchain/coins/btc/bitcoinparser.go index 415082a2..692d1170 100644 --- a/bchain/coins/btc/bitcoinparser.go +++ b/bchain/coins/btc/bitcoinparser.go @@ -41,8 +41,8 @@ func (p *BitcoinBlockParser) GetUIDFromAddress(address string) ([]byte, error) { return p.AddressToOutputScript(address) } -func (p *BitcoinBlockParser) PackUID(script string) ([]byte, error) { - return hex.DecodeString(script) +func (p *BitcoinBlockParser) PackUID(str string) ([]byte, error) { + return hex.DecodeString(str) } func (p *BitcoinBlockParser) UnpackUID(buf []byte) string { diff --git a/bchain/coins/btc/bitcoinrpc.go b/bchain/coins/btc/bitcoinrpc.go index d57c94d2..ba4f62d5 100644 --- a/bchain/coins/btc/bitcoinrpc.go +++ b/bchain/coins/btc/bitcoinrpc.go @@ -24,7 +24,7 @@ type BitcoinRPC struct { rpcURL string user string password string - Parser *BitcoinBlockParser + Parser bchain.BlockChainParser Testnet bool Network string Mempool *bchain.Mempool @@ -64,26 +64,6 @@ func NewBitcoinRPC(config json.RawMessage, pushHandler func(*bchain.MQMessage), ParseBlocks: c.Parse, metrics: metrics, } - chainName, err := s.GetBlockChainInfo() - if err != nil { - return nil, err - } - - // always create parser - s.Parser = &BitcoinBlockParser{ - Params: GetChainParams(chainName), - } - - // parameters for getInfo request - if s.Parser.Params.Net == wire.MainNet { - s.Testnet = false - s.Network = "livenet" - } else { - s.Testnet = true - s.Network = "testnet" - } - - glog.Info("rpc: block chain ", s.Parser.Params.Name) mq, err := bchain.NewMQ(c.ZeroMQBinding, pushHandler) if err != nil { @@ -95,6 +75,35 @@ func NewBitcoinRPC(config json.RawMessage, pushHandler func(*bchain.MQMessage), return s, nil } +func (b *BitcoinRPC) Initialize(mempool *bchain.Mempool) error { + b.Mempool = mempool + + chainName, err := b.GetBlockChainInfo() + if err != nil { + return err + } + + params := GetChainParams(chainName) + + // always create parser + b.Parser = &BitcoinBlockParser{ + Params: params, + } + + // parameters for getInfo request + if params.Net == wire.MainNet { + b.Testnet = false + b.Network = "livenet" + } else { + b.Testnet = true + b.Network = "testnet" + } + + glog.Info("rpc: block chain ", params.Name) + + return nil +} + func (b *BitcoinRPC) Shutdown() error { if b.mq != nil { if err := b.mq.Shutdown(); err != nil { @@ -105,10 +114,6 @@ func (b *BitcoinRPC) Shutdown() error { return nil } -func (b *BitcoinRPC) Initialize(mempool *bchain.Mempool) { - b.Mempool = mempool -} - func (b *BitcoinRPC) IsTestnet() bool { return b.Testnet } diff --git a/bchain/coins/zec/zcashparser.go b/bchain/coins/zec/zcashparser.go new file mode 100644 index 00000000..fab2b5ba --- /dev/null +++ b/bchain/coins/zec/zcashparser.go @@ -0,0 +1,46 @@ +package zec + +import ( + "blockbook/bchain" + "blockbook/bchain/coins/btc" + + "github.com/btcsuite/btcd/chaincfg" +) + +// bitcoinwire parsing + +type ZCashBlockParser struct { + btc.BitcoinBlockParser +} + +// getChainParams contains network parameters for the main Bitcoin network, +// the regression test Bitcoin network, the test Bitcoin network and +// the simulation test Bitcoin network, in this order +func GetChainParams(chain string) *chaincfg.Params { + switch chain { + case "test": + return &chaincfg.TestNet3Params + case "regtest": + return &chaincfg.RegressionNetParams + } + return &chaincfg.MainNetParams +} + +func (p *ZCashBlockParser) GetUIDFromVout(output *bchain.Vout) string { + if len(output.ScriptPubKey.Addresses) != 1 { + return "" + } + return output.ScriptPubKey.Addresses[0] +} + +func (p *ZCashBlockParser) GetUIDFromAddress(address string) ([]byte, error) { + return p.PackUID(address) +} + +func (p *ZCashBlockParser) PackUID(str string) ([]byte, error) { + return []byte(str), nil +} + +func (p *ZCashBlockParser) UnpackUID(buf []byte) string { + return string(buf) +} diff --git a/bchain/coins/zec/zcashrpc.go b/bchain/coins/zec/zcashrpc.go index 743cf026..5f6dd539 100644 --- a/bchain/coins/zec/zcashrpc.go +++ b/bchain/coins/zec/zcashrpc.go @@ -6,6 +6,8 @@ import ( "blockbook/common" "encoding/json" + "github.com/btcsuite/btcd/wire" + "github.com/golang/glog" "github.com/juju/errors" ) @@ -25,6 +27,37 @@ func NewZCashRPC(config json.RawMessage, pushHandler func(*bchain.MQMessage), me return z, nil } +func (z *ZCashRPC) Initialize(mempool *bchain.Mempool) error { + z.Mempool = mempool + + chainName, err := z.GetBlockChainInfo() + if err != nil { + return err + } + + params := GetChainParams(chainName) + + // always create parser + z.Parser = &ZCashBlockParser{ + btc.BitcoinBlockParser{ + Params: params, + }, + } + + // parameters for getInfo request + if params.Net == wire.MainNet { + z.Testnet = false + z.Network = "livenet" + } else { + z.Testnet = true + z.Network = "testnet" + } + + glog.Info("rpc: block chain ", params.Name) + + return nil +} + type untypedArrayParams struct { Method string `json:"method"` Params []interface{} `json:"params"` @@ -145,8 +178,3 @@ func (z *ZCashRPC) GetBlockHeader(hash string) (*bchain.BlockHeader, error) { } return &res.Result, nil } - -// GetChainParser returns BlockChainParser -func (z *ZCashRPC) GetChainParser() bchain.BlockChainParser { - return z.Parser -} diff --git a/bchain/mempool.go b/bchain/mempool.go index 37155fda..a37b6c93 100644 --- a/bchain/mempool.go +++ b/bchain/mempool.go @@ -27,7 +27,6 @@ type inputOutput struct { // Mempool is mempool handle. type Mempool struct { chain BlockChain - chainParser BlockChainParser mux sync.Mutex txToInputOutput map[string]inputOutput scriptToTx map[string][]outpoint // TODO rename all occurences @@ -37,18 +36,19 @@ type Mempool struct { // NewMempool creates new mempool handler. func NewMempool(chain BlockChain, metrics *common.Metrics) *Mempool { - return &Mempool{chain: chain, chainParser: chain.GetChainParser(), metrics: metrics} + return &Mempool{chain: chain, metrics: metrics} } // GetTransactions returns slice of mempool transactions for given output script. func (m *Mempool) GetTransactions(address string) ([]string, error) { m.mux.Lock() defer m.mux.Unlock() - buf, err := m.chainParser.GetUIDFromAddress(address) + parser := m.chain.GetChainParser() + buf, err := parser.GetUIDFromAddress(address) if err != nil { return nil, err } - outid := m.chainParser.UnpackUID(buf) + outid := parser.UnpackUID(buf) outpoints := m.scriptToTx[outid] txs := make([]string, 0, len(outpoints)+len(outpoints)/2) for _, o := range outpoints { @@ -86,6 +86,7 @@ func (m *Mempool) Resync(onNewTxAddr func(txid string, addr string)) error { m.metrics.MempoolResyncErrors.With(common.Labels{"error": err.Error()}).Inc() return err } + parser := m.chain.GetChainParser() newTxToInputOutput := make(map[string]inputOutput, len(m.txToInputOutput)+1) newScriptToTx := make(map[string][]outpoint, len(m.scriptToTx)+1) newInputs := make(map[outpoint]string, len(m.inputs)+1) @@ -100,7 +101,7 @@ func (m *Mempool) Resync(onNewTxAddr func(txid string, addr string)) error { } io.outputs = make([]scriptIndex, 0, len(tx.Vout)) for _, output := range tx.Vout { - outid := m.chainParser.GetUIDFromVout(&output) + outid := parser.GetUIDFromVout(&output) if outid != "" { io.outputs = append(io.outputs, scriptIndex{outid, output.N}) } diff --git a/bchain/types.go b/bchain/types.go index 4d0d5e28..6e665364 100644 --- a/bchain/types.go +++ b/bchain/types.go @@ -87,7 +87,7 @@ func (e *RPCError) Error() string { type BlockChain interface { // life-cycle methods - Initialize(mempool *Mempool) + Initialize(mempool *Mempool) error Shutdown() error // chain info IsTestnet() bool diff --git a/db/rocksdb.go b/db/rocksdb.go index 43d01260..50ce4438 100644 --- a/db/rocksdb.go +++ b/db/rocksdb.go @@ -266,7 +266,7 @@ func (d *RocksDB) writeOutputs(wb *gorocksdb.WriteBatch, block *bchain.Block, op for outid, outpoints := range records { bOutid, err := d.chainParser.PackUID(outid) if err != nil { - glog.Warningf("rocksdb: packOutputID: %v - %d %s", err, block.Height, outid) + glog.Warningf("rocksdb: packUID: %v - %d %s", err, block.Height, outid) continue } key, err := packOutputKey(bOutid, block.Height)