github.com/cerberus-wallet/blockbook@v0.3.2/bchain/coins/blockchain.go (about) 1 package coins 2 3 import ( 4 "blockbook/bchain" 5 "blockbook/bchain/coins/bch" 6 "blockbook/bchain/coins/bellcoin" 7 "blockbook/bchain/coins/bitcore" 8 "blockbook/bchain/coins/btc" 9 "blockbook/bchain/coins/btg" 10 "blockbook/bchain/coins/cpuchain" 11 "blockbook/bchain/coins/dash" 12 "blockbook/bchain/coins/dcr" 13 "blockbook/bchain/coins/deeponion" 14 "blockbook/bchain/coins/digibyte" 15 "blockbook/bchain/coins/divi" 16 "blockbook/bchain/coins/dogecoin" 17 "blockbook/bchain/coins/eth" 18 "blockbook/bchain/coins/flo" 19 "blockbook/bchain/coins/fujicoin" 20 "blockbook/bchain/coins/gamecredits" 21 "blockbook/bchain/coins/grs" 22 "blockbook/bchain/coins/koto" 23 "blockbook/bchain/coins/liquid" 24 "blockbook/bchain/coins/litecoin" 25 "blockbook/bchain/coins/monacoin" 26 "blockbook/bchain/coins/monetaryunit" 27 "blockbook/bchain/coins/myriad" 28 "blockbook/bchain/coins/namecoin" 29 "blockbook/bchain/coins/nuls" 30 "blockbook/bchain/coins/omotenashicoin" 31 "blockbook/bchain/coins/pivx" 32 "blockbook/bchain/coins/polis" 33 "blockbook/bchain/coins/qtum" 34 "blockbook/bchain/coins/ravencoin" 35 "blockbook/bchain/coins/ritocoin" 36 "blockbook/bchain/coins/unobtanium" 37 "blockbook/bchain/coins/vertcoin" 38 "blockbook/bchain/coins/viacoin" 39 "blockbook/bchain/coins/vipstarcoin" 40 "blockbook/bchain/coins/xzc" 41 "blockbook/bchain/coins/zec" 42 "blockbook/common" 43 "context" 44 "encoding/json" 45 "fmt" 46 "io/ioutil" 47 "math/big" 48 "reflect" 49 "time" 50 51 "github.com/juju/errors" 52 ) 53 54 type blockChainFactory func(config json.RawMessage, pushHandler func(bchain.NotificationType)) (bchain.BlockChain, error) 55 56 // BlockChainFactories is a map of constructors of coin RPC interfaces 57 var BlockChainFactories = make(map[string]blockChainFactory) 58 59 func init() { 60 BlockChainFactories["Bitcoin"] = btc.NewBitcoinRPC 61 BlockChainFactories["Testnet"] = btc.NewBitcoinRPC 62 BlockChainFactories["Zcash"] = zec.NewZCashRPC 63 BlockChainFactories["Zcash Testnet"] = zec.NewZCashRPC 64 BlockChainFactories["Ethereum"] = eth.NewEthereumRPC 65 BlockChainFactories["Ethereum Classic"] = eth.NewEthereumRPC 66 BlockChainFactories["Ethereum Testnet Ropsten"] = eth.NewEthereumRPC 67 BlockChainFactories["Bcash"] = bch.NewBCashRPC 68 BlockChainFactories["Bcash Testnet"] = bch.NewBCashRPC 69 BlockChainFactories["Bgold"] = btg.NewBGoldRPC 70 BlockChainFactories["Dash"] = dash.NewDashRPC 71 BlockChainFactories["Dash Testnet"] = dash.NewDashRPC 72 BlockChainFactories["Decred"] = dcr.NewDecredRPC 73 BlockChainFactories["Decred Testnet"] = dcr.NewDecredRPC 74 BlockChainFactories["GameCredits"] = gamecredits.NewGameCreditsRPC 75 BlockChainFactories["Koto"] = koto.NewKotoRPC 76 BlockChainFactories["Koto Testnet"] = koto.NewKotoRPC 77 BlockChainFactories["Litecoin"] = litecoin.NewLitecoinRPC 78 BlockChainFactories["Litecoin Testnet"] = litecoin.NewLitecoinRPC 79 BlockChainFactories["Dogecoin"] = dogecoin.NewDogecoinRPC 80 BlockChainFactories["Vertcoin"] = vertcoin.NewVertcoinRPC 81 BlockChainFactories["Vertcoin Testnet"] = vertcoin.NewVertcoinRPC 82 BlockChainFactories["Namecoin"] = namecoin.NewNamecoinRPC 83 BlockChainFactories["Monacoin"] = monacoin.NewMonacoinRPC 84 BlockChainFactories["Monacoin Testnet"] = monacoin.NewMonacoinRPC 85 BlockChainFactories["MonetaryUnit"] = monetaryunit.NewMonetaryUnitRPC 86 BlockChainFactories["DigiByte"] = digibyte.NewDigiByteRPC 87 BlockChainFactories["Myriad"] = myriad.NewMyriadRPC 88 BlockChainFactories["Liquid"] = liquid.NewLiquidRPC 89 BlockChainFactories["Groestlcoin"] = grs.NewGroestlcoinRPC 90 BlockChainFactories["Groestlcoin Testnet"] = grs.NewGroestlcoinRPC 91 BlockChainFactories["PIVX"] = pivx.NewPivXRPC 92 BlockChainFactories["PIVX Testnet"] = pivx.NewPivXRPC 93 BlockChainFactories["Polis"] = polis.NewPolisRPC 94 BlockChainFactories["Zcoin"] = xzc.NewZcoinRPC 95 BlockChainFactories["Fujicoin"] = fujicoin.NewFujicoinRPC 96 BlockChainFactories["Flo"] = flo.NewFloRPC 97 BlockChainFactories["Bellcoin"] = bellcoin.NewBellcoinRPC 98 BlockChainFactories["Qtum"] = qtum.NewQtumRPC 99 BlockChainFactories["Viacoin"] = viacoin.NewViacoinRPC 100 BlockChainFactories["Qtum Testnet"] = qtum.NewQtumRPC 101 BlockChainFactories["NULS"] = nuls.NewNulsRPC 102 BlockChainFactories["VIPSTARCOIN"] = vipstarcoin.NewVIPSTARCOINRPC 103 BlockChainFactories["ZelCash"] = zec.NewZCashRPC 104 BlockChainFactories["Ravencoin"] = ravencoin.NewRavencoinRPC 105 BlockChainFactories["Ritocoin"] = ritocoin.NewRitocoinRPC 106 BlockChainFactories["Divi"] = divi.NewDiviRPC 107 BlockChainFactories["CPUchain"] = cpuchain.NewCPUchainRPC 108 BlockChainFactories["Unobtanium"] = unobtanium.NewUnobtaniumRPC 109 BlockChainFactories["DeepOnion"] = deeponion.NewDeepOnionRPC 110 BlockChainFactories["Bitcore"] = bitcore.NewBitcoreRPC 111 BlockChainFactories["Omotenashicoin"] = omotenashicoin.NewOmotenashiCoinRPC 112 BlockChainFactories["Omotenashicoin Testnet"] = omotenashicoin.NewOmotenashiCoinRPC 113 } 114 115 // GetCoinNameFromConfig gets coin name and coin shortcut from config file 116 func GetCoinNameFromConfig(configfile string) (string, string, string, error) { 117 data, err := ioutil.ReadFile(configfile) 118 if err != nil { 119 return "", "", "", errors.Annotatef(err, "Error reading file %v", configfile) 120 } 121 var cn struct { 122 CoinName string `json:"coin_name"` 123 CoinShortcut string `json:"coin_shortcut"` 124 CoinLabel string `json:"coin_label"` 125 } 126 err = json.Unmarshal(data, &cn) 127 if err != nil { 128 return "", "", "", errors.Annotatef(err, "Error parsing file %v", configfile) 129 } 130 return cn.CoinName, cn.CoinShortcut, cn.CoinLabel, nil 131 } 132 133 // NewBlockChain creates bchain.BlockChain and bchain.Mempool for the coin passed by the parameter coin 134 func NewBlockChain(coin string, configfile string, pushHandler func(bchain.NotificationType), metrics *common.Metrics) (bchain.BlockChain, bchain.Mempool, error) { 135 data, err := ioutil.ReadFile(configfile) 136 if err != nil { 137 return nil, nil, errors.Annotatef(err, "Error reading file %v", configfile) 138 } 139 var config json.RawMessage 140 err = json.Unmarshal(data, &config) 141 if err != nil { 142 return nil, nil, errors.Annotatef(err, "Error parsing file %v", configfile) 143 } 144 bcf, ok := BlockChainFactories[coin] 145 if !ok { 146 return nil, nil, errors.New(fmt.Sprint("Unsupported coin '", coin, "'. Must be one of ", reflect.ValueOf(BlockChainFactories).MapKeys())) 147 } 148 bc, err := bcf(config, pushHandler) 149 if err != nil { 150 return nil, nil, err 151 } 152 err = bc.Initialize() 153 if err != nil { 154 return nil, nil, err 155 } 156 mempool, err := bc.CreateMempool(bc) 157 if err != nil { 158 return nil, nil, err 159 } 160 return &blockChainWithMetrics{b: bc, m: metrics}, &mempoolWithMetrics{mempool: mempool, m: metrics}, nil 161 } 162 163 type blockChainWithMetrics struct { 164 b bchain.BlockChain 165 m *common.Metrics 166 } 167 168 func (c *blockChainWithMetrics) observeRPCLatency(method string, start time.Time, err error) { 169 var e string 170 if err != nil { 171 e = "failure" 172 } 173 c.m.RPCLatency.With(common.Labels{"method": method, "error": e}).Observe(float64(time.Since(start)) / 1e6) // in milliseconds 174 } 175 176 func (c *blockChainWithMetrics) Initialize() error { 177 return c.b.Initialize() 178 } 179 180 func (c *blockChainWithMetrics) CreateMempool(chain bchain.BlockChain) (bchain.Mempool, error) { 181 return c.b.CreateMempool(chain) 182 } 183 184 func (c *blockChainWithMetrics) InitializeMempool(addrDescForOutpoint bchain.AddrDescForOutpointFunc, onNewTxAddr bchain.OnNewTxAddrFunc) error { 185 return c.b.InitializeMempool(addrDescForOutpoint, onNewTxAddr) 186 } 187 188 func (c *blockChainWithMetrics) Shutdown(ctx context.Context) error { 189 return c.b.Shutdown(ctx) 190 } 191 192 func (c *blockChainWithMetrics) IsTestnet() bool { 193 return c.b.IsTestnet() 194 } 195 196 func (c *blockChainWithMetrics) GetNetworkName() string { 197 return c.b.GetNetworkName() 198 } 199 200 func (c *blockChainWithMetrics) GetCoinName() string { 201 return c.b.GetCoinName() 202 } 203 204 func (c *blockChainWithMetrics) GetSubversion() string { 205 return c.b.GetSubversion() 206 } 207 208 func (c *blockChainWithMetrics) GetChainInfo() (v *bchain.ChainInfo, err error) { 209 defer func(s time.Time) { c.observeRPCLatency("GetChainInfo", s, err) }(time.Now()) 210 return c.b.GetChainInfo() 211 } 212 213 func (c *blockChainWithMetrics) GetBestBlockHash() (v string, err error) { 214 defer func(s time.Time) { c.observeRPCLatency("GetBestBlockHash", s, err) }(time.Now()) 215 return c.b.GetBestBlockHash() 216 } 217 218 func (c *blockChainWithMetrics) GetBestBlockHeight() (v uint32, err error) { 219 defer func(s time.Time) { c.observeRPCLatency("GetBestBlockHeight", s, err) }(time.Now()) 220 return c.b.GetBestBlockHeight() 221 } 222 223 func (c *blockChainWithMetrics) GetBlockHash(height uint32) (v string, err error) { 224 defer func(s time.Time) { c.observeRPCLatency("GetBlockHash", s, err) }(time.Now()) 225 return c.b.GetBlockHash(height) 226 } 227 228 func (c *blockChainWithMetrics) GetBlockHeader(hash string) (v *bchain.BlockHeader, err error) { 229 defer func(s time.Time) { c.observeRPCLatency("GetBlockHeader", s, err) }(time.Now()) 230 return c.b.GetBlockHeader(hash) 231 } 232 233 func (c *blockChainWithMetrics) GetBlock(hash string, height uint32) (v *bchain.Block, err error) { 234 defer func(s time.Time) { c.observeRPCLatency("GetBlock", s, err) }(time.Now()) 235 return c.b.GetBlock(hash, height) 236 } 237 238 func (c *blockChainWithMetrics) GetBlockInfo(hash string) (v *bchain.BlockInfo, err error) { 239 defer func(s time.Time) { c.observeRPCLatency("GetBlockInfo", s, err) }(time.Now()) 240 return c.b.GetBlockInfo(hash) 241 } 242 243 func (c *blockChainWithMetrics) GetMempoolTransactions() (v []string, err error) { 244 defer func(s time.Time) { c.observeRPCLatency("GetMempoolTransactions", s, err) }(time.Now()) 245 return c.b.GetMempoolTransactions() 246 } 247 248 func (c *blockChainWithMetrics) GetTransaction(txid string) (v *bchain.Tx, err error) { 249 defer func(s time.Time) { c.observeRPCLatency("GetTransaction", s, err) }(time.Now()) 250 return c.b.GetTransaction(txid) 251 } 252 253 func (c *blockChainWithMetrics) GetTransactionSpecific(tx *bchain.Tx) (v json.RawMessage, err error) { 254 defer func(s time.Time) { c.observeRPCLatency("GetTransactionSpecific", s, err) }(time.Now()) 255 return c.b.GetTransactionSpecific(tx) 256 } 257 258 func (c *blockChainWithMetrics) GetTransactionForMempool(txid string) (v *bchain.Tx, err error) { 259 defer func(s time.Time) { c.observeRPCLatency("GetTransactionForMempool", s, err) }(time.Now()) 260 return c.b.GetTransactionForMempool(txid) 261 } 262 263 func (c *blockChainWithMetrics) EstimateSmartFee(blocks int, conservative bool) (v big.Int, err error) { 264 defer func(s time.Time) { c.observeRPCLatency("EstimateSmartFee", s, err) }(time.Now()) 265 return c.b.EstimateSmartFee(blocks, conservative) 266 } 267 268 func (c *blockChainWithMetrics) EstimateFee(blocks int) (v big.Int, err error) { 269 defer func(s time.Time) { c.observeRPCLatency("EstimateFee", s, err) }(time.Now()) 270 return c.b.EstimateFee(blocks) 271 } 272 273 func (c *blockChainWithMetrics) SendRawTransaction(tx string) (v string, err error) { 274 defer func(s time.Time) { c.observeRPCLatency("SendRawTransaction", s, err) }(time.Now()) 275 return c.b.SendRawTransaction(tx) 276 } 277 278 func (c *blockChainWithMetrics) GetMempoolEntry(txid string) (v *bchain.MempoolEntry, err error) { 279 defer func(s time.Time) { c.observeRPCLatency("GetMempoolEntry", s, err) }(time.Now()) 280 return c.b.GetMempoolEntry(txid) 281 } 282 283 func (c *blockChainWithMetrics) GetChainParser() bchain.BlockChainParser { 284 return c.b.GetChainParser() 285 } 286 287 func (c *blockChainWithMetrics) EthereumTypeGetBalance(addrDesc bchain.AddressDescriptor) (v *big.Int, err error) { 288 defer func(s time.Time) { c.observeRPCLatency("EthereumTypeGetBalance", s, err) }(time.Now()) 289 return c.b.EthereumTypeGetBalance(addrDesc) 290 } 291 292 func (c *blockChainWithMetrics) EthereumTypeGetNonce(addrDesc bchain.AddressDescriptor) (v uint64, err error) { 293 defer func(s time.Time) { c.observeRPCLatency("EthereumTypeGetNonce", s, err) }(time.Now()) 294 return c.b.EthereumTypeGetNonce(addrDesc) 295 } 296 297 func (c *blockChainWithMetrics) EthereumTypeEstimateGas(params map[string]interface{}) (v uint64, err error) { 298 defer func(s time.Time) { c.observeRPCLatency("EthereumTypeEstimateGas", s, err) }(time.Now()) 299 return c.b.EthereumTypeEstimateGas(params) 300 } 301 302 func (c *blockChainWithMetrics) EthereumTypeGetErc20ContractInfo(contractDesc bchain.AddressDescriptor) (v *bchain.Erc20Contract, err error) { 303 defer func(s time.Time) { c.observeRPCLatency("EthereumTypeGetErc20ContractInfo", s, err) }(time.Now()) 304 return c.b.EthereumTypeGetErc20ContractInfo(contractDesc) 305 } 306 307 func (c *blockChainWithMetrics) EthereumTypeGetErc20ContractBalance(addrDesc, contractDesc bchain.AddressDescriptor) (v *big.Int, err error) { 308 defer func(s time.Time) { c.observeRPCLatency("EthereumTypeGetErc20ContractInfo", s, err) }(time.Now()) 309 return c.b.EthereumTypeGetErc20ContractBalance(addrDesc, contractDesc) 310 } 311 312 type mempoolWithMetrics struct { 313 mempool bchain.Mempool 314 m *common.Metrics 315 } 316 317 func (c *mempoolWithMetrics) observeRPCLatency(method string, start time.Time, err error) { 318 var e string 319 if err != nil { 320 e = "failure" 321 } 322 c.m.RPCLatency.With(common.Labels{"method": method, "error": e}).Observe(float64(time.Since(start)) / 1e6) // in milliseconds 323 } 324 325 func (c *mempoolWithMetrics) Resync() (count int, err error) { 326 defer func(s time.Time) { c.observeRPCLatency("ResyncMempool", s, err) }(time.Now()) 327 count, err = c.mempool.Resync() 328 if err == nil { 329 c.m.MempoolSize.Set(float64(count)) 330 } 331 return count, err 332 } 333 334 func (c *mempoolWithMetrics) GetTransactions(address string) (v []bchain.Outpoint, err error) { 335 defer func(s time.Time) { c.observeRPCLatency("GetMempoolTransactions", s, err) }(time.Now()) 336 return c.mempool.GetTransactions(address) 337 } 338 339 func (c *mempoolWithMetrics) GetAddrDescTransactions(addrDesc bchain.AddressDescriptor) (v []bchain.Outpoint, err error) { 340 defer func(s time.Time) { c.observeRPCLatency("GetMempoolTransactionsForAddrDesc", s, err) }(time.Now()) 341 return c.mempool.GetAddrDescTransactions(addrDesc) 342 } 343 344 func (c *mempoolWithMetrics) GetAllEntries() (v bchain.MempoolTxidEntries) { 345 defer func(s time.Time) { c.observeRPCLatency("GetAllEntries", s, nil) }(time.Now()) 346 return c.mempool.GetAllEntries() 347 } 348 349 func (c *mempoolWithMetrics) GetTransactionTime(txid string) uint32 { 350 return c.mempool.GetTransactionTime(txid) 351 }