github.com/cerberus-wallet/blockbook@v0.3.2/bchain/coins/btg/bgoldparser.go (about)

     1  package btg
     2  
     3  import (
     4  	"blockbook/bchain"
     5  	"blockbook/bchain/coins/btc"
     6  	"blockbook/bchain/coins/utils"
     7  	"bytes"
     8  	"encoding/binary"
     9  	"io"
    10  
    11  	"github.com/martinboehm/btcd/chaincfg/chainhash"
    12  	"github.com/martinboehm/btcd/wire"
    13  	"github.com/martinboehm/btcutil/chaincfg"
    14  )
    15  
    16  const (
    17  	// MainnetMagic is mainnet network constant
    18  	MainnetMagic wire.BitcoinNet = 0x446d47e1
    19  	// TestnetMagic is testnet network constant
    20  	TestnetMagic wire.BitcoinNet = 0x456e48e2
    21  )
    22  
    23  var (
    24  	// MainNetParams are parser parameters for mainnet
    25  	MainNetParams chaincfg.Params
    26  	// TestNetParams are parser parameters for testnet
    27  	TestNetParams chaincfg.Params
    28  )
    29  
    30  func init() {
    31  	MainNetParams = chaincfg.MainNetParams
    32  	MainNetParams.Net = MainnetMagic
    33  
    34  	// Address encoding magics
    35  	MainNetParams.PubKeyHashAddrID = []byte{38} // base58 prefix: G
    36  	MainNetParams.ScriptHashAddrID = []byte{23} // base58 prefix: A
    37  
    38  	TestNetParams = chaincfg.TestNet3Params
    39  	TestNetParams.Net = TestnetMagic
    40  
    41  	// Human-readable part for Bech32 encoded segwit addresses, as defined in
    42  	// BIP 173.
    43  	// see https://github.com/satoshilabs/slips/blob/master/slip-0173.md
    44  	MainNetParams.Bech32HRPSegwit = "btg"
    45  	TestNetParams.Bech32HRPSegwit = "tbtg"
    46  }
    47  
    48  // BGoldParser handle
    49  type BGoldParser struct {
    50  	*btc.BitcoinParser
    51  }
    52  
    53  // NewBGoldParser returns new BGoldParser instance
    54  func NewBGoldParser(params *chaincfg.Params, c *btc.Configuration) *BGoldParser {
    55  	return &BGoldParser{BitcoinParser: btc.NewBitcoinParser(params, c)}
    56  }
    57  
    58  // GetChainParams contains network parameters for the main Bitcoin Cash network,
    59  // the regression test Bitcoin Cash network, the test Bitcoin Cash network and
    60  // the simulation test Bitcoin Cash network, in this order
    61  func GetChainParams(chain string) *chaincfg.Params {
    62  	if !chaincfg.IsRegistered(&MainNetParams) {
    63  		err := chaincfg.Register(&MainNetParams)
    64  		if err == nil {
    65  			err = chaincfg.Register(&TestNetParams)
    66  		}
    67  		if err != nil {
    68  			panic(err)
    69  		}
    70  	}
    71  	switch chain {
    72  	case "test":
    73  		return &TestNetParams
    74  	case "regtest":
    75  		return &chaincfg.RegressionNetParams
    76  	default:
    77  		return &MainNetParams
    78  	}
    79  }
    80  
    81  // headerFixedLength is the length of fixed fields of a block (i.e. without solution)
    82  // see https://github.com/BTCGPU/BTCGPU/wiki/Technical-Spec#block-header
    83  const headerFixedLength = 44 + (chainhash.HashSize * 3)
    84  const timestampOffset = 100
    85  const timestampLength = 4
    86  
    87  // ParseBlock parses raw block to our Block struct
    88  func (p *BGoldParser) ParseBlock(b []byte) (*bchain.Block, error) {
    89  	r := bytes.NewReader(b)
    90  	time, err := getTimestampAndSkipHeader(r, 0)
    91  	if err != nil {
    92  		return nil, err
    93  	}
    94  
    95  	w := wire.MsgBlock{}
    96  	err = utils.DecodeTransactions(r, 0, wire.WitnessEncoding, &w)
    97  	if err != nil {
    98  		return nil, err
    99  	}
   100  
   101  	txs := make([]bchain.Tx, len(w.Transactions))
   102  	for ti, t := range w.Transactions {
   103  		txs[ti] = p.TxFromMsgTx(t, false)
   104  	}
   105  
   106  	return &bchain.Block{
   107  		BlockHeader: bchain.BlockHeader{
   108  			Size: len(b),
   109  			Time: time,
   110  		},
   111  		Txs: txs,
   112  	}, nil
   113  }
   114  
   115  func getTimestampAndSkipHeader(r io.ReadSeeker, pver uint32) (int64, error) {
   116  	_, err := r.Seek(timestampOffset, io.SeekStart)
   117  	if err != nil {
   118  		return 0, err
   119  	}
   120  
   121  	buf := make([]byte, timestampLength)
   122  	if _, err = io.ReadFull(r, buf); err != nil {
   123  		return 0, err
   124  	}
   125  	time := binary.LittleEndian.Uint32(buf)
   126  
   127  	_, err = r.Seek(headerFixedLength-timestampOffset-timestampLength, io.SeekCurrent)
   128  	if err != nil {
   129  		return 0, err
   130  	}
   131  
   132  	size, err := wire.ReadVarInt(r, pver)
   133  	if err != nil {
   134  		return 0, err
   135  	}
   136  
   137  	_, err = r.Seek(int64(size), io.SeekCurrent)
   138  	if err != nil {
   139  		return 0, err
   140  	}
   141  
   142  	return int64(time), nil
   143  }