github.com/trezor/blockbook@v0.4.1-0.20240328132726-e9a08582ee2c/bchain/coins/zec/zcashrpc.go (about)

     1  package zec
     2  
     3  import (
     4  	"encoding/json"
     5  
     6  	"github.com/golang/glog"
     7  	"github.com/juju/errors"
     8  	"github.com/trezor/blockbook/bchain"
     9  	"github.com/trezor/blockbook/bchain/coins/btc"
    10  	"github.com/trezor/blockbook/common"
    11  )
    12  
    13  // ZCashRPC is an interface to JSON-RPC bitcoind service
    14  type ZCashRPC struct {
    15  	*btc.BitcoinRPC
    16  }
    17  
    18  // ResGetBlockChainInfo is a response to GetChainInfo request
    19  type ResGetBlockChainInfo struct {
    20  	Error  *bchain.RPCError `json:"error"`
    21  	Result struct {
    22  		Chain         string            `json:"chain"`
    23  		Blocks        int               `json:"blocks"`
    24  		Headers       int               `json:"headers"`
    25  		Bestblockhash string            `json:"bestblockhash"`
    26  		Difficulty    common.JSONNumber `json:"difficulty"`
    27  		Pruned        bool              `json:"pruned"`
    28  		SizeOnDisk    int64             `json:"size_on_disk"`
    29  		Consensus     struct {
    30  			Chaintip  string `json:"chaintip"`
    31  			Nextblock string `json:"nextblock"`
    32  		} `json:"consensus"`
    33  	} `json:"result"`
    34  }
    35  
    36  // NewZCashRPC returns new ZCashRPC instance
    37  func NewZCashRPC(config json.RawMessage, pushHandler func(bchain.NotificationType)) (bchain.BlockChain, error) {
    38  	b, err := btc.NewBitcoinRPC(config, pushHandler)
    39  	if err != nil {
    40  		return nil, err
    41  	}
    42  	z := &ZCashRPC{
    43  		BitcoinRPC: b.(*btc.BitcoinRPC),
    44  	}
    45  	z.RPCMarshaler = btc.JSONMarshalerV1{}
    46  	z.ChainConfig.SupportsEstimateSmartFee = false
    47  	return z, nil
    48  }
    49  
    50  // Initialize initializes ZCashRPC instance
    51  func (z *ZCashRPC) Initialize() error {
    52  	ci, err := z.GetChainInfo()
    53  	if err != nil {
    54  		return err
    55  	}
    56  	chainName := ci.Chain
    57  
    58  	params := GetChainParams(chainName)
    59  
    60  	z.Parser = NewZCashParser(params, z.ChainConfig)
    61  
    62  	// parameters for getInfo request
    63  	if params.Net == MainnetMagic {
    64  		z.Testnet = false
    65  		z.Network = "livenet"
    66  	} else {
    67  		z.Testnet = true
    68  		z.Network = "testnet"
    69  	}
    70  
    71  	glog.Info("rpc: block chain ", params.Name)
    72  
    73  	return nil
    74  }
    75  
    76  // GetChainInfo return info about the blockchain
    77  func (z *ZCashRPC) GetChainInfo() (*bchain.ChainInfo, error) {
    78  	chainInfo := ResGetBlockChainInfo{}
    79  	err := z.Call(&btc.CmdGetBlockChainInfo{Method: "getblockchaininfo"}, &chainInfo)
    80  	if err != nil {
    81  		return nil, err
    82  	}
    83  	if chainInfo.Error != nil {
    84  		return nil, chainInfo.Error
    85  	}
    86  
    87  	networkInfo := btc.ResGetNetworkInfo{}
    88  	err = z.Call(&btc.CmdGetNetworkInfo{Method: "getnetworkinfo"}, &networkInfo)
    89  	if err != nil {
    90  		return nil, err
    91  	}
    92  	if networkInfo.Error != nil {
    93  		return nil, networkInfo.Error
    94  	}
    95  
    96  	return &bchain.ChainInfo{
    97  		Bestblockhash:   chainInfo.Result.Bestblockhash,
    98  		Blocks:          chainInfo.Result.Blocks,
    99  		Chain:           chainInfo.Result.Chain,
   100  		Difficulty:      string(chainInfo.Result.Difficulty),
   101  		Headers:         chainInfo.Result.Headers,
   102  		SizeOnDisk:      chainInfo.Result.SizeOnDisk,
   103  		Version:         string(networkInfo.Result.Version),
   104  		Subversion:      string(networkInfo.Result.Subversion),
   105  		ProtocolVersion: string(networkInfo.Result.ProtocolVersion),
   106  		Timeoffset:      networkInfo.Result.Timeoffset,
   107  		Consensus:       chainInfo.Result.Consensus,
   108  		Warnings:        networkInfo.Result.Warnings,
   109  	}, nil
   110  }
   111  
   112  // GetBlock returns block with given hash.
   113  func (z *ZCashRPC) GetBlock(hash string, height uint32) (*bchain.Block, error) {
   114  	var err error
   115  	if hash == "" && height > 0 {
   116  		hash, err = z.GetBlockHash(height)
   117  		if err != nil {
   118  			return nil, err
   119  		}
   120  	}
   121  
   122  	glog.V(1).Info("rpc: getblock (verbosity=1) ", hash)
   123  
   124  	res := btc.ResGetBlockThin{}
   125  	req := btc.CmdGetBlock{Method: "getblock"}
   126  	req.Params.BlockHash = hash
   127  	req.Params.Verbosity = 1
   128  	err = z.Call(&req, &res)
   129  
   130  	if err != nil {
   131  		return nil, errors.Annotatef(err, "hash %v", hash)
   132  	}
   133  	if res.Error != nil {
   134  		return nil, errors.Annotatef(res.Error, "hash %v", hash)
   135  	}
   136  
   137  	txs := make([]bchain.Tx, 0, len(res.Result.Txids))
   138  	for _, txid := range res.Result.Txids {
   139  		tx, err := z.GetTransaction(txid)
   140  		if err != nil {
   141  			if err == bchain.ErrTxNotFound {
   142  				glog.Errorf("rpc: getblock: skipping transanction in block %s due error: %s", hash, err)
   143  				continue
   144  			}
   145  			return nil, err
   146  		}
   147  		txs = append(txs, *tx)
   148  	}
   149  	block := &bchain.Block{
   150  		BlockHeader: res.Result.BlockHeader,
   151  		Txs:         txs,
   152  	}
   153  	return block, nil
   154  }
   155  
   156  // GetTransactionForMempool returns a transaction by the transaction ID.
   157  // It could be optimized for mempool, i.e. without block time and confirmations
   158  func (z *ZCashRPC) GetTransactionForMempool(txid string) (*bchain.Tx, error) {
   159  	return z.GetTransaction(txid)
   160  }
   161  
   162  // GetMempoolEntry returns mempool data for given transaction
   163  func (z *ZCashRPC) GetMempoolEntry(txid string) (*bchain.MempoolEntry, error) {
   164  	return nil, errors.New("GetMempoolEntry: not implemented")
   165  }
   166  
   167  // GetBlockRaw is not supported
   168  func (z *ZCashRPC) GetBlockRaw(hash string) (string, error) {
   169  	return "", errors.New("GetBlockRaw: not supported")
   170  }