github.com/trezor/blockbook@v0.4.1-0.20240328132726-e9a08582ee2c/bchain/coins/litecoin/litecoinparser.go (about)

     1  package litecoin
     2  
     3  import (
     4  	"encoding/json"
     5  
     6  	"github.com/golang/glog"
     7  	"github.com/martinboehm/btcd/wire"
     8  	"github.com/martinboehm/btcutil/chaincfg"
     9  	"github.com/trezor/blockbook/bchain"
    10  	"github.com/trezor/blockbook/bchain/coins/btc"
    11  )
    12  
    13  // magic numbers
    14  const (
    15  	MainnetMagic wire.BitcoinNet = 0xdbb6c0fb
    16  	TestnetMagic wire.BitcoinNet = 0xf1c8d2fd
    17  	RegtestMagic wire.BitcoinNet = 0xdab5bffa
    18  )
    19  
    20  // chain parameters
    21  var (
    22  	MainNetParams chaincfg.Params
    23  	TestNetParams chaincfg.Params
    24  )
    25  
    26  func init() {
    27  	MainNetParams = chaincfg.MainNetParams
    28  	MainNetParams.Net = MainnetMagic
    29  	MainNetParams.PubKeyHashAddrID = []byte{48}
    30  	MainNetParams.ScriptHashAddrID = []byte{50}
    31  	MainNetParams.Bech32HRPSegwit = "ltc"
    32  
    33  	TestNetParams = chaincfg.TestNet3Params
    34  	TestNetParams.Net = TestnetMagic
    35  	TestNetParams.PubKeyHashAddrID = []byte{111}
    36  	TestNetParams.ScriptHashAddrID = []byte{58}
    37  	TestNetParams.Bech32HRPSegwit = "tltc"
    38  }
    39  
    40  // LitecoinParser handle
    41  type LitecoinParser struct {
    42  	*btc.BitcoinLikeParser
    43  	baseparser *bchain.BaseParser
    44  }
    45  
    46  // NewLitecoinParser returns new LitecoinParser instance
    47  func NewLitecoinParser(params *chaincfg.Params, c *btc.Configuration) *LitecoinParser {
    48  	p := &LitecoinParser{
    49  		BitcoinLikeParser: btc.NewBitcoinLikeParser(params, c),
    50  		baseparser:        &bchain.BaseParser{},
    51  	}
    52  	p.VSizeSupport = true
    53  	return p
    54  }
    55  
    56  // GetChainParams contains network parameters for the main Litecoin network,
    57  // and the test Litecoin network
    58  func GetChainParams(chain string) *chaincfg.Params {
    59  	// register bitcoin parameters in addition to litecoin parameters
    60  	// litecoin has dual standard of addresses and we want to be able to
    61  	// parse both standards
    62  	if !chaincfg.IsRegistered(&chaincfg.MainNetParams) {
    63  		chaincfg.RegisterBitcoinParams()
    64  	}
    65  	if !chaincfg.IsRegistered(&MainNetParams) {
    66  		err := chaincfg.Register(&MainNetParams)
    67  		if err == nil {
    68  			err = chaincfg.Register(&TestNetParams)
    69  		}
    70  		if err != nil {
    71  			panic(err)
    72  		}
    73  	}
    74  	switch chain {
    75  	case "test":
    76  		return &TestNetParams
    77  	default:
    78  		return &MainNetParams
    79  	}
    80  }
    81  
    82  // fallbackTx is used to handle situation when Litecoin mainnet returns
    83  // for certain transactions Version 4294967295 instead of -1, which causes json unmarshal error
    84  type fallbackTx struct {
    85  	Hex         string        `json:"hex"`
    86  	Txid        string        `json:"txid"`
    87  	Version     uint32        `json:"version"`
    88  	LockTime    uint32        `json:"locktime"`
    89  	Vin         []bchain.Vin  `json:"vin"`
    90  	Vout        []bchain.Vout `json:"vout"`
    91  	BlockHeight uint32        `json:"blockHeight,omitempty"`
    92  	// BlockHash     string `json:"blockhash,omitempty"`
    93  	Confirmations uint32 `json:"confirmations,omitempty"`
    94  	Time          int64  `json:"time,omitempty"`
    95  	Blocktime     int64  `json:"blocktime,omitempty"`
    96  }
    97  
    98  // ParseTxFromJson parses JSON message containing transaction and returns Tx struct
    99  func (p *LitecoinParser) ParseTxFromJson(msg json.RawMessage) (*bchain.Tx, error) {
   100  	var tx bchain.Tx
   101  	err := json.Unmarshal(msg, &tx)
   102  	if err != nil {
   103  		var fTx fallbackTx
   104  		fErr := json.Unmarshal(msg, &fTx)
   105  		// log warning with Txid possibly parsed using fallbackTx
   106  		glog.Warningf("ParseTxFromJson txid %s to bchain.Tx error %v, using fallback method", fTx.Txid, err)
   107  		if fErr != nil {
   108  			return nil, fErr
   109  		}
   110  		tx.Hex = fTx.Hex
   111  		tx.Txid = fTx.Txid
   112  		tx.Version = int32(fTx.Version)
   113  		tx.LockTime = fTx.LockTime
   114  		tx.Vin = fTx.Vin
   115  		tx.Vout = fTx.Vout
   116  		tx.BlockHeight = fTx.BlockHeight
   117  		tx.Confirmations = fTx.Confirmations
   118  		tx.Time = fTx.Time
   119  		tx.Blocktime = fTx.Blocktime
   120  	}
   121  
   122  	for i := range tx.Vout {
   123  		vout := &tx.Vout[i]
   124  		// convert vout.JsonValue to big.Int and clear it, it is only temporary value used for unmarshal
   125  		vout.ValueSat, err = p.AmountToBigInt(vout.JsonValue)
   126  		if err != nil {
   127  			return nil, err
   128  		}
   129  		vout.JsonValue = ""
   130  	}
   131  
   132  	return &tx, nil
   133  }
   134  
   135  // PackTx packs transaction to byte array using protobuf
   136  func (p *LitecoinParser) PackTx(tx *bchain.Tx, height uint32, blockTime int64) ([]byte, error) {
   137  	return p.baseparser.PackTx(tx, height, blockTime)
   138  }
   139  
   140  // UnpackTx unpacks transaction from protobuf byte array
   141  func (p *LitecoinParser) UnpackTx(buf []byte) (*bchain.Tx, uint32, error) {
   142  	return p.baseparser.UnpackTx(buf)
   143  }