github.com/aychain/blockbook@v0.1.1-0.20181121092459-6d1fc7e07c5b/bchain/coins/zec/zcashrpc.go (about)

     1  package zec
     2  
     3  import (
     4  	"blockbook/bchain"
     5  	"blockbook/bchain/coins/btc"
     6  	"encoding/json"
     7  
     8  	"github.com/golang/glog"
     9  	"github.com/juju/errors"
    10  )
    11  
    12  type ZCashRPC struct {
    13  	*btc.BitcoinRPC
    14  }
    15  
    16  func NewZCashRPC(config json.RawMessage, pushHandler func(bchain.NotificationType)) (bchain.BlockChain, error) {
    17  	b, err := btc.NewBitcoinRPC(config, pushHandler)
    18  	if err != nil {
    19  		return nil, err
    20  	}
    21  	z := &ZCashRPC{
    22  		BitcoinRPC: b.(*btc.BitcoinRPC),
    23  	}
    24  	z.RPCMarshaler = btc.JSONMarshalerV1{}
    25  	z.ChainConfig.SupportsEstimateSmartFee = false
    26  	return z, nil
    27  }
    28  
    29  // Initialize initializes ZCashRPC instance.
    30  func (z *ZCashRPC) Initialize() error {
    31  	chainName, err := z.GetChainInfoAndInitializeMempool(z)
    32  	if err != nil {
    33  		return err
    34  	}
    35  
    36  	params := GetChainParams(chainName)
    37  
    38  	z.Parser = NewZCashParser(params, z.ChainConfig)
    39  
    40  	// parameters for getInfo request
    41  	if params.Net == MainnetMagic {
    42  		z.Testnet = false
    43  		z.Network = "livenet"
    44  	} else {
    45  		z.Testnet = true
    46  		z.Network = "testnet"
    47  	}
    48  
    49  	glog.Info("rpc: block chain ", params.Name)
    50  
    51  	return nil
    52  }
    53  
    54  // GetBlock returns block with given hash.
    55  func (z *ZCashRPC) GetBlock(hash string, height uint32) (*bchain.Block, error) {
    56  	var err error
    57  	if hash == "" && height > 0 {
    58  		hash, err = z.GetBlockHash(height)
    59  		if err != nil {
    60  			return nil, err
    61  		}
    62  	}
    63  
    64  	glog.V(1).Info("rpc: getblock (verbosity=1) ", hash)
    65  
    66  	res := btc.ResGetBlockThin{}
    67  	req := btc.CmdGetBlock{Method: "getblock"}
    68  	req.Params.BlockHash = hash
    69  	req.Params.Verbosity = 1
    70  	err = z.Call(&req, &res)
    71  
    72  	if err != nil {
    73  		return nil, errors.Annotatef(err, "hash %v", hash)
    74  	}
    75  	if res.Error != nil {
    76  		return nil, errors.Annotatef(res.Error, "hash %v", hash)
    77  	}
    78  
    79  	txs := make([]bchain.Tx, 0, len(res.Result.Txids))
    80  	for _, txid := range res.Result.Txids {
    81  		tx, err := z.GetTransaction(txid)
    82  		if err != nil {
    83  			if isInvalidTx(err) {
    84  				glog.Errorf("rpc: getblock: skipping transanction in block %s due error: %s", hash, err)
    85  				continue
    86  			}
    87  			return nil, err
    88  		}
    89  		txs = append(txs, *tx)
    90  	}
    91  	block := &bchain.Block{
    92  		BlockHeader: res.Result.BlockHeader,
    93  		Txs:         txs,
    94  	}
    95  	return block, nil
    96  }
    97  
    98  func isInvalidTx(err error) bool {
    99  	switch e1 := err.(type) {
   100  	case *errors.Err:
   101  		switch e2 := e1.Cause().(type) {
   102  		case *bchain.RPCError:
   103  			if e2.Code == -5 { // "No information available about transaction"
   104  				return true
   105  			}
   106  		}
   107  	}
   108  
   109  	return false
   110  }
   111  
   112  // GetTransactionForMempool returns a transaction by the transaction ID.
   113  // It could be optimized for mempool, i.e. without block time and confirmations
   114  func (z *ZCashRPC) GetTransactionForMempool(txid string) (*bchain.Tx, error) {
   115  	return z.GetTransaction(txid)
   116  }
   117  
   118  // GetMempoolEntry returns mempool data for given transaction
   119  func (z *ZCashRPC) GetMempoolEntry(txid string) (*bchain.MempoolEntry, error) {
   120  	return nil, errors.New("GetMempoolEntry: not implemented")
   121  }
   122  
   123  func isErrBlockNotFound(err *bchain.RPCError) bool {
   124  	return err.Message == "Block not found" ||
   125  		err.Message == "Block height out of range"
   126  }