github.com/cerberus-wallet/blockbook@v0.3.2/bchain/coins/bch/bcashrpc.go (about) 1 package bch 2 3 import ( 4 "blockbook/bchain" 5 "blockbook/bchain/coins/btc" 6 "encoding/hex" 7 "encoding/json" 8 "math/big" 9 10 "github.com/golang/glog" 11 "github.com/juju/errors" 12 "github.com/martinboehm/bchutil" 13 ) 14 15 // BCashRPC is an interface to JSON-RPC bitcoind service. 16 type BCashRPC struct { 17 *btc.BitcoinRPC 18 } 19 20 // NewBCashRPC returns new BCashRPC instance. 21 func NewBCashRPC(config json.RawMessage, pushHandler func(bchain.NotificationType)) (bchain.BlockChain, error) { 22 b, err := btc.NewBitcoinRPC(config, pushHandler) 23 if err != nil { 24 return nil, err 25 } 26 27 s := &BCashRPC{ 28 b.(*btc.BitcoinRPC), 29 } 30 s.ChainConfig.SupportsEstimateSmartFee = false 31 32 return s, nil 33 } 34 35 // Initialize initializes BCashRPC instance. 36 func (b *BCashRPC) Initialize() error { 37 ci, err := b.GetChainInfo() 38 if err != nil { 39 return err 40 } 41 chainName := ci.Chain 42 43 params := GetChainParams(chainName) 44 45 // always create parser 46 b.Parser, err = NewBCashParser(params, b.ChainConfig) 47 48 if err != nil { 49 return err 50 } 51 52 // parameters for getInfo request 53 if params.Net == bchutil.MainnetMagic { 54 b.Testnet = false 55 b.Network = "livenet" 56 } else { 57 b.Testnet = true 58 b.Network = "testnet" 59 } 60 61 glog.Info("rpc: block chain ", params.Name) 62 63 return nil 64 } 65 66 // getblock 67 68 type cmdGetBlock struct { 69 Method string `json:"method"` 70 Params struct { 71 BlockHash string `json:"blockhash"` 72 Verbose bool `json:"verbose"` 73 } `json:"params"` 74 } 75 76 // estimatesmartfee 77 78 type cmdEstimateSmartFee struct { 79 Method string `json:"method"` 80 Params struct { 81 Blocks int `json:"nblocks"` 82 } `json:"params"` 83 } 84 85 // GetBlock returns block with given hash. 86 func (b *BCashRPC) GetBlock(hash string, height uint32) (*bchain.Block, error) { 87 var err error 88 if hash == "" && height > 0 { 89 hash, err = b.GetBlockHash(height) 90 if err != nil { 91 return nil, err 92 } 93 } 94 header, err := b.GetBlockHeader(hash) 95 if err != nil { 96 return nil, err 97 } 98 data, err := b.GetBlockRaw(hash) 99 if err != nil { 100 return nil, err 101 } 102 block, err := b.Parser.ParseBlock(data) 103 if err != nil { 104 return nil, errors.Annotatef(err, "hash %v", hash) 105 } 106 // size is not returned by GetBlockHeader and would be overwritten 107 size := block.Size 108 block.BlockHeader = *header 109 block.Size = size 110 return block, nil 111 } 112 113 // GetBlockRaw returns block with given hash as bytes. 114 func (b *BCashRPC) GetBlockRaw(hash string) ([]byte, error) { 115 glog.V(1).Info("rpc: getblock (verbose=0) ", hash) 116 117 res := btc.ResGetBlockRaw{} 118 req := cmdGetBlock{Method: "getblock"} 119 req.Params.BlockHash = hash 120 req.Params.Verbose = false 121 err := b.Call(&req, &res) 122 123 if err != nil { 124 return nil, errors.Annotatef(err, "hash %v", hash) 125 } 126 if res.Error != nil { 127 if isErrBlockNotFound(res.Error) { 128 return nil, bchain.ErrBlockNotFound 129 } 130 return nil, errors.Annotatef(res.Error, "hash %v", hash) 131 } 132 return hex.DecodeString(res.Result) 133 } 134 135 // GetBlockInfo returns extended header (more info than in bchain.BlockHeader) with a list of txids 136 func (b *BCashRPC) GetBlockInfo(hash string) (*bchain.BlockInfo, error) { 137 glog.V(1).Info("rpc: getblock (verbosity=1) ", hash) 138 139 res := btc.ResGetBlockInfo{} 140 req := cmdGetBlock{Method: "getblock"} 141 req.Params.BlockHash = hash 142 req.Params.Verbose = true 143 err := b.Call(&req, &res) 144 145 if err != nil { 146 return nil, errors.Annotatef(err, "hash %v", hash) 147 } 148 if res.Error != nil { 149 if isErrBlockNotFound(res.Error) { 150 return nil, bchain.ErrBlockNotFound 151 } 152 return nil, errors.Annotatef(res.Error, "hash %v", hash) 153 } 154 return &res.Result, nil 155 } 156 157 // GetBlockFull returns block with given hash. 158 func (b *BCashRPC) GetBlockFull(hash string) (*bchain.Block, error) { 159 return nil, errors.New("Not implemented") 160 } 161 162 func isErrBlockNotFound(err *bchain.RPCError) bool { 163 return err.Message == "Block not found" || 164 err.Message == "Block height out of range" 165 } 166 167 // EstimateFee returns fee estimation 168 func (b *BCashRPC) EstimateFee(blocks int) (big.Int, error) { 169 // from version BitcoinABC version 0.19.1 EstimateFee does not support parameter Blocks 170 if b.ChainConfig.CoinShortcut == "BCHSV" { 171 return b.BitcoinRPC.EstimateFee(blocks) 172 } 173 174 glog.V(1).Info("rpc: estimatefee ", blocks) 175 176 res := btc.ResEstimateFee{} 177 req := struct { 178 Method string `json:"method"` 179 }{ 180 Method: "estimatefee", 181 } 182 183 err := b.Call(&req, &res) 184 185 var r big.Int 186 if err != nil { 187 return r, err 188 } 189 if res.Error != nil { 190 return r, res.Error 191 } 192 r, err = b.Parser.AmountToBigInt(res.Result) 193 if err != nil { 194 return r, err 195 } 196 return r, nil 197 } 198 199 // EstimateSmartFee returns fee estimation 200 func (b *BCashRPC) EstimateSmartFee(blocks int, conservative bool) (big.Int, error) { 201 // EstimateSmartFee is not supported by bcash 202 return b.EstimateFee(blocks) 203 }