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

     1  package btc
     2  
     3  import (
     4  	"encoding/json"
     5  	"math/big"
     6  
     7  	"github.com/martinboehm/btcutil/chaincfg"
     8  	"github.com/trezor/blockbook/bchain"
     9  	"github.com/trezor/blockbook/common"
    10  )
    11  
    12  // BitcoinParser handle
    13  type BitcoinParser struct {
    14  	*BitcoinLikeParser
    15  }
    16  
    17  // NewBitcoinParser returns new BitcoinParser instance
    18  func NewBitcoinParser(params *chaincfg.Params, c *Configuration) *BitcoinParser {
    19  	p := &BitcoinParser{
    20  		BitcoinLikeParser: NewBitcoinLikeParser(params, c),
    21  	}
    22  	p.VSizeSupport = true
    23  	return p
    24  }
    25  
    26  // GetChainParams contains network parameters for the main Bitcoin network,
    27  // the regression test Bitcoin network, the test Bitcoin network and
    28  // the simulation test Bitcoin network, in this order
    29  func GetChainParams(chain string) *chaincfg.Params {
    30  	if !chaincfg.IsRegistered(&chaincfg.MainNetParams) {
    31  		chaincfg.RegisterBitcoinParams()
    32  	}
    33  	switch chain {
    34  	case "test":
    35  		return &chaincfg.TestNet3Params
    36  	case "regtest":
    37  		return &chaincfg.RegressionNetParams
    38  	case "signet":
    39  		return &chaincfg.SigNetParams
    40  	}
    41  	return &chaincfg.MainNetParams
    42  }
    43  
    44  // ScriptPubKey contains data about output script
    45  type ScriptPubKey struct {
    46  	// Asm       string   `json:"asm"`
    47  	Hex string `json:"hex,omitempty"`
    48  	// Type      string   `json:"type"`
    49  	Addresses []string `json:"addresses"` // removed from Bitcoind 22.0.0
    50  	Address   string   `json:"address"`   // used in Bitcoind 22.0.0
    51  }
    52  
    53  // Vout contains data about tx output
    54  type Vout struct {
    55  	ValueSat     big.Int
    56  	JsonValue    common.JSONNumber `json:"value"`
    57  	N            uint32            `json:"n"`
    58  	ScriptPubKey ScriptPubKey      `json:"scriptPubKey"`
    59  }
    60  
    61  // Tx is blockchain transaction
    62  // unnecessary fields are commented out to avoid overhead
    63  type Tx struct {
    64  	Hex         string       `json:"hex"`
    65  	Txid        string       `json:"txid"`
    66  	Version     int32        `json:"version"`
    67  	LockTime    uint32       `json:"locktime"`
    68  	VSize       int64        `json:"vsize,omitempty"`
    69  	Vin         []bchain.Vin `json:"vin"`
    70  	Vout        []Vout       `json:"vout"`
    71  	BlockHeight uint32       `json:"blockHeight,omitempty"`
    72  	// BlockHash     string `json:"blockhash,omitempty"`
    73  	Confirmations    uint32      `json:"confirmations,omitempty"`
    74  	Time             int64       `json:"time,omitempty"`
    75  	Blocktime        int64       `json:"blocktime,omitempty"`
    76  	CoinSpecificData interface{} `json:"-"`
    77  }
    78  
    79  // ParseTxFromJson parses JSON message containing transaction and returns Tx struct
    80  // Bitcoind version 22.0.0 removed ScriptPubKey.Addresses from the API and replaced it by a single Address
    81  func (p *BitcoinParser) ParseTxFromJson(msg json.RawMessage) (*bchain.Tx, error) {
    82  	var bitcoinTx Tx
    83  	var tx bchain.Tx
    84  	err := json.Unmarshal(msg, &bitcoinTx)
    85  	if err != nil {
    86  		return nil, err
    87  	}
    88  
    89  	// it is necessary to copy bitcoinTx to Tx to make it compatible
    90  	tx.Hex = bitcoinTx.Hex
    91  	tx.Txid = bitcoinTx.Txid
    92  	tx.Version = bitcoinTx.Version
    93  	tx.LockTime = bitcoinTx.LockTime
    94  	tx.VSize = bitcoinTx.VSize
    95  	tx.Vin = bitcoinTx.Vin
    96  	tx.BlockHeight = bitcoinTx.BlockHeight
    97  	tx.Confirmations = bitcoinTx.Confirmations
    98  	tx.Time = bitcoinTx.Time
    99  	tx.Blocktime = bitcoinTx.Blocktime
   100  	tx.CoinSpecificData = bitcoinTx.CoinSpecificData
   101  	tx.Vout = make([]bchain.Vout, len(bitcoinTx.Vout))
   102  
   103  	for i := range bitcoinTx.Vout {
   104  		bitcoinVout := &bitcoinTx.Vout[i]
   105  		vout := &tx.Vout[i]
   106  		// convert vout.JsonValue to big.Int and clear it, it is only temporary value used for unmarshal
   107  		vout.ValueSat, err = p.AmountToBigInt(bitcoinVout.JsonValue)
   108  		if err != nil {
   109  			return nil, err
   110  		}
   111  		vout.N = bitcoinVout.N
   112  		vout.ScriptPubKey.Hex = bitcoinVout.ScriptPubKey.Hex
   113  		// convert single Address to Addresses if Addresses are empty
   114  		if len(bitcoinVout.ScriptPubKey.Addresses) == 0 {
   115  			vout.ScriptPubKey.Addresses = []string{bitcoinVout.ScriptPubKey.Address}
   116  		} else {
   117  			vout.ScriptPubKey.Addresses = bitcoinVout.ScriptPubKey.Addresses
   118  		}
   119  	}
   120  
   121  	return &tx, nil
   122  }