github.com/trezor/blockbook@v0.4.1-0.20240328132726-e9a08582ee2c/bchain/coins/qtum/qtumparser.go (about) 1 package qtum 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "io" 7 8 "github.com/martinboehm/btcd/wire" 9 "github.com/martinboehm/btcutil/chaincfg" 10 "github.com/trezor/blockbook/bchain" 11 "github.com/trezor/blockbook/bchain/coins/btc" 12 "github.com/trezor/blockbook/bchain/coins/utils" 13 ) 14 15 // magic numbers 16 const ( 17 MainnetMagic wire.BitcoinNet = 0xf1cfa6d3 18 TestnetMagic wire.BitcoinNet = 0x0d221506 19 ) 20 21 // chain parameters 22 var ( 23 MainNetParams chaincfg.Params 24 TestNetParams chaincfg.Params 25 ) 26 27 func init() { 28 MainNetParams = chaincfg.MainNetParams 29 MainNetParams.Net = MainnetMagic 30 MainNetParams.PubKeyHashAddrID = []byte{58} 31 MainNetParams.ScriptHashAddrID = []byte{50} 32 MainNetParams.Bech32HRPSegwit = "qc" 33 34 TestNetParams = chaincfg.TestNet3Params 35 TestNetParams.Net = TestnetMagic 36 TestNetParams.PubKeyHashAddrID = []byte{120} 37 TestNetParams.ScriptHashAddrID = []byte{110} 38 TestNetParams.Bech32HRPSegwit = "tq" 39 } 40 41 // QtumParser handle 42 type QtumParser struct { 43 *btc.BitcoinParser 44 } 45 46 // NewQtumParser returns new DashParser instance 47 func NewQtumParser(params *chaincfg.Params, c *btc.Configuration) *QtumParser { 48 p := &QtumParser{ 49 BitcoinParser: btc.NewBitcoinParser(params, c), 50 } 51 p.VSizeSupport = false 52 return p 53 } 54 55 // GetChainParams contains network parameters for the main Qtum network, 56 // the regression test Qtum network, the test Qtum network and 57 // the simulation test Qtum network, in this order 58 func GetChainParams(chain string) *chaincfg.Params { 59 if !chaincfg.IsRegistered(&MainNetParams) { 60 err := chaincfg.Register(&MainNetParams) 61 if err == nil { 62 err = chaincfg.Register(&TestNetParams) 63 } 64 if err != nil { 65 panic(err) 66 } 67 } 68 switch chain { 69 case "test": 70 return &TestNetParams 71 default: 72 return &MainNetParams 73 } 74 } 75 76 func parseBlockHeader(r io.Reader) (*wire.BlockHeader, error) { 77 h := &wire.BlockHeader{} 78 err := h.Deserialize(r) 79 if err != nil { 80 return nil, err 81 } 82 83 // hash_state_root 32 84 // hash_utxo_root 32 85 // hash_prevout_stake 32 86 // hash_prevout_n 4 87 buf := make([]byte, 100) 88 _, err = io.ReadFull(r, buf) 89 if err != nil { 90 return nil, err 91 } 92 93 sigLength, err := wire.ReadVarInt(r, 0) 94 if err != nil { 95 return nil, err 96 } 97 sigBuf := make([]byte, sigLength) 98 _, err = io.ReadFull(r, sigBuf) 99 if err != nil { 100 return nil, err 101 } 102 103 return h, err 104 } 105 106 func (p *QtumParser) ParseBlock(b []byte) (*bchain.Block, error) { 107 r := bytes.NewReader(b) 108 w := wire.MsgBlock{} 109 110 h, err := parseBlockHeader(r) 111 if err != nil { 112 return nil, err 113 } 114 115 err = utils.DecodeTransactions(r, 0, wire.WitnessEncoding, &w) 116 if err != nil { 117 return nil, err 118 } 119 120 txs := make([]bchain.Tx, len(w.Transactions)) 121 for ti, t := range w.Transactions { 122 txs[ti] = p.TxFromMsgTx(t, false) 123 } 124 125 return &bchain.Block{ 126 BlockHeader: bchain.BlockHeader{ 127 Size: len(b), 128 Time: h.Timestamp.Unix(), 129 }, 130 Txs: txs, 131 }, nil 132 } 133 134 // ParseTxFromJson parses JSON message containing transaction and returns Tx struct 135 func (p *QtumParser) ParseTxFromJson(msg json.RawMessage) (*bchain.Tx, error) { 136 var tx bchain.Tx 137 err := json.Unmarshal(msg, &tx) 138 if err != nil { 139 return nil, err 140 } 141 142 for i := range tx.Vout { 143 vout := &tx.Vout[i] 144 // convert vout.JsonValue to big.Int and clear it, it is only temporary value used for unmarshal 145 vout.ValueSat, err = p.AmountToBigInt(vout.JsonValue) 146 if err != nil { 147 return nil, err 148 } 149 vout.JsonValue = "" 150 151 if vout.ScriptPubKey.Addresses == nil { 152 vout.ScriptPubKey.Addresses = []string{} 153 } 154 } 155 156 return &tx, nil 157 }