github.com/cerberus-wallet/blockbook@v0.3.2/bchain/coins/monetaryunit/monetaryunitparser.go (about) 1 package monetaryunit 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 "github.com/juju/errors" 14 "github.com/martinboehm/btcd/wire" 15 "github.com/martinboehm/btcutil/chaincfg" 16 ) 17 18 const ( 19 // Net Magics 20 MainnetMagic wire.BitcoinNet = 0x91c4fdea 21 TestnetMagic wire.BitcoinNet = 0x477665bd 22 ) 23 24 var ( 25 MainNetParams chaincfg.Params 26 TestNetParams chaincfg.Params 27 ) 28 29 func init() { 30 // MonetaryUnit mainnet Address encoding magics 31 MainNetParams = chaincfg.MainNetParams 32 MainNetParams.Net = MainnetMagic 33 MainNetParams.PubKeyHashAddrID = []byte{16} // starting with '7' 34 MainNetParams.ScriptHashAddrID = []byte{76} 35 MainNetParams.PrivateKeyID = []byte{126} 36 37 // MonetaryUnit testnet Address encoding magics 38 TestNetParams = chaincfg.TestNet3Params 39 TestNetParams.Net = TestnetMagic 40 TestNetParams.PubKeyHashAddrID = []byte{139} // starting with 'x' or 'y' 41 TestNetParams.ScriptHashAddrID = []byte{19} 42 TestNetParams.PrivateKeyID = []byte{239} 43 } 44 45 // MonetaryUnitParser handle 46 type MonetaryUnitParser struct { 47 *btc.BitcoinParser 48 baseparser *bchain.BaseParser 49 BitcoinOutputScriptToAddressesFunc btc.OutputScriptToAddressesFunc 50 } 51 52 // NewMonetaryUnitParser returns new MonetaryUnitParser instance 53 func NewMonetaryUnitParser(params *chaincfg.Params, c *btc.Configuration) *MonetaryUnitParser { 54 p := &MonetaryUnitParser{ 55 BitcoinParser: btc.NewBitcoinParser(params, c), 56 baseparser: &bchain.BaseParser{}, 57 } 58 p.BitcoinOutputScriptToAddressesFunc = p.OutputScriptToAddressesFunc 59 p.OutputScriptToAddressesFunc = p.outputScriptToAddresses 60 return p 61 } 62 63 // GetChainParams contains network parameters for the main MonetaryUnit network 64 func GetChainParams(chain string) *chaincfg.Params { 65 if !chaincfg.IsRegistered(&MainNetParams) { 66 err := chaincfg.Register(&MainNetParams) 67 if err == nil { 68 err = chaincfg.Register(&TestNetParams) 69 } 70 if err != nil { 71 panic(err) 72 } 73 } 74 switch chain { 75 case "test": 76 return &TestNetParams 77 default: 78 return &MainNetParams 79 } 80 } 81 82 // ParseBlock parses raw block to our Block struct 83 func (p *MonetaryUnitParser) ParseBlock(b []byte) (*bchain.Block, error) { 84 r := bytes.NewReader(b) 85 w := wire.MsgBlock{} 86 h := wire.BlockHeader{} 87 err := h.Deserialize(r) 88 if err != nil { 89 return nil, errors.Annotatef(err, "Deserialize") 90 } 91 92 if h.Version > 3 { 93 // Skip past AccumulatorCheckpoint which was added in MonetaryUnit block version 4 94 r.Seek(32, io.SeekCurrent) 95 } 96 97 err = utils.DecodeTransactions(r, 0, wire.WitnessEncoding, &w) 98 if err != nil { 99 return nil, errors.Annotatef(err, "DecodeTransactions") 100 } 101 102 txs := make([]bchain.Tx, len(w.Transactions)) 103 for ti, t := range w.Transactions { 104 txs[ti] = p.TxFromMsgTx(t, false) 105 } 106 107 return &bchain.Block{ 108 BlockHeader: bchain.BlockHeader{ 109 Size: len(b), 110 Time: h.Timestamp.Unix(), 111 }, 112 Txs: txs, 113 }, nil 114 } 115 116 // PackTx packs transaction to byte array using protobuf 117 func (p *MonetaryUnitParser) PackTx(tx *bchain.Tx, height uint32, blockTime int64) ([]byte, error) { 118 return p.baseparser.PackTx(tx, height, blockTime) 119 } 120 121 // UnpackTx unpacks transaction from protobuf byte array 122 func (p *MonetaryUnitParser) UnpackTx(buf []byte) (*bchain.Tx, uint32, error) { 123 return p.baseparser.UnpackTx(buf) 124 } 125 126 // ParseTx parses byte array containing transaction and returns Tx struct 127 func (p *MonetaryUnitParser) ParseTx(b []byte) (*bchain.Tx, error) { 128 t := wire.MsgTx{} 129 r := bytes.NewReader(b) 130 if err := t.Deserialize(r); err != nil { 131 return nil, err 132 } 133 tx := p.TxFromMsgTx(&t, true) 134 tx.Hex = hex.EncodeToString(b) 135 return &tx, nil 136 } 137 138 // ParseTxFromJson parses JSON message containing transaction and returns Tx struct 139 func (p *MonetaryUnitParser) ParseTxFromJson(msg json.RawMessage) (*bchain.Tx, error) { 140 var tx bchain.Tx 141 err := json.Unmarshal(msg, &tx) 142 if err != nil { 143 return nil, err 144 } 145 146 for i := range tx.Vout { 147 vout := &tx.Vout[i] 148 // convert vout.JsonValue to big.Int and clear it, it is only temporary value used for unmarshal 149 vout.ValueSat, err = p.AmountToBigInt(vout.JsonValue) 150 if err != nil { 151 return nil, err 152 } 153 vout.JsonValue = "" 154 155 if vout.ScriptPubKey.Addresses == nil { 156 vout.ScriptPubKey.Addresses = []string{} 157 } 158 } 159 160 return &tx, nil 161 } 162 163 // outputScriptToAddresses converts ScriptPubKey to bitcoin addresses 164 func (p *MonetaryUnitParser) outputScriptToAddresses(script []byte) ([]string, bool, error) { 165 166 rv, s, _ := p.BitcoinOutputScriptToAddressesFunc(script) 167 return rv, s, nil 168 } 169 170 func (p *MonetaryUnitParser) GetAddrDescForUnknownInput(tx *bchain.Tx, input int) bchain.AddressDescriptor { 171 if len(tx.Vin) > input { 172 scriptHex := tx.Vin[input].ScriptSig.Hex 173 174 if scriptHex != "" { 175 script, _ := hex.DecodeString(scriptHex) 176 return script 177 } 178 } 179 180 s := make([]byte, 10) 181 return s 182 }