github.com/cerberus-wallet/blockbook@v0.3.2/bchain/coins/nuls/nulsparser.go (about)

     1  package nuls
     2  
     3  import (
     4  	"blockbook/bchain"
     5  	"blockbook/bchain/coins/btc"
     6  	"bytes"
     7  	"encoding/binary"
     8  	"encoding/json"
     9  	"errors"
    10  	vlq "github.com/bsm/go-vlq"
    11  	"github.com/martinboehm/btcutil/base58"
    12  
    13  	"github.com/martinboehm/btcd/wire"
    14  	"github.com/martinboehm/btcutil/chaincfg"
    15  	"github.com/martinboehm/btcutil/hdkeychain"
    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.BitcoinParser
    63  }
    64  
    65  // NewNulsParser returns new NulsParser instance
    66  func NewNulsParser(params *chaincfg.Params, c *btc.Configuration) *NulsParser {
    67  	return &NulsParser{BitcoinParser: btc.NewBitcoinParser(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(xpub string, change uint32, fromIndex uint32, toIndex uint32) ([]bchain.AddressDescriptor, error) {
   165  	if toIndex <= fromIndex {
   166  		return nil, errors.New("toIndex<=fromIndex")
   167  	}
   168  	extKey, err := hdkeychain.NewKeyFromString(xpub, p.Params.Base58CksumHasher)
   169  	if err != nil {
   170  		return nil, err
   171  	}
   172  	changeExtKey, err := extKey.Child(change)
   173  	if err != nil {
   174  		return nil, err
   175  	}
   176  	ad := make([]bchain.AddressDescriptor, toIndex-fromIndex)
   177  	for index := fromIndex; index < toIndex; index++ {
   178  		indexExtKey, err := changeExtKey.Child(index)
   179  		if err != nil {
   180  			return nil, err
   181  		}
   182  		s, err := indexExtKey.Address(p.Params)
   183  
   184  		if err != nil && indexExtKey != nil {
   185  			return nil, err
   186  		}
   187  		addHashs := make([]byte, AddressHashLength)
   188  		copy(addHashs[0:3], p.Params.PubKeyHashAddrID)
   189  		copy(addHashs[3:], s.ScriptAddress())
   190  		copy(addHashs[23:], []byte{p.xor(addHashs[0:23])})
   191  
   192  		//addressStr := base58.Encode(addHashs)
   193  		ad[index-fromIndex] = addHashs
   194  	}
   195  	return ad, nil
   196  }
   197  
   198  func (p *NulsParser) xor(body []byte) byte {
   199  	var xor byte = 0x00
   200  	for i := 0; i < len(body); i++ {
   201  		xor ^= body[i]
   202  	}
   203  	return xor
   204  }