108 lines
3.2 KiB
Go
108 lines
3.2 KiB
Go
package liquid
|
|
|
|
import (
|
|
"strconv"
|
|
|
|
vlq "github.com/bsm/go-vlq"
|
|
"github.com/golang/glog"
|
|
"github.com/martinboehm/btcd/txscript"
|
|
"github.com/martinboehm/btcd/wire"
|
|
"github.com/martinboehm/btcutil/chaincfg"
|
|
"spacecruft.org/spacecruft/blockbook/bchain"
|
|
"spacecruft.org/spacecruft/blockbook/bchain/coins/btc"
|
|
)
|
|
|
|
const (
|
|
// MainnetMagic is mainnet network constant
|
|
MainnetMagic wire.BitcoinNet = 0xdab5bffa
|
|
)
|
|
|
|
var (
|
|
// MainNetParams are parser parameters for mainnet
|
|
MainNetParams chaincfg.Params
|
|
)
|
|
|
|
func init() {
|
|
MainNetParams = chaincfg.MainNetParams
|
|
MainNetParams.Net = MainnetMagic
|
|
MainNetParams.PubKeyHashAddrID = []byte{57}
|
|
MainNetParams.ScriptHashAddrID = []byte{39}
|
|
// BLINDED_ADDRESS 12
|
|
}
|
|
|
|
// LiquidParser handle
|
|
type LiquidParser struct {
|
|
*btc.BitcoinParser
|
|
baseparser *bchain.BaseParser
|
|
origOutputScriptToAddressesFunc btc.OutputScriptToAddressesFunc
|
|
}
|
|
|
|
// NewLiquidParser returns new LiquidParser instance
|
|
func NewLiquidParser(params *chaincfg.Params, c *btc.Configuration) *LiquidParser {
|
|
p := &LiquidParser{
|
|
BitcoinParser: btc.NewBitcoinParser(params, c),
|
|
baseparser: &bchain.BaseParser{},
|
|
}
|
|
p.origOutputScriptToAddressesFunc = p.OutputScriptToAddressesFunc
|
|
p.OutputScriptToAddressesFunc = p.outputScriptToAddresses
|
|
return p
|
|
}
|
|
|
|
// GetChainParams contains network parameters for the main GameCredits network,
|
|
// and the test GameCredits network
|
|
func GetChainParams(chain string) *chaincfg.Params {
|
|
if !chaincfg.IsRegistered(&MainNetParams) {
|
|
err := chaincfg.Register(&MainNetParams)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
switch chain {
|
|
default:
|
|
return &MainNetParams
|
|
}
|
|
}
|
|
|
|
// PackTx packs transaction to byte array using protobuf
|
|
func (p *LiquidParser) PackTx(tx *bchain.Tx, height uint32, blockTime int64) ([]byte, error) {
|
|
return p.baseparser.PackTx(tx, height, blockTime)
|
|
}
|
|
|
|
// UnpackTx unpacks transaction from protobuf byte array
|
|
func (p *LiquidParser) UnpackTx(buf []byte) (*bchain.Tx, uint32, error) {
|
|
return p.baseparser.UnpackTx(buf)
|
|
}
|
|
|
|
// GetAddrDescForUnknownInput processes inputs that were not found in txAddresses - they are bitcoin transactions
|
|
// create a special script for the input in the form OP_INVALIDOPCODE <txid> <vout varint>
|
|
func (p *LiquidParser) GetAddrDescForUnknownInput(tx *bchain.Tx, input int) bchain.AddressDescriptor {
|
|
var iTxid string
|
|
s := make([]byte, 0, 40)
|
|
if len(tx.Vin) > input {
|
|
iTxid = tx.Vin[input].Txid
|
|
btxID, err := p.PackTxid(iTxid)
|
|
if err == nil {
|
|
buf := make([]byte, vlq.MaxLen64)
|
|
l := vlq.PutInt(buf, int64(tx.Vin[input].Vout))
|
|
s = append(s, txscript.OP_INVALIDOPCODE)
|
|
s = append(s, btxID...)
|
|
s = append(s, buf[:l]...)
|
|
}
|
|
}
|
|
glog.Info("tx ", tx.Txid, ", encountered Bitcoin tx ", iTxid)
|
|
return s
|
|
}
|
|
|
|
// outputScriptToAddresses converts ScriptPubKey to bitcoin addresses
|
|
func (p *LiquidParser) outputScriptToAddresses(script []byte) ([]string, bool, error) {
|
|
// minimum length of the special script OP_INVALIDOPCODE <txid> <index varint> is 34 bytes (1 byte opcode, 32 bytes tx, 1 byte vout)
|
|
if len(script) > 33 && script[0] == txscript.OP_INVALIDOPCODE {
|
|
txid, _ := p.UnpackTxid(script[1:33])
|
|
vout, _ := vlq.Int(script[33:])
|
|
return []string{
|
|
"Bitcoin tx " + txid + ":" + strconv.Itoa(int(vout)),
|
|
}, false, nil
|
|
}
|
|
return p.origOutputScriptToAddressesFunc(script)
|
|
}
|