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  }