package qtum import ( "bytes" "encoding/json" "io" "github.com/martinboehm/btcd/wire" "github.com/martinboehm/btcutil/chaincfg" "github.com/trezor/blockbook/bchain" "github.com/trezor/blockbook/bchain/coins/btc" "github.com/trezor/blockbook/bchain/coins/utils" ) // magic numbers const ( MainnetMagic wire.BitcoinNet = 0xf1cfa6d3 TestnetMagic wire.BitcoinNet = 0x0d221506 ) // chain parameters var ( MainNetParams chaincfg.Params TestNetParams chaincfg.Params ) func init() { MainNetParams = chaincfg.MainNetParams MainNetParams.Net = MainnetMagic MainNetParams.PubKeyHashAddrID = []byte{58} MainNetParams.ScriptHashAddrID = []byte{50} MainNetParams.Bech32HRPSegwit = "qc" TestNetParams = chaincfg.TestNet3Params TestNetParams.Net = TestnetMagic TestNetParams.PubKeyHashAddrID = []byte{120} TestNetParams.ScriptHashAddrID = []byte{110} TestNetParams.Bech32HRPSegwit = "tq" } // QtumParser handle type QtumParser struct { *btc.BitcoinParser } // NewQtumParser returns new DashParser instance func NewQtumParser(params *chaincfg.Params, c *btc.Configuration) *QtumParser { return &QtumParser{ BitcoinParser: btc.NewBitcoinParser(params, c), } } // GetChainParams contains network parameters for the main Qtum network, // the regression test Qtum network, the test Qtum network and // the simulation test Qtum network, in this order func GetChainParams(chain string) *chaincfg.Params { if !chaincfg.IsRegistered(&MainNetParams) { err := chaincfg.Register(&MainNetParams) if err == nil { err = chaincfg.Register(&TestNetParams) } if err != nil { panic(err) } } switch chain { case "test": return &TestNetParams default: return &MainNetParams } } func parseBlockHeader(r io.Reader) (*wire.BlockHeader, error) { h := &wire.BlockHeader{} err := h.Deserialize(r) if err != nil { return nil, err } // hash_state_root 32 // hash_utxo_root 32 // hash_prevout_stake 32 // hash_prevout_n 4 buf := make([]byte, 100) _, err = io.ReadFull(r, buf) if err != nil { return nil, err } sigLength, err := wire.ReadVarInt(r, 0) if err != nil { return nil, err } sigBuf := make([]byte, sigLength) _, err = io.ReadFull(r, sigBuf) if err != nil { return nil, err } return h, err } func (p *QtumParser) ParseBlock(b []byte) (*bchain.Block, error) { r := bytes.NewReader(b) w := wire.MsgBlock{} h, err := parseBlockHeader(r) if err != nil { return nil, err } err = utils.DecodeTransactions(r, 0, wire.WitnessEncoding, &w) if err != nil { return nil, err } txs := make([]bchain.Tx, len(w.Transactions)) for ti, t := range w.Transactions { txs[ti] = p.TxFromMsgTx(t, false) } return &bchain.Block{ BlockHeader: bchain.BlockHeader{ Size: len(b), Time: h.Timestamp.Unix(), }, Txs: txs, }, nil } // ParseTxFromJson parses JSON message containing transaction and returns Tx struct func (p *QtumParser) ParseTxFromJson(msg json.RawMessage) (*bchain.Tx, error) { var tx bchain.Tx err := json.Unmarshal(msg, &tx) if err != nil { return nil, err } for i := range tx.Vout { vout := &tx.Vout[i] // convert vout.JsonValue to big.Int and clear it, it is only temporary value used for unmarshal vout.ValueSat, err = p.AmountToBigInt(vout.JsonValue) if err != nil { return nil, err } vout.JsonValue = "" if vout.ScriptPubKey.Addresses == nil { vout.ScriptPubKey.Addresses = []string{} } } return &tx, nil }