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