github.com/trezor/blockbook@v0.4.1-0.20240328132726-e9a08582ee2c/bchain/coins/liquid/liquidparser.go (about) 1 package liquid 2 3 import ( 4 "strconv" 5 6 vlq "github.com/bsm/go-vlq" 7 "github.com/golang/glog" 8 "github.com/martinboehm/btcd/txscript" 9 "github.com/martinboehm/btcd/wire" 10 "github.com/martinboehm/btcutil/chaincfg" 11 "github.com/trezor/blockbook/bchain" 12 "github.com/trezor/blockbook/bchain/coins/btc" 13 ) 14 15 const ( 16 // MainnetMagic is mainnet network constant 17 MainnetMagic wire.BitcoinNet = 0xdab5bffa 18 ) 19 20 var ( 21 // MainNetParams are parser parameters for mainnet 22 MainNetParams chaincfg.Params 23 ) 24 25 func init() { 26 MainNetParams = chaincfg.MainNetParams 27 MainNetParams.Net = MainnetMagic 28 MainNetParams.PubKeyHashAddrID = []byte{57} 29 MainNetParams.ScriptHashAddrID = []byte{39} 30 // BLINDED_ADDRESS 12 31 } 32 33 // LiquidParser handle 34 type LiquidParser struct { 35 *btc.BitcoinLikeParser 36 baseparser *bchain.BaseParser 37 origOutputScriptToAddressesFunc btc.OutputScriptToAddressesFunc 38 } 39 40 // NewLiquidParser returns new LiquidParser instance 41 func NewLiquidParser(params *chaincfg.Params, c *btc.Configuration) *LiquidParser { 42 p := &LiquidParser{ 43 BitcoinLikeParser: btc.NewBitcoinLikeParser(params, c), 44 baseparser: &bchain.BaseParser{}, 45 } 46 p.origOutputScriptToAddressesFunc = p.OutputScriptToAddressesFunc 47 p.OutputScriptToAddressesFunc = p.outputScriptToAddresses 48 return p 49 } 50 51 // GetChainParams contains network parameters for the main GameCredits network, 52 // and the test GameCredits network 53 func GetChainParams(chain string) *chaincfg.Params { 54 if !chaincfg.IsRegistered(&MainNetParams) { 55 err := chaincfg.Register(&MainNetParams) 56 if err != nil { 57 panic(err) 58 } 59 } 60 switch chain { 61 default: 62 return &MainNetParams 63 } 64 } 65 66 // PackTx packs transaction to byte array using protobuf 67 func (p *LiquidParser) PackTx(tx *bchain.Tx, height uint32, blockTime int64) ([]byte, error) { 68 return p.baseparser.PackTx(tx, height, blockTime) 69 } 70 71 // UnpackTx unpacks transaction from protobuf byte array 72 func (p *LiquidParser) UnpackTx(buf []byte) (*bchain.Tx, uint32, error) { 73 return p.baseparser.UnpackTx(buf) 74 } 75 76 // GetAddrDescForUnknownInput processes inputs that were not found in txAddresses - they are bitcoin transactions 77 // create a special script for the input in the form OP_INVALIDOPCODE <txid> <vout varint> 78 func (p *LiquidParser) GetAddrDescForUnknownInput(tx *bchain.Tx, input int) bchain.AddressDescriptor { 79 var iTxid string 80 s := make([]byte, 0, 40) 81 if len(tx.Vin) > input { 82 iTxid = tx.Vin[input].Txid 83 btxID, err := p.PackTxid(iTxid) 84 if err == nil { 85 buf := make([]byte, vlq.MaxLen64) 86 l := vlq.PutInt(buf, int64(tx.Vin[input].Vout)) 87 s = append(s, txscript.OP_INVALIDOPCODE) 88 s = append(s, btxID...) 89 s = append(s, buf[:l]...) 90 } 91 } 92 glog.Info("tx ", tx.Txid, ", encountered Bitcoin tx ", iTxid) 93 return s 94 } 95 96 // outputScriptToAddresses converts ScriptPubKey to bitcoin addresses 97 func (p *LiquidParser) outputScriptToAddresses(script []byte) ([]string, bool, error) { 98 // minimum length of the special script OP_INVALIDOPCODE <txid> <index varint> is 34 bytes (1 byte opcode, 32 bytes tx, 1 byte vout) 99 if len(script) > 33 && script[0] == txscript.OP_INVALIDOPCODE { 100 txid, _ := p.UnpackTxid(script[1:33]) 101 vout, _ := vlq.Int(script[33:]) 102 return []string{ 103 "Bitcoin tx " + txid + ":" + strconv.Itoa(int(vout)), 104 }, false, nil 105 } 106 return p.origOutputScriptToAddressesFunc(script) 107 }