github.com/bchainhub/blockbook@v0.3.2/bchain/coins/divi/diviparser.go (about) 1 package divi 2 3 import ( 4 "blockbook/bchain" 5 "blockbook/bchain/coins/btc" 6 "blockbook/bchain/coins/utils" 7 "bytes" 8 "io" 9 10 "encoding/hex" 11 "encoding/json" 12 13 "math/big" 14 15 "github.com/juju/errors" 16 "github.com/martinboehm/btcd/wire" 17 "github.com/martinboehm/btcutil/chaincfg" 18 ) 19 20 const ( 21 // MainnetMagic = "network messages so the messages can be identified to belong to a specific coin" 22 // Source https://github.com/DiviProject/Divi/blob/master0/divi/src/chainparams.cpp#L128-L136 23 MainnetMagic wire.BitcoinNet = 0x8f8da0df 24 ) 25 26 var ( 27 // MainNetParams = ??? 28 MainNetParams chaincfg.Params 29 ) 30 31 func init() { 32 // DIVI mainnet Address encoding magics 33 MainNetParams = chaincfg.MainNetParams 34 MainNetParams.Net = MainnetMagic 35 MainNetParams.PubKeyHashAddrID = []byte{30} // starting with 'D' 36 MainNetParams.ScriptHashAddrID = []byte{13} 37 MainNetParams.PrivateKeyID = []byte{212} 38 } 39 40 // DivicoinParser handle 41 type DivicoinParser struct { 42 *btc.BitcoinParser 43 baseparser *bchain.BaseParser 44 BitcoinOutputScriptToAddressesFunc btc.OutputScriptToAddressesFunc 45 } 46 47 // NewDiviParser returns new DivicoinParser instance 48 func NewDiviParser(params *chaincfg.Params, c *btc.Configuration) *DivicoinParser { 49 p := &DivicoinParser{ 50 BitcoinParser: btc.NewBitcoinParser(params, c), 51 baseparser: &bchain.BaseParser{}, 52 } 53 p.BitcoinOutputScriptToAddressesFunc = p.OutputScriptToAddressesFunc 54 p.OutputScriptToAddressesFunc = p.outputScriptToAddresses 55 return p 56 } 57 58 // GetChainParams contains network parameters for the main Divi network 59 func GetChainParams(chain string) *chaincfg.Params { 60 if !chaincfg.IsRegistered(&MainNetParams) { 61 err := chaincfg.Register(&MainNetParams) 62 /*if err == nil { 63 err = chaincfg.Register(&TestNetParams) 64 }*/ 65 if err != nil { 66 panic(err) 67 } 68 } /* 69 switch chain { 70 case "test": 71 return &TestNetParams 72 default: 73 */return &MainNetParams 74 //} 75 } 76 77 // ParseBlock parses raw block to our Block struct 78 func (p *DivicoinParser) ParseBlock(b []byte) (*bchain.Block, error) { 79 r := bytes.NewReader(b) 80 w := wire.MsgBlock{} 81 h := wire.BlockHeader{} 82 err := h.Deserialize(r) 83 if err != nil { 84 return nil, errors.Annotatef(err, "Deserialize") 85 } 86 87 if h.Version > 3 { 88 // Skip past AccumulatorCheckpoint which was added in pivx block version 4 89 r.Seek(32, io.SeekCurrent) 90 } 91 92 err = utils.DecodeTransactions(r, 0, wire.WitnessEncoding, &w) 93 if err != nil { 94 return nil, errors.Annotatef(err, "DecodeTransactions") 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: h.Timestamp.Unix(), 106 }, 107 Txs: txs, 108 }, nil 109 } 110 111 // PackTx packs transaction to byte array using protobuf 112 func (p *DivicoinParser) PackTx(tx *bchain.Tx, height uint32, blockTime int64) ([]byte, error) { 113 return p.baseparser.PackTx(tx, height, blockTime) 114 } 115 116 // UnpackTx unpacks transaction from protobuf byte array 117 func (p *DivicoinParser) UnpackTx(buf []byte) (*bchain.Tx, uint32, error) { 118 return p.baseparser.UnpackTx(buf) 119 } 120 121 // ParseTx parses byte array containing transaction and returns Tx struct 122 func (p *DivicoinParser) ParseTx(b []byte) (*bchain.Tx, error) { 123 t := wire.MsgTx{} 124 r := bytes.NewReader(b) 125 if err := t.Deserialize(r); err != nil { 126 return nil, err 127 } 128 tx := p.TxFromMsgTx(&t, true) 129 tx.Hex = hex.EncodeToString(b) 130 return &tx, nil 131 } 132 133 // TxFromMsgTx parses tx and adds handling for OP_ZEROCOINSPEND inputs 134 func (p *DivicoinParser) TxFromMsgTx(t *wire.MsgTx, parseAddresses bool) bchain.Tx { 135 vin := make([]bchain.Vin, len(t.TxIn)) 136 for i, in := range t.TxIn { 137 s := bchain.ScriptSig{ 138 Hex: hex.EncodeToString(in.SignatureScript), 139 // missing: Asm, 140 } 141 142 txid := in.PreviousOutPoint.Hash.String() 143 144 vin[i] = bchain.Vin{ 145 Txid: txid, 146 Vout: in.PreviousOutPoint.Index, 147 Sequence: in.Sequence, 148 ScriptSig: s, 149 } 150 } 151 vout := make([]bchain.Vout, len(t.TxOut)) 152 for i, out := range t.TxOut { 153 addrs := []string{} 154 if parseAddresses { 155 addrs, _, _ = p.OutputScriptToAddressesFunc(out.PkScript) 156 } 157 s := bchain.ScriptPubKey{ 158 Hex: hex.EncodeToString(out.PkScript), 159 Addresses: addrs, 160 // missing: Asm, 161 // missing: Type, 162 } 163 var vs big.Int 164 vs.SetInt64(out.Value) 165 vout[i] = bchain.Vout{ 166 ValueSat: vs, 167 N: uint32(i), 168 ScriptPubKey: s, 169 } 170 } 171 tx := bchain.Tx{ 172 Txid: t.TxHash().String(), 173 Version: t.Version, 174 LockTime: t.LockTime, 175 Vin: vin, 176 Vout: vout, 177 // skip: BlockHash, 178 // skip: Confirmations, 179 // skip: Time, 180 // skip: Blocktime, 181 } 182 return tx 183 } 184 185 // ParseTxFromJSON parses JSON message containing transaction and returns Tx struct 186 func (p *DivicoinParser) ParseTxFromJSON(msg json.RawMessage) (*bchain.Tx, error) { 187 var tx bchain.Tx 188 err := json.Unmarshal(msg, &tx) 189 if err != nil { 190 return nil, err 191 } 192 193 for i := range tx.Vout { 194 vout := &tx.Vout[i] 195 // convert vout.JsonValue to big.Int and clear it, it is only temporary value used for unmarshal 196 vout.ValueSat, err = p.AmountToBigInt(vout.JsonValue) 197 if err != nil { 198 return nil, err 199 } 200 vout.JsonValue = "" 201 202 if vout.ScriptPubKey.Addresses == nil { 203 vout.ScriptPubKey.Addresses = []string{} 204 } 205 } 206 207 return &tx, nil 208 } 209 210 // outputScriptToAddresses converts ScriptPubKey to bitcoin addresses 211 func (p *DivicoinParser) outputScriptToAddresses(script []byte) ([]string, bool, error) { 212 rv, s, _ := p.BitcoinOutputScriptToAddressesFunc(script) 213 return rv, s, nil 214 } 215 216 // GetAddrDescForUnknownInput = ??? 217 func (p *DivicoinParser) GetAddrDescForUnknownInput(tx *bchain.Tx, input int) bchain.AddressDescriptor { 218 if len(tx.Vin) > input { 219 scriptHex := tx.Vin[input].ScriptSig.Hex 220 221 if scriptHex != "" { 222 script, _ := hex.DecodeString(scriptHex) 223 return script 224 } 225 } 226 227 s := make([]byte, 10) 228 return s 229 }