github.com/aychain/blockbook@v0.1.1-0.20181121092459-6d1fc7e07c5b/bchain/coins/blockchain.go (about) 1 package coins 2 3 import ( 4 "blockbook/bchain" 5 "blockbook/bchain/coins/bch" 6 "blockbook/bchain/coins/btc" 7 "blockbook/bchain/coins/btg" 8 "blockbook/bchain/coins/dash" 9 "blockbook/bchain/coins/digibyte" 10 "blockbook/bchain/coins/dogecoin" 11 "blockbook/bchain/coins/eth" 12 "blockbook/bchain/coins/gamecredits" 13 "blockbook/bchain/coins/grs" 14 "blockbook/bchain/coins/litecoin" 15 "blockbook/bchain/coins/monacoin" 16 "blockbook/bchain/coins/myriad" 17 "blockbook/bchain/coins/namecoin" 18 "blockbook/bchain/coins/vertcoin" 19 "blockbook/bchain/coins/zec" 20 "blockbook/common" 21 "context" 22 "encoding/json" 23 "fmt" 24 "io/ioutil" 25 "math/big" 26 "reflect" 27 "time" 28 29 "github.com/juju/errors" 30 ) 31 32 type blockChainFactory func(config json.RawMessage, pushHandler func(bchain.NotificationType)) (bchain.BlockChain, error) 33 34 var BlockChainFactories = make(map[string]blockChainFactory) 35 36 func init() { 37 BlockChainFactories["Bitcoin"] = btc.NewBitcoinRPC 38 BlockChainFactories["Testnet"] = btc.NewBitcoinRPC 39 BlockChainFactories["Zcash"] = zec.NewZCashRPC 40 BlockChainFactories["Zcash Testnet"] = zec.NewZCashRPC 41 BlockChainFactories["Ethereum"] = eth.NewEthereumRPC 42 BlockChainFactories["Ethereum Classic"] = eth.NewEthereumRPC 43 BlockChainFactories["Ethereum Testnet Ropsten"] = eth.NewEthereumRPC 44 BlockChainFactories["Bcash"] = bch.NewBCashRPC 45 BlockChainFactories["Bcash Testnet"] = bch.NewBCashRPC 46 BlockChainFactories["Bgold"] = btg.NewBGoldRPC 47 BlockChainFactories["Dash"] = dash.NewDashRPC 48 BlockChainFactories["Dash Testnet"] = dash.NewDashRPC 49 BlockChainFactories["GameCredits"] = gamecredits.NewGameCreditsRPC 50 BlockChainFactories["Litecoin"] = litecoin.NewLitecoinRPC 51 BlockChainFactories["Litecoin Testnet"] = litecoin.NewLitecoinRPC 52 BlockChainFactories["Dogecoin"] = dogecoin.NewDogecoinRPC 53 BlockChainFactories["Vertcoin"] = vertcoin.NewVertcoinRPC 54 BlockChainFactories["Vertcoin Testnet"] = vertcoin.NewVertcoinRPC 55 BlockChainFactories["Namecoin"] = namecoin.NewNamecoinRPC 56 BlockChainFactories["Monacoin"] = monacoin.NewMonacoinRPC 57 BlockChainFactories["Monacoin Testnet"] = monacoin.NewMonacoinRPC 58 BlockChainFactories["DigiByte"] = digibyte.NewDigiByteRPC 59 BlockChainFactories["Myriad"] = myriad.NewMyriadRPC 60 BlockChainFactories["Groestlcoin"] = grs.NewGroestlcoinRPC 61 BlockChainFactories["Groestlcoin Testnet"] = grs.NewGroestlcoinRPC 62 } 63 64 // GetCoinNameFromConfig gets coin name and coin shortcut from config file 65 func GetCoinNameFromConfig(configfile string) (string, string, string, error) { 66 data, err := ioutil.ReadFile(configfile) 67 if err != nil { 68 return "", "", "", errors.Annotatef(err, "Error reading file %v", configfile) 69 } 70 var cn struct { 71 CoinName string `json:"coin_name"` 72 CoinShortcut string `json:"coin_shortcut"` 73 CoinLabel string `json:"coin_label"` 74 } 75 err = json.Unmarshal(data, &cn) 76 if err != nil { 77 return "", "", "", errors.Annotatef(err, "Error parsing file %v", configfile) 78 } 79 return cn.CoinName, cn.CoinShortcut, cn.CoinLabel, nil 80 } 81 82 // NewBlockChain creates bchain.BlockChain of type defined by parameter coin 83 func NewBlockChain(coin string, configfile string, pushHandler func(bchain.NotificationType), metrics *common.Metrics) (bchain.BlockChain, error) { 84 data, err := ioutil.ReadFile(configfile) 85 if err != nil { 86 return nil, errors.Annotatef(err, "Error reading file %v", configfile) 87 } 88 var config json.RawMessage 89 err = json.Unmarshal(data, &config) 90 if err != nil { 91 return nil, errors.Annotatef(err, "Error parsing file %v", configfile) 92 } 93 bcf, ok := BlockChainFactories[coin] 94 if !ok { 95 return nil, errors.New(fmt.Sprint("Unsupported coin '", coin, "'. Must be one of ", reflect.ValueOf(BlockChainFactories).MapKeys())) 96 } 97 bc, err := bcf(config, pushHandler) 98 if err != nil { 99 return nil, err 100 } 101 err = bc.Initialize() 102 if err != nil { 103 return nil, err 104 } 105 return &blockChainWithMetrics{b: bc, m: metrics}, nil 106 } 107 108 type blockChainWithMetrics struct { 109 b bchain.BlockChain 110 m *common.Metrics 111 } 112 113 func (c *blockChainWithMetrics) observeRPCLatency(method string, start time.Time, err error) { 114 var e string 115 if err != nil { 116 e = err.Error() 117 } 118 c.m.RPCLatency.With(common.Labels{"method": method, "error": e}).Observe(float64(time.Since(start)) / 1e6) // in milliseconds 119 } 120 121 func (c *blockChainWithMetrics) Initialize() error { 122 return c.b.Initialize() 123 } 124 125 func (c *blockChainWithMetrics) Shutdown(ctx context.Context) error { 126 return c.b.Shutdown(ctx) 127 } 128 129 func (c *blockChainWithMetrics) IsTestnet() bool { 130 return c.b.IsTestnet() 131 } 132 133 func (c *blockChainWithMetrics) GetNetworkName() string { 134 return c.b.GetNetworkName() 135 } 136 137 func (c *blockChainWithMetrics) GetCoinName() string { 138 return c.b.GetCoinName() 139 } 140 141 func (c *blockChainWithMetrics) GetSubversion() string { 142 return c.b.GetSubversion() 143 } 144 145 func (c *blockChainWithMetrics) GetChainInfo() (v *bchain.ChainInfo, err error) { 146 defer func(s time.Time) { c.observeRPCLatency("GetChainInfo", s, err) }(time.Now()) 147 return c.b.GetChainInfo() 148 } 149 150 func (c *blockChainWithMetrics) GetBestBlockHash() (v string, err error) { 151 defer func(s time.Time) { c.observeRPCLatency("GetBestBlockHash", s, err) }(time.Now()) 152 return c.b.GetBestBlockHash() 153 } 154 155 func (c *blockChainWithMetrics) GetBestBlockHeight() (v uint32, err error) { 156 defer func(s time.Time) { c.observeRPCLatency("GetBestBlockHeight", s, err) }(time.Now()) 157 return c.b.GetBestBlockHeight() 158 } 159 160 func (c *blockChainWithMetrics) GetBlockHash(height uint32) (v string, err error) { 161 defer func(s time.Time) { c.observeRPCLatency("GetBlockHash", s, err) }(time.Now()) 162 return c.b.GetBlockHash(height) 163 } 164 165 func (c *blockChainWithMetrics) GetBlockHeader(hash string) (v *bchain.BlockHeader, err error) { 166 defer func(s time.Time) { c.observeRPCLatency("GetBlockHeader", s, err) }(time.Now()) 167 return c.b.GetBlockHeader(hash) 168 } 169 170 func (c *blockChainWithMetrics) GetBlock(hash string, height uint32) (v *bchain.Block, err error) { 171 defer func(s time.Time) { c.observeRPCLatency("GetBlock", s, err) }(time.Now()) 172 return c.b.GetBlock(hash, height) 173 } 174 175 func (c *blockChainWithMetrics) GetBlockInfo(hash string) (v *bchain.BlockInfo, err error) { 176 defer func(s time.Time) { c.observeRPCLatency("GetBlockInfo", s, err) }(time.Now()) 177 return c.b.GetBlockInfo(hash) 178 } 179 180 func (c *blockChainWithMetrics) GetMempool() (v []string, err error) { 181 defer func(s time.Time) { c.observeRPCLatency("GetMempool", s, err) }(time.Now()) 182 return c.b.GetMempool() 183 } 184 185 func (c *blockChainWithMetrics) GetTransaction(txid string) (v *bchain.Tx, err error) { 186 defer func(s time.Time) { c.observeRPCLatency("GetTransaction", s, err) }(time.Now()) 187 return c.b.GetTransaction(txid) 188 } 189 190 func (c *blockChainWithMetrics) GetTransactionSpecific(txid string) (v json.RawMessage, err error) { 191 defer func(s time.Time) { c.observeRPCLatency("GetTransactionSpecific", s, err) }(time.Now()) 192 return c.b.GetTransactionSpecific(txid) 193 } 194 195 func (c *blockChainWithMetrics) GetTransactionForMempool(txid string) (v *bchain.Tx, err error) { 196 defer func(s time.Time) { c.observeRPCLatency("GetTransactionForMempool", s, err) }(time.Now()) 197 return c.b.GetTransactionForMempool(txid) 198 } 199 200 func (c *blockChainWithMetrics) EstimateSmartFee(blocks int, conservative bool) (v big.Int, err error) { 201 defer func(s time.Time) { c.observeRPCLatency("EstimateSmartFee", s, err) }(time.Now()) 202 return c.b.EstimateSmartFee(blocks, conservative) 203 } 204 205 func (c *blockChainWithMetrics) EstimateFee(blocks int) (v big.Int, err error) { 206 defer func(s time.Time) { c.observeRPCLatency("EstimateFee", s, err) }(time.Now()) 207 return c.b.EstimateFee(blocks) 208 } 209 210 func (c *blockChainWithMetrics) SendRawTransaction(tx string) (v string, err error) { 211 defer func(s time.Time) { c.observeRPCLatency("SendRawTransaction", s, err) }(time.Now()) 212 return c.b.SendRawTransaction(tx) 213 } 214 215 func (c *blockChainWithMetrics) ResyncMempool(onNewTxAddr bchain.OnNewTxAddrFunc) (count int, err error) { 216 defer func(s time.Time) { c.observeRPCLatency("ResyncMempool", s, err) }(time.Now()) 217 count, err = c.b.ResyncMempool(onNewTxAddr) 218 if err == nil { 219 c.m.MempoolSize.Set(float64(count)) 220 } 221 return count, err 222 } 223 224 func (c *blockChainWithMetrics) GetMempoolTransactions(address string) (v []string, err error) { 225 defer func(s time.Time) { c.observeRPCLatency("GetMempoolTransactions", s, err) }(time.Now()) 226 return c.b.GetMempoolTransactions(address) 227 } 228 229 func (c *blockChainWithMetrics) GetMempoolTransactionsForAddrDesc(addrDesc bchain.AddressDescriptor) (v []string, err error) { 230 defer func(s time.Time) { c.observeRPCLatency("GetMempoolTransactionsForAddrDesc", s, err) }(time.Now()) 231 return c.b.GetMempoolTransactionsForAddrDesc(addrDesc) 232 } 233 234 func (c *blockChainWithMetrics) GetMempoolEntry(txid string) (v *bchain.MempoolEntry, err error) { 235 defer func(s time.Time) { c.observeRPCLatency("GetMempoolEntry", s, err) }(time.Now()) 236 return c.b.GetMempoolEntry(txid) 237 } 238 239 func (c *blockChainWithMetrics) GetChainParser() bchain.BlockChainParser { 240 return c.b.GetChainParser() 241 }