decred.org/dcrdex@v1.0.5/client/asset/firo/tx_deserialize.go (about)

     1  package firo
     2  
     3  import (
     4  	"encoding/binary"
     5  	"fmt"
     6  	"io"
     7  
     8  	"github.com/btcsuite/btcd/wire"
     9  )
    10  
    11  var byteOrder = binary.LittleEndian
    12  
    13  const (
    14  	// protocol version 0
    15  	pver uint32 = 0
    16  	// wire.maxTxInPerMessage
    17  	maxTxInPerMessage = wire.MaxMessagePayload/41 + 1
    18  	// wire.maxTxOutPerMessage
    19  	maxTxOutPerMessage = wire.MaxMessagePayload/wire.MinTxOutPayload + 1
    20  )
    21  
    22  type TxType int
    23  
    24  const (
    25  	// Transaction types
    26  	TransactionNormal                  = 0
    27  	TransactionProviderRegister        = 1
    28  	TransactionProviderUpdateService   = 2
    29  	TransactionProviderUpdateRegistrar = 3
    30  	TransactionProviderUpdateRevoke    = 4
    31  	TransactionCoinbase                = 5
    32  	TransactionQuorumCommitment        = 6
    33  	TransactionSpork                   = 7
    34  	TransactionLelantus                = 8
    35  	TransactionSpark                   = 9
    36  	// TRANSACTION_ALIAS is a regular spark spend transaction, but contains
    37  	// additional info about a created/modified spark name.
    38  	TransactionAlias = 10
    39  )
    40  
    41  type decoder struct {
    42  	buf [8]byte
    43  	rd  io.Reader
    44  }
    45  
    46  func newDecoder(r io.Reader) *decoder {
    47  	return &decoder{rd: r}
    48  }
    49  
    50  func (d *decoder) Read(b []byte) (n int, err error) {
    51  	n, err = d.rd.Read(b)
    52  	if err != nil {
    53  		return 0, err
    54  	}
    55  	return n, nil
    56  }
    57  
    58  func (d *decoder) readByte() (byte, error) {
    59  	b := d.buf[:1]
    60  	if _, err := io.ReadFull(d, b); err != nil {
    61  		return 0, err
    62  	}
    63  	return b[0], nil
    64  }
    65  
    66  func (d *decoder) readUint16() (uint16, error) {
    67  	b := d.buf[:2]
    68  	if _, err := io.ReadFull(d, b); err != nil {
    69  		return 0, err
    70  	}
    71  	return byteOrder.Uint16(b), nil
    72  }
    73  
    74  func (d *decoder) readUint32() (uint32, error) {
    75  	b := d.buf[:4]
    76  	if _, err := io.ReadFull(d, b); err != nil {
    77  		return 0, err
    78  	}
    79  	return byteOrder.Uint32(b), nil
    80  }
    81  
    82  func (d *decoder) readUint64() (uint64, error) {
    83  	b := d.buf[:]
    84  	if _, err := io.ReadFull(d, b); err != nil {
    85  		return 0, err
    86  	}
    87  	return byteOrder.Uint64(b), nil
    88  }
    89  
    90  // readOutPoint reads the next sequence of bytes from r as an OutPoint.
    91  func (d *decoder) readOutPoint(op *wire.OutPoint) error {
    92  	_, err := io.ReadFull(d, op.Hash[:])
    93  	if err != nil {
    94  		return err
    95  	}
    96  
    97  	op.Index, err = d.readUint32()
    98  	return err
    99  }
   100  
   101  // wire.ReadVarInt a.k.a. CompactSize, not VARINT
   102  // https://en.bitcoin.it/wiki/Protocol_documentation#Variable_length_integer
   103  func (d *decoder) readCompactSize() (uint64, error) {
   104  	// Compact Size
   105  	// size <  253        -- 1 byte
   106  	// size <= USHRT_MAX  -- 3 bytes  (253 + 2 bytes)
   107  	// size <= UINT_MAX   -- 5 bytes  (254 + 4 bytes)
   108  	// size >  UINT_MAX   -- 9 bytes  (255 + 8 bytes)
   109  	chSize, err := d.readByte()
   110  	if err != nil {
   111  		return 0, err
   112  	}
   113  	switch chSize {
   114  	case 253:
   115  		sz, err := d.readUint16()
   116  		if err != nil {
   117  			return 0, err
   118  		}
   119  		return uint64(sz), nil
   120  	case 254:
   121  		sz, err := d.readUint32()
   122  		if err != nil {
   123  			return 0, err
   124  		}
   125  		return uint64(sz), nil
   126  	case 255:
   127  		sz, err := d.readUint64()
   128  		if err != nil {
   129  			return 0, err
   130  		}
   131  		return sz, nil
   132  	default: // < 253
   133  		return uint64(chSize), nil
   134  	}
   135  }
   136  
   137  // readTxIn reads the next sequence of bytes from r as a transaction input.
   138  func (d *decoder) readTxIn(ti *wire.TxIn) error {
   139  	err := d.readOutPoint(&ti.PreviousOutPoint)
   140  	if err != nil {
   141  		return err
   142  	}
   143  
   144  	ti.SignatureScript, err = wire.ReadVarBytes(d, pver, wire.MaxMessagePayload, "sigScript")
   145  	if err != nil {
   146  		return err
   147  	}
   148  
   149  	ti.Sequence, err = d.readUint32()
   150  	return err
   151  }
   152  
   153  // readTxOut reads the next sequence of bytes from r as a transaction output.
   154  func (d *decoder) readTxOut(to *wire.TxOut) error {
   155  	v, err := d.readUint64()
   156  	if err != nil {
   157  		return err
   158  	}
   159  
   160  	pkScript, err := wire.ReadVarBytes(d, pver, wire.MaxMessagePayload, "pkScript")
   161  	if err != nil {
   162  		return err
   163  	}
   164  
   165  	to.Value = int64(v)
   166  	to.PkScript = pkScript
   167  
   168  	return nil
   169  }
   170  
   171  // readVarBytes reads the next sequence of bytes from r and returns them.
   172  func (d *decoder) readVarBytes() ([]byte, error) {
   173  	byteArray, err := wire.ReadVarBytes(d, pver, wire.MaxMessagePayload, "extra")
   174  	if err != nil {
   175  		return nil, err
   176  	}
   177  	return byteArray, nil
   178  }
   179  
   180  type txn struct {
   181  	msgTx  *wire.MsgTx
   182  	txType TxType
   183  }
   184  
   185  // deserializeTransaction deserializes a transaction
   186  func deserializeTransaction(r io.Reader) (*txn, error) {
   187  	tx := txn{
   188  		msgTx:  &wire.MsgTx{},
   189  		txType: 0,
   190  	}
   191  
   192  	dec := newDecoder(r)
   193  
   194  	fullVersion, err := dec.readUint32()
   195  	if err != nil {
   196  		return nil, err
   197  	}
   198  	ver := fullVersion & 0x0000ffff
   199  	typ := (fullVersion >> 16) & 0x0000ffff
   200  
   201  	tx.msgTx.Version = int32(ver)
   202  	tx.txType = TxType(typ)
   203  
   204  	switch tx.txType {
   205  	case TransactionNormal,
   206  		TransactionProviderRegister,
   207  		TransactionProviderUpdateService,
   208  		TransactionProviderUpdateRegistrar,
   209  		TransactionProviderUpdateRevoke,
   210  		TransactionCoinbase,
   211  		TransactionLelantus,
   212  		TransactionSpark,
   213  		TransactionAlias:
   214  		{
   215  			deserializeTx(dec, &tx, tx.txType)
   216  		}
   217  	case TransactionQuorumCommitment,
   218  		TransactionSpork:
   219  		err = deserializeNonSpendingTx(dec, &tx, tx.txType)
   220  	default:
   221  		err = fmt.Errorf("unknown transaction type %d", tx.txType)
   222  	}
   223  
   224  	return &tx, err
   225  }
   226  
   227  // deserializeTx deserializes a transaction
   228  func deserializeTx(dec *decoder, tx *txn, txType TxType) error {
   229  	count, err := dec.readCompactSize()
   230  	if err != nil {
   231  		return err
   232  	}
   233  
   234  	if count == 0 {
   235  		return fmt.Errorf("input count is 0 -- but no segwit transactions for Firo")
   236  	}
   237  
   238  	if count > maxTxInPerMessage {
   239  		return fmt.Errorf("too many transaction inputs to fit into "+
   240  			"max message size [count %d, max %d]", count, maxTxInPerMessage)
   241  	}
   242  
   243  	tx.msgTx.TxIn = make([]*wire.TxIn, count)
   244  	for i := range tx.msgTx.TxIn {
   245  		txIn := &wire.TxIn{}
   246  		err = dec.readTxIn(txIn)
   247  		if err != nil {
   248  			return err
   249  		}
   250  		tx.msgTx.TxIn[i] = txIn
   251  	}
   252  
   253  	count, err = dec.readCompactSize()
   254  	if err != nil {
   255  		return err
   256  	}
   257  	if count > maxTxOutPerMessage {
   258  		return fmt.Errorf("too many transactions outputs to fit into "+
   259  			"max message size [count %d, max %d]", count, maxTxOutPerMessage)
   260  	}
   261  
   262  	tx.msgTx.TxOut = make([]*wire.TxOut, count)
   263  	for i := range tx.msgTx.TxOut {
   264  		txOut := &wire.TxOut{}
   265  		err = dec.readTxOut(txOut)
   266  		if err != nil {
   267  			return err
   268  		}
   269  		tx.msgTx.TxOut[i] = txOut
   270  	}
   271  
   272  	tx.msgTx.LockTime, err = dec.readUint32()
   273  	if err != nil {
   274  		return err
   275  	}
   276  
   277  	if txType == TransactionNormal {
   278  		return nil
   279  	}
   280  
   281  	// read vExtraPayload
   282  	_, err = dec.readVarBytes()
   283  	return err
   284  }
   285  
   286  // deserializeNonSpendingTx deserializes spork, quorum txs which have no inputs and
   287  // no outputs
   288  func deserializeNonSpendingTx(dec *decoder, tx *txn, txType TxType) error {
   289  	count, err := dec.readCompactSize()
   290  	if err != nil {
   291  		return err
   292  	}
   293  
   294  	if count != 0 {
   295  		return fmt.Errorf("tx (type=%d) expected 0 txins - got %d", txType, count)
   296  	}
   297  
   298  	count, err = dec.readCompactSize()
   299  	if err != nil {
   300  		return err
   301  	}
   302  
   303  	if count != 0 {
   304  		return fmt.Errorf("tx (type=%d) expected 0 txouts - got %d", txType, count)
   305  	}
   306  
   307  	tx.msgTx.LockTime, err = dec.readUint32()
   308  	if err != nil {
   309  		return err
   310  	}
   311  
   312  	_, err = dec.readVarBytes()
   313  	return err
   314  }