github.com/trezor/blockbook@v0.4.1-0.20240328132726-e9a08582ee2c/bchain/coins/nuls/nulsparser.go (about)

     1  package nuls
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/binary"
     6  	"encoding/json"
     7  	"errors"
     8  
     9  	vlq "github.com/bsm/go-vlq"
    10  	"github.com/martinboehm/btcd/wire"
    11  	"github.com/martinboehm/btcutil/base58"
    12  	"github.com/martinboehm/btcutil/chaincfg"
    13  	"github.com/martinboehm/btcutil/hdkeychain"
    14  	"github.com/trezor/blockbook/bchain"
    15  	"github.com/trezor/blockbook/bchain/coins/btc"
    16  )
    17  
    18  // magic numbers
    19  const (
    20  	MainnetMagic wire.BitcoinNet = 0xbd6b0cbf
    21  	TestnetMagic wire.BitcoinNet = 0xffcae2ce
    22  	RegtestMagic wire.BitcoinNet = 0xdcb7c1fc
    23  
    24  	AddressHashLength = 24
    25  )
    26  
    27  // chain parameters
    28  var (
    29  	MainNetParams chaincfg.Params
    30  	TestNetParams chaincfg.Params
    31  	RegtestParams chaincfg.Params
    32  )
    33  
    34  func init() {
    35  	MainNetParams = chaincfg.MainNetParams
    36  	MainNetParams.Net = MainnetMagic
    37  
    38  	// Address encoding magics
    39  	MainNetParams.AddressMagicLen = 3
    40  
    41  	// Address encoding magics
    42  	MainNetParams.PubKeyHashAddrID = []byte{4, 35, 1} // base58 prefix: Ns
    43  	MainNetParams.ScriptHashAddrID = []byte{4, 35, 1} // base58 prefix: Ns
    44  
    45  	TestNetParams = chaincfg.TestNet3Params
    46  	TestNetParams.Net = TestnetMagic
    47  
    48  	// Address encoding magics
    49  	TestNetParams.PubKeyHashAddrID = []byte{140} // base58 prefix: y
    50  	TestNetParams.ScriptHashAddrID = []byte{19}  // base58 prefix: 8 or 9
    51  
    52  	RegtestParams = chaincfg.RegressionNetParams
    53  	RegtestParams.Net = RegtestMagic
    54  
    55  	// Address encoding magics
    56  	RegtestParams.PubKeyHashAddrID = []byte{140} // base58 prefix: y
    57  	RegtestParams.ScriptHashAddrID = []byte{19}  // base58 prefix: 8 or 9
    58  }
    59  
    60  // NulsParser handle
    61  type NulsParser struct {
    62  	*btc.BitcoinLikeParser
    63  }
    64  
    65  // NewNulsParser returns new NulsParser instance
    66  func NewNulsParser(params *chaincfg.Params, c *btc.Configuration) *NulsParser {
    67  	return &NulsParser{BitcoinLikeParser: btc.NewBitcoinLikeParser(params, c)}
    68  }
    69  
    70  // GetChainParams contains network parameters for the main Gincoin network,
    71  // the regression test Gincoin network, the test Gincoin network and
    72  // the simulation test Gincoin network, in this order
    73  func GetChainParams(chain string) *chaincfg.Params {
    74  	if !chaincfg.IsRegistered(&MainNetParams) {
    75  		err := chaincfg.Register(&MainNetParams)
    76  		if err == nil {
    77  			err = chaincfg.Register(&TestNetParams)
    78  		}
    79  		if err == nil {
    80  			err = chaincfg.Register(&RegtestParams)
    81  		}
    82  		if err != nil {
    83  			panic(err)
    84  		}
    85  	}
    86  	switch chain {
    87  	case "test":
    88  		return &TestNetParams
    89  	case "regtest":
    90  		return &RegtestParams
    91  	default:
    92  		return &MainNetParams
    93  	}
    94  }
    95  
    96  // PackedTxidLen returns length in bytes of packed txid
    97  func (p *NulsParser) PackedTxidLen() int {
    98  	return 34
    99  }
   100  
   101  // GetAddrDescFromAddress returns internal address representation (descriptor) of given address
   102  func (p *NulsParser) GetAddrDescFromAddress(address string) (bchain.AddressDescriptor, error) {
   103  	addressByte := base58.Decode(address)
   104  	return bchain.AddressDescriptor(addressByte), nil
   105  }
   106  
   107  // GetAddrDescFromVout returns internal address representation (descriptor) of given transaction output
   108  func (p *NulsParser) GetAddrDescFromVout(output *bchain.Vout) (bchain.AddressDescriptor, error) {
   109  	addressStr := output.ScriptPubKey.Hex
   110  	addressByte := base58.Decode(addressStr)
   111  	return bchain.AddressDescriptor(addressByte), nil
   112  }
   113  
   114  // GetAddressesFromAddrDesc returns addresses for given address descriptor with flag if the addresses are searchable
   115  func (p *NulsParser) GetAddressesFromAddrDesc(addrDesc bchain.AddressDescriptor) ([]string, bool, error) {
   116  	var addrs []string
   117  
   118  	if addrDesc != nil {
   119  		addrs = append(addrs, base58.Encode(addrDesc))
   120  	}
   121  
   122  	return addrs, true, nil
   123  }
   124  
   125  // PackTx packs transaction to byte array
   126  func (p *NulsParser) PackTx(tx *bchain.Tx, height uint32, blockTime int64) ([]byte, error) {
   127  	txBytes, error := json.Marshal(tx)
   128  	if error != nil {
   129  		return nil, error
   130  	}
   131  
   132  	buf := make([]byte, 4+vlq.MaxLen64)
   133  	binary.BigEndian.PutUint32(buf[0:4], height)
   134  	vlq.PutInt(buf[4:4+vlq.MaxLen64], blockTime)
   135  	resByes := bytes.Join([][]byte{buf, txBytes}, []byte(""))
   136  	return resByes, nil
   137  }
   138  
   139  // UnpackTx unpacks transaction from byte array
   140  func (p *NulsParser) UnpackTx(buf []byte) (*bchain.Tx, uint32, error) {
   141  	height := binary.BigEndian.Uint32(buf)
   142  	bt, _ := vlq.Int(buf[4 : 4+vlq.MaxLen64])
   143  	tx, err := p.ParseTx(buf[4+vlq.MaxLen64:])
   144  	if err != nil {
   145  		return nil, 0, err
   146  	}
   147  	tx.Blocktime = bt
   148  
   149  	return tx, height, nil
   150  }
   151  
   152  // ParseTx parses tx from blob
   153  func (p *NulsParser) ParseTx(b []byte) (*bchain.Tx, error) {
   154  	tx := bchain.Tx{}
   155  	err := json.Unmarshal(b, &tx)
   156  
   157  	if err != nil {
   158  		return nil, err
   159  	}
   160  	return &tx, err
   161  }
   162  
   163  // DeriveAddressDescriptorsFromTo derives address descriptors from given xpub for addresses in index range
   164  func (p *NulsParser) DeriveAddressDescriptorsFromTo(descriptor *bchain.XpubDescriptor, change uint32, fromIndex uint32, toIndex uint32) ([]bchain.AddressDescriptor, error) {
   165  	if toIndex <= fromIndex {
   166  		return nil, errors.New("toIndex<=fromIndex")
   167  	}
   168  	changeExtKey, err := descriptor.ExtKey.(*hdkeychain.ExtendedKey).Derive(change)
   169  	if err != nil {
   170  		return nil, err
   171  	}
   172  	ad := make([]bchain.AddressDescriptor, toIndex-fromIndex)
   173  	for index := fromIndex; index < toIndex; index++ {
   174  		indexExtKey, err := changeExtKey.Derive(index)
   175  		if err != nil {
   176  			return nil, err
   177  		}
   178  		s, err := indexExtKey.Address(p.Params)
   179  
   180  		if err != nil && indexExtKey != nil {
   181  			return nil, err
   182  		}
   183  		addHashs := make([]byte, AddressHashLength)
   184  		copy(addHashs[0:3], p.Params.PubKeyHashAddrID)
   185  		copy(addHashs[3:], s.ScriptAddress())
   186  		copy(addHashs[23:], []byte{p.xor(addHashs[0:23])})
   187  
   188  		//addressStr := base58.Encode(addHashs)
   189  		ad[index-fromIndex] = addHashs
   190  	}
   191  	return ad, nil
   192  }
   193  
   194  func (p *NulsParser) xor(body []byte) byte {
   195  	var xor byte = 0x00
   196  	for i := 0; i < len(body); i++ {
   197  		xor ^= body[i]
   198  	}
   199  	return xor
   200  }