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