github.com/cerberus-wallet/blockbook@v0.3.2/bchain/coins/xzc/zcoinrpc.go (about) 1 package xzc 2 3 import ( 4 "blockbook/bchain" 5 "blockbook/bchain/coins/btc" 6 "encoding/hex" 7 "encoding/json" 8 9 "github.com/golang/glog" 10 "github.com/juju/errors" 11 ) 12 13 type ZcoinRPC struct { 14 *btc.BitcoinRPC 15 } 16 17 func NewZcoinRPC(config json.RawMessage, pushHandler func(bchain.NotificationType)) (bchain.BlockChain, error) { 18 // init base implementation 19 bc, err := btc.NewBitcoinRPC(config, pushHandler) 20 if err != nil { 21 return nil, err 22 } 23 24 // init zcoin implementation 25 zc := &ZcoinRPC{ 26 BitcoinRPC: bc.(*btc.BitcoinRPC), 27 } 28 29 zc.ChainConfig.Parse = true 30 zc.ChainConfig.SupportsEstimateFee = true 31 zc.ChainConfig.SupportsEstimateSmartFee = false 32 zc.ParseBlocks = true 33 zc.RPCMarshaler = btc.JSONMarshalerV1{} 34 35 return zc, nil 36 } 37 38 func (zc *ZcoinRPC) Initialize() error { 39 ci, err := zc.GetChainInfo() 40 if err != nil { 41 return err 42 } 43 chainName := ci.Chain 44 45 params := GetChainParams(chainName) 46 47 // always create parser 48 zc.Parser = NewZcoinParser(params, zc.ChainConfig) 49 50 // parameters for getInfo request 51 if params.Net == MainnetMagic { 52 zc.Testnet = false 53 zc.Network = "livenet" 54 } else { 55 zc.Testnet = true 56 zc.Network = "testnet" 57 } 58 59 glog.Info("rpc: block chain ", params.Name) 60 61 return nil 62 } 63 64 func (zc *ZcoinRPC) GetBlock(hash string, height uint32) (*bchain.Block, error) { 65 var err error 66 67 if hash == "" { 68 hash, err = zc.GetBlockHash(height) 69 if err != nil { 70 return nil, err 71 } 72 } 73 74 // optimization 75 if height > 0 { 76 return zc.GetBlockWithoutHeader(hash, height) 77 } 78 79 header, err := zc.GetBlockHeader(hash) 80 if err != nil { 81 return nil, err 82 } 83 84 data, err := zc.GetBlockRaw(hash) 85 if err != nil { 86 return nil, err 87 } 88 89 block, err := zc.Parser.ParseBlock(data) 90 if err != nil { 91 return nil, errors.Annotatef(err, "hash %v", hash) 92 } 93 94 block.BlockHeader = *header 95 96 return block, nil 97 } 98 99 func (zc *ZcoinRPC) GetBlockInfo(hash string) (*bchain.BlockInfo, error) { 100 glog.V(1).Info("rpc: getblock (verbosity=true) ", hash) 101 102 res := btc.ResGetBlockInfo{} 103 req := cmdGetBlock{Method: "getblock"} 104 req.Params.BlockHash = hash 105 req.Params.Verbosity = true 106 err := zc.Call(&req, &res) 107 108 if err != nil { 109 return nil, errors.Annotatef(err, "hash %v", hash) 110 } 111 if res.Error != nil { 112 if btc.IsErrBlockNotFound(res.Error) { 113 return nil, bchain.ErrBlockNotFound 114 } 115 return nil, errors.Annotatef(res.Error, "hash %v", hash) 116 } 117 return &res.Result, nil 118 } 119 120 func (zc *ZcoinRPC) GetBlockWithoutHeader(hash string, height uint32) (*bchain.Block, error) { 121 data, err := zc.GetBlockRaw(hash) 122 if err != nil { 123 return nil, err 124 } 125 126 block, err := zc.Parser.ParseBlock(data) 127 if err != nil { 128 return nil, errors.Annotatef(err, "%v %v", height, hash) 129 } 130 131 block.BlockHeader.Hash = hash 132 block.BlockHeader.Height = height 133 134 return block, nil 135 } 136 137 func (zc *ZcoinRPC) GetBlockRaw(hash string) ([]byte, error) { 138 glog.V(1).Info("rpc: getblock (verbosity=false) ", hash) 139 140 res := btc.ResGetBlockRaw{} 141 req := cmdGetBlock{Method: "getblock"} 142 req.Params.BlockHash = hash 143 req.Params.Verbosity = false 144 err := zc.Call(&req, &res) 145 146 if err != nil { 147 return nil, errors.Annotatef(err, "hash %v", hash) 148 } 149 if res.Error != nil { 150 if btc.IsErrBlockNotFound(res.Error) { 151 return nil, bchain.ErrBlockNotFound 152 } 153 return nil, errors.Annotatef(res.Error, "hash %v", hash) 154 } 155 return hex.DecodeString(res.Result) 156 } 157 158 func (zc *ZcoinRPC) GetTransactionForMempool(txid string) (*bchain.Tx, error) { 159 glog.V(1).Info("rpc: getrawtransaction nonverbose ", txid) 160 161 res := btc.ResGetRawTransactionNonverbose{} 162 req := cmdGetRawTransaction{Method: "getrawtransaction"} 163 req.Params.Txid = txid 164 req.Params.Verbose = 0 165 err := zc.Call(&req, &res) 166 if err != nil { 167 return nil, errors.Annotatef(err, "txid %v", txid) 168 } 169 if res.Error != nil { 170 if btc.IsMissingTx(res.Error) { 171 return nil, bchain.ErrTxNotFound 172 } 173 return nil, errors.Annotatef(res.Error, "txid %v", txid) 174 } 175 data, err := hex.DecodeString(res.Result) 176 if err != nil { 177 return nil, errors.Annotatef(err, "txid %v", txid) 178 } 179 tx, err := zc.Parser.ParseTx(data) 180 if err != nil { 181 return nil, errors.Annotatef(err, "txid %v", txid) 182 } 183 return tx, nil 184 } 185 186 func (zc *ZcoinRPC) GetTransaction(txid string) (*bchain.Tx, error) { 187 r, err := zc.getRawTransaction(txid) 188 if err != nil { 189 return nil, err 190 } 191 192 tx, err := zc.Parser.ParseTxFromJson(r) 193 tx.CoinSpecificData = r 194 if err != nil { 195 return nil, errors.Annotatef(err, "txid %v", txid) 196 } 197 198 return tx, nil 199 } 200 201 func (zc *ZcoinRPC) GetTransactionSpecific(tx *bchain.Tx) (json.RawMessage, error) { 202 if csd, ok := tx.CoinSpecificData.(json.RawMessage); ok { 203 return csd, nil 204 } 205 return zc.getRawTransaction(tx.Txid) 206 } 207 208 func (zc *ZcoinRPC) getRawTransaction(txid string) (json.RawMessage, error) { 209 glog.V(1).Info("rpc: getrawtransaction ", txid) 210 211 res := btc.ResGetRawTransaction{} 212 req := cmdGetRawTransaction{Method: "getrawtransaction"} 213 req.Params.Txid = txid 214 req.Params.Verbose = 1 215 err := zc.Call(&req, &res) 216 217 if err != nil { 218 return nil, errors.Annotatef(err, "txid %v", txid) 219 } 220 if res.Error != nil { 221 if btc.IsMissingTx(res.Error) { 222 return nil, bchain.ErrTxNotFound 223 } 224 return nil, errors.Annotatef(res.Error, "txid %v", txid) 225 } 226 return res.Result, nil 227 } 228 229 type cmdGetBlock struct { 230 Method string `json:"method"` 231 Params struct { 232 BlockHash string `json:"blockhash"` 233 Verbosity bool `json:"verbosity"` 234 } `json:"params"` 235 } 236 237 type cmdGetRawTransaction struct { 238 Method string `json:"method"` 239 Params struct { 240 Txid string `json:"txid"` 241 Verbose int `json:"verbose"` 242 } `json:"params"` 243 }