github.com/aychain/blockbook@v0.1.1-0.20181121092459-6d1fc7e07c5b/bchain/coins/grs/grsrpc.go (about)

     1  package grs
     2  
     3  import (
     4  	"blockbook/bchain"
     5  	"blockbook/bchain/coins/btc"
     6  	"encoding/json"
     7  
     8  	"github.com/golang/glog"
     9  	"github.com/juju/errors"
    10  )
    11  
    12  type GroestlcoinRPC struct {
    13  	*btc.BitcoinRPC
    14  }
    15  
    16  func NewGroestlcoinRPC(config json.RawMessage, pushHandler func(bchain.NotificationType)) (bchain.BlockChain, error) {
    17  	b, err := btc.NewBitcoinRPC(config, pushHandler)
    18  	if err != nil {
    19  		return nil, err
    20  	}
    21  	g := &GroestlcoinRPC{
    22  		BitcoinRPC: b.(*btc.BitcoinRPC),
    23  	}
    24  	g.RPCMarshaler = btc.JSONMarshalerV1{}
    25  	return g, nil
    26  }
    27  
    28  // Initialize initializes GroestlcoinRPC instance.
    29  func (g *GroestlcoinRPC) Initialize() error {
    30  	chainName, err := g.GetChainInfoAndInitializeMempool(g)
    31  	if err != nil {
    32  		return err
    33  	}
    34  
    35  	params := GetChainParams(chainName)
    36  
    37  	g.Parser = NewGroestlcoinParser(params, g.ChainConfig)
    38  
    39  	// parameters for getInfo request
    40  	if params.Net == MainnetMagic {
    41  		g.Testnet = false
    42  		g.Network = "livenet"
    43  	} else {
    44  		g.Testnet = true
    45  		g.Network = "testnet"
    46  	}
    47  
    48  	glog.Info("rpc: block chain ", params.Name)
    49  
    50  	return nil
    51  }
    52  
    53  // GetBlock returns block with given hash.
    54  func (g *GroestlcoinRPC) GetBlock(hash string, height uint32) (*bchain.Block, error) {
    55  	var err error
    56  	if hash == "" && height > 0 {
    57  		hash, err = g.GetBlockHash(height)
    58  		if err != nil {
    59  			return nil, err
    60  		}
    61  	}
    62  
    63  	glog.V(1).Info("rpc: getblock (verbosity=1) ", hash)
    64  
    65  	res := btc.ResGetBlockThin{}
    66  	req := btc.CmdGetBlock{Method: "getblock"}
    67  	req.Params.BlockHash = hash
    68  	req.Params.Verbosity = 1
    69  	err = g.Call(&req, &res)
    70  
    71  	if err != nil {
    72  		return nil, errors.Annotatef(err, "hash %v", hash)
    73  	}
    74  	if res.Error != nil {
    75  		return nil, errors.Annotatef(res.Error, "hash %v", hash)
    76  	}
    77  
    78  	txs := make([]bchain.Tx, 0, len(res.Result.Txids))
    79  	for _, txid := range res.Result.Txids {
    80  		tx, err := g.GetTransaction(txid)
    81  		if err != nil {
    82  			if isInvalidTx(err) {
    83  				glog.Errorf("rpc: getblock: skipping transanction in block %s due error: %s", hash, err)
    84  				continue
    85  			}
    86  			return nil, err
    87  		}
    88  		txs = append(txs, *tx)
    89  	}
    90  	block := &bchain.Block{
    91  		BlockHeader: res.Result.BlockHeader,
    92  		Txs:         txs,
    93  	}
    94  	return block, nil
    95  }
    96  
    97  func isInvalidTx(err error) bool {
    98  	switch e1 := err.(type) {
    99  	case *errors.Err:
   100  		switch e2 := e1.Cause().(type) {
   101  		case *bchain.RPCError:
   102  			if e2.Code == -5 { // "No information available about transaction"
   103  				return true
   104  			}
   105  		}
   106  	}
   107  
   108  	return false
   109  }
   110  
   111  // GetTransactionForMempool returns a transaction by the transaction ID.
   112  // It could be optimized for mempool, i.e. without block time and confirmations
   113  func (g *GroestlcoinRPC) GetTransactionForMempool(txid string) (*bchain.Tx, error) {
   114  	return g.GetTransaction(txid)
   115  }