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 }