decred.org/dcrdex@v1.0.5/dex/networks/ltc/tx.go (about)

     1  package ltc
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/binary"
     6  	"errors"
     7  	"fmt"
     8  	"io"
     9  
    10  	"github.com/btcsuite/btcd/chaincfg/chainhash"
    11  	"github.com/btcsuite/btcd/wire"
    12  
    13  	"lukechampine.com/blake3"
    14  )
    15  
    16  var byteOrder = binary.LittleEndian
    17  
    18  const (
    19  	pver               uint32 = 0                             // only protocol version 0 supported
    20  	maxTxInPerMessage         = wire.MaxMessagePayload/41 + 1 // wire.maxTxInPerMessage
    21  	maxTxOutPerMessage        = wire.MaxMessagePayload/       // wire.maxTxOutPerMessage
    22  		wire.MinTxOutPayload + 1
    23  	maxWitnessItemsPerInput = 4_000_000 // from wire
    24  	maxWitnessItemSize      = 4_000_000 // from wire
    25  )
    26  
    27  type decoder struct {
    28  	buf [8]byte
    29  	rd  io.Reader
    30  	tee *bytes.Buffer // anything read from rd is Written to tee
    31  }
    32  
    33  func newDecoder(r io.Reader) *decoder {
    34  	return &decoder{rd: r}
    35  }
    36  
    37  func (d *decoder) Read(b []byte) (n int, err error) {
    38  	n, err = d.rd.Read(b)
    39  	if err != nil {
    40  		return 0, err
    41  	}
    42  	if d.tee != nil {
    43  		d.tee.Write(b)
    44  	}
    45  	return n, nil
    46  }
    47  
    48  func (d *decoder) readByte() (byte, error) {
    49  	b := d.buf[:1]
    50  	if _, err := io.ReadFull(d, b); err != nil {
    51  		return 0, err
    52  	}
    53  	return b[0], nil
    54  }
    55  
    56  func (d *decoder) readUint16() (uint16, error) {
    57  	b := d.buf[:2]
    58  	if _, err := io.ReadFull(d, b); err != nil {
    59  		return 0, err
    60  	}
    61  	return byteOrder.Uint16(b), nil
    62  }
    63  
    64  func (d *decoder) readUint32() (uint32, error) {
    65  	b := d.buf[:4]
    66  	if _, err := io.ReadFull(d, b); err != nil {
    67  		return 0, err
    68  	}
    69  	return byteOrder.Uint32(b), nil
    70  }
    71  
    72  func (d *decoder) readUint64() (uint64, error) {
    73  	b := d.buf[:]
    74  	if _, err := io.ReadFull(d, b); err != nil {
    75  		return 0, err
    76  	}
    77  	return byteOrder.Uint64(b), nil
    78  }
    79  
    80  // readOutPoint reads the next sequence of bytes from r as an OutPoint.
    81  func (d *decoder) readOutPoint(op *wire.OutPoint) error {
    82  	_, err := io.ReadFull(d, op.Hash[:])
    83  	if err != nil {
    84  		return err
    85  	}
    86  
    87  	op.Index, err = d.readUint32()
    88  	return err
    89  }
    90  
    91  // wire.ReadVarInt a.k.a. CompactSize, not VARINT
    92  // https://en.bitcoin.it/wiki/Protocol_documentation#Variable_length_integer
    93  func (d *decoder) readCompactSize() (uint64, error) {
    94  	// Compact Size
    95  	// size <  253        -- 1 byte
    96  	// size <= USHRT_MAX  -- 3 bytes  (253 + 2 bytes)
    97  	// size <= UINT_MAX   -- 5 bytes  (254 + 4 bytes)
    98  	// size >  UINT_MAX   -- 9 bytes  (255 + 8 bytes)
    99  	chSize, err := d.readByte()
   100  	if err != nil {
   101  		return 0, err
   102  	}
   103  	switch chSize {
   104  	case 253:
   105  		sz, err := d.readUint16()
   106  		if err != nil {
   107  			return 0, err
   108  		}
   109  		return uint64(sz), nil
   110  	case 254:
   111  		sz, err := d.readUint32()
   112  		if err != nil {
   113  			return 0, err
   114  		}
   115  		return uint64(sz), nil
   116  	case 255:
   117  		sz, err := d.readUint64()
   118  		if err != nil {
   119  			return 0, err
   120  		}
   121  		return sz, nil
   122  	default: // < 253
   123  		return uint64(chSize), nil
   124  	}
   125  }
   126  
   127  // variable length quantity, not supposed to be part of the wire protocol.
   128  // Not the same as CompactSize type in the C++ code, but rather VARINT.
   129  // https://en.wikipedia.org/wiki/Variable-length_quantity
   130  // This function is borrowed from dcrd.
   131  func (d *decoder) readVLQ() (uint64, error) {
   132  	var n uint64
   133  	for {
   134  		val, err := d.readByte()
   135  		if err != nil {
   136  			return 0, err
   137  		}
   138  		n = (n << 7) | uint64(val&0x7f)
   139  		if val&0x80 != 0x80 {
   140  			break
   141  		}
   142  		n++
   143  	}
   144  
   145  	return n, nil
   146  }
   147  
   148  // readTxIn reads the next sequence of bytes from r as a transaction input.
   149  func (d *decoder) readTxIn(ti *wire.TxIn) error {
   150  	err := d.readOutPoint(&ti.PreviousOutPoint)
   151  	if err != nil {
   152  		return err
   153  	}
   154  
   155  	ti.SignatureScript, err = wire.ReadVarBytes(d, pver, wire.MaxMessagePayload, "sigScript")
   156  	if err != nil {
   157  		return err
   158  	}
   159  
   160  	ti.Sequence, err = d.readUint32()
   161  	return err
   162  }
   163  
   164  // readTxOut reads the next sequence of bytes from r as a transaction output.
   165  func (d *decoder) readTxOut(to *wire.TxOut) error {
   166  	v, err := d.readUint64()
   167  	if err != nil {
   168  		return err
   169  	}
   170  
   171  	pkScript, err := wire.ReadVarBytes(d, pver, wire.MaxMessagePayload, "pkScript")
   172  	if err != nil {
   173  		return err
   174  	}
   175  
   176  	to.Value = int64(v)
   177  	to.PkScript = pkScript
   178  
   179  	return nil
   180  }
   181  
   182  func (d *decoder) discardBytes(n int64) error {
   183  	m, err := io.CopyN(io.Discard, d, n)
   184  	if err != nil {
   185  		return err
   186  	}
   187  	if m != n {
   188  		return fmt.Errorf("only discarded %d of %d bytes", m, n)
   189  	}
   190  	return nil
   191  }
   192  
   193  func (d *decoder) discardVect() error {
   194  	sz, err := d.readCompactSize()
   195  	if err != nil {
   196  		return err
   197  	}
   198  	return d.discardBytes(int64(sz))
   199  }
   200  
   201  func (d *decoder) readMWTX() ([]byte, bool, error) {
   202  	// src/mweb/mweb_models.h - struct Tx
   203  	// "A convenience wrapper around a possibly-null MWEB transcation."
   204  	// Read the uint8_t is_set of OptionalPtr.
   205  	haveMWTX, err := d.readByte()
   206  	if err != nil {
   207  		return nil, false, err
   208  	}
   209  	if haveMWTX == 0 {
   210  		return nil, true, nil // HogEx - that's all folks
   211  	}
   212  
   213  	// src/libmw/include/mw/models/tx/Transaction.h - class Transaction
   214  	// READWRITE(obj.m_kernelOffset); // class BlindingFactor
   215  	// READWRITE(obj.m_stealthOffset); // class BlindingFactor
   216  	// READWRITE(obj.m_body); // class TxBody
   217  
   218  	// src/libmw/include/mw/models/crypto/BlindingFactor.h - class BlindingFactor
   219  	// just 32 bytes:
   220  	//  BigInt<32> m_value;
   221  	//  READWRITE(obj.m_value);
   222  	// x2 for both kernel_offset and stealth_offset BlindingFactor
   223  	if err = d.discardBytes(64); err != nil {
   224  		return nil, false, err
   225  	}
   226  
   227  	// TxBody
   228  	kern0, err := d.readMWTXBody()
   229  	if err != nil {
   230  		return nil, false, err
   231  	}
   232  	return kern0, false, nil
   233  }
   234  
   235  func (d *decoder) readMWTXBody() ([]byte, error) {
   236  	// src/libmw/include/mw/models/tx/TxBody.h - class TxBody
   237  	//  READWRITE(obj.m_inputs, obj.m_outputs, obj.m_kernels);
   238  	//  std::vector<Input> m_inputs;
   239  	//  std::vector<Output> m_outputs;
   240  	//  std::vector<Kernel> m_kernels;
   241  
   242  	// inputs
   243  	numIn, err := d.readCompactSize()
   244  	if err != nil {
   245  		return nil, err
   246  	}
   247  	for i := 0; i < int(numIn); i++ {
   248  		// src/libmw/include/mw/models/tx/Input.h - class Input
   249  		// - features uint8_t
   250  		// - outputID mw::Hash - 32 bytes BigInt<32>
   251  		// - commit Commitment - 33 bytes BigInt<SIZE> for SIZE 33
   252  		// - outputPubKey PublicKey - 33 bytes BigInt<33>
   253  		// (if features includes STEALTH_KEY_FEATURE_BIT) input_pubkey PublicKey
   254  		// (if features includes EXTRA_DATA_FEATURE_BIT) extraData vector<uint8_t>
   255  		// - signature Signature - 64 bytes BigInt<SIZE> for SIZE 64
   256  		//
   257  		// enum FeatureBit {
   258  		//     STEALTH_KEY_FEATURE_BIT = 0x01,
   259  		//     EXTRA_DATA_FEATURE_BIT = 0x02
   260  		// };
   261  		feats, err := d.readByte()
   262  		if err != nil {
   263  			return nil, err
   264  		}
   265  		if err = d.discardBytes(32 + 33 + 33); err != nil { // outputID, commitment, outputPubKey
   266  			return nil, err
   267  		}
   268  		if feats&0x1 != 0 { // input pubkey
   269  			if err = d.discardBytes(33); err != nil {
   270  				return nil, err
   271  			}
   272  		}
   273  		if feats&0x2 != 0 { // extraData
   274  			if err = d.discardVect(); err != nil {
   275  				return nil, err
   276  			}
   277  		}
   278  		if err = d.discardBytes(64); err != nil { // sig
   279  			return nil, err
   280  		}
   281  	} // inputs
   282  
   283  	// outputs
   284  	numOut, err := d.readCompactSize()
   285  	if err != nil {
   286  		return nil, err
   287  	}
   288  	for i := 0; i < int(numOut); i++ {
   289  		// src/libmw/include/mw/models/tx/Output.h - class Output
   290  		// commit
   291  		// sender pubkey
   292  		// receiver pubkey
   293  		// message OutputMessage --- fuuuuuuuu
   294  		// proof RangeProof
   295  		// signature
   296  		if err = d.discardBytes(33 + 33 + 33); err != nil { // commitment, sender pk, receiver pk
   297  			return nil, err
   298  		}
   299  
   300  		// OutputMessage
   301  		feats, err := d.readByte()
   302  		if err != nil {
   303  			return nil, err
   304  		}
   305  		// enum FeatureBit {
   306  		// 	STANDARD_FIELDS_FEATURE_BIT = 0x01,
   307  		// 	EXTRA_DATA_FEATURE_BIT = 0x02
   308  		// };
   309  		if feats&0x1 != 0 { // pubkey | view_tag uint8_t | masked_value uint64_t | nonce 16-bytes
   310  			if err = d.discardBytes(33 + 1 + 8 + 16); err != nil {
   311  				return nil, err
   312  			}
   313  		}
   314  		if feats&0x2 != 0 { // extraData
   315  			if err = d.discardVect(); err != nil {
   316  				return nil, err
   317  			}
   318  		}
   319  
   320  		// RangeProof "The proof itself, at most 675 bytes long."
   321  		// std::vector<uint8_t> m_bytes; -- except it's actually used like a [675]byte...
   322  		if err = d.discardBytes(675 + 64); err != nil { // proof + sig
   323  			return nil, err
   324  		}
   325  	} // outputs
   326  
   327  	// kernels
   328  	numKerns, err := d.readCompactSize()
   329  	if err != nil {
   330  		return nil, err
   331  	}
   332  	// Capture the first kernel since pure MW txns (no canonical inputs or
   333  	// outputs) that live in the MWEB but are also seen in mempool have their
   334  	// hash computed as blake3_256(kernel0).
   335  	var kern0 []byte
   336  	d.tee = new(bytes.Buffer)
   337  	for i := 0; i < int(numKerns); i++ {
   338  		// src/libmw/include/mw/models/tx/Kernel.h - class Kernel
   339  
   340  		// enum FeatureBit {
   341  		//     FEE_FEATURE_BIT = 0x01,
   342  		//     PEGIN_FEATURE_BIT = 0x02,
   343  		//     PEGOUT_FEATURE_BIT = 0x04,
   344  		//     HEIGHT_LOCK_FEATURE_BIT = 0x08,
   345  		//     STEALTH_EXCESS_FEATURE_BIT = 0x10,
   346  		//     EXTRA_DATA_FEATURE_BIT = 0x20,
   347  		//     ALL_FEATURE_BITS = FEE_FEATURE_BIT | PEGIN...
   348  		// };
   349  		feats, err := d.readByte()
   350  		if err != nil {
   351  			return nil, err
   352  		}
   353  		if feats&0x1 != 0 { // fee
   354  			_, err = d.readVLQ() // vlq for amount? in the wire protocol?!?
   355  			if err != nil {
   356  				return nil, err
   357  			}
   358  		}
   359  		if feats&0x2 != 0 { // pegin amt
   360  			_, err = d.readVLQ()
   361  			if err != nil {
   362  				return nil, err
   363  			}
   364  		}
   365  		if feats&0x4 != 0 { // pegouts vector
   366  			sz, err := d.readCompactSize()
   367  			if err != nil {
   368  				return nil, err
   369  			}
   370  			for i := uint64(0); i < sz; i++ {
   371  				_, err = d.readVLQ() // pegout amt
   372  				if err != nil {
   373  					return nil, err
   374  				}
   375  				if err = d.discardVect(); err != nil { // pkScript
   376  					return nil, err
   377  				}
   378  			}
   379  		}
   380  		if feats&0x8 != 0 { // lockHeight
   381  			_, err = d.readVLQ()
   382  			if err != nil {
   383  				return nil, err
   384  			}
   385  		}
   386  		if feats&0x10 != 0 { // stealth_excess pubkey
   387  			if err = d.discardBytes(33); err != nil {
   388  				return nil, err
   389  			}
   390  		}
   391  		if feats&0x20 != 0 { // extraData vector
   392  			if err = d.discardVect(); err != nil {
   393  				return nil, err
   394  			}
   395  		}
   396  		// "excess" commitment and signature
   397  		if err = d.discardBytes(33 + 64); err != nil {
   398  			return nil, err
   399  		}
   400  
   401  		if i == 0 {
   402  			kern0 = d.tee.Bytes()
   403  			d.tee = nil
   404  		}
   405  	} // kernels
   406  
   407  	return kern0, nil
   408  }
   409  
   410  type Tx struct {
   411  	*wire.MsgTx
   412  	IsHogEx bool
   413  	Kern0   []byte
   414  }
   415  
   416  func (tx *Tx) TxHash() chainhash.Hash {
   417  	// A pure-MW tx can only be in mempool or the EB, not the canonical block.
   418  	if len(tx.Kern0) > 0 && len(tx.TxIn) == 0 && len(tx.TxOut) == 0 {
   419  		// CTransaction::ComputeHash in src/primitives/transaction.cpp.
   420  		// Fortunately also a 32 byte hash so we can use chainhash.Hash.
   421  		return blake3.Sum256(tx.Kern0)
   422  	}
   423  	return tx.MsgTx.TxHash()
   424  }
   425  
   426  // DeserializeTx
   427  func DeserializeTx(r io.Reader) (*Tx, error) {
   428  	// mostly taken from wire/msgtx.go
   429  	msgTx := &wire.MsgTx{}
   430  	dec := newDecoder(r)
   431  
   432  	version, err := dec.readUint32()
   433  	if err != nil {
   434  		return nil, err
   435  	}
   436  	// if version != 0 {
   437  	// 	return nil, fmt.Errorf("only tx version 0 supported, got %d", version)
   438  	// }
   439  	msgTx.Version = int32(version)
   440  
   441  	count, err := dec.readCompactSize()
   442  	if err != nil {
   443  		return nil, err
   444  	}
   445  
   446  	// A count of zero (meaning no TxIn's to the uninitiated) means that the
   447  	// value is a TxFlagMarker, and hence indicates the presence of a flag.
   448  	var flag [1]byte
   449  	if count == 0 {
   450  		// The count varint was in fact the flag marker byte. Next, we need to
   451  		// read the flag value, which is a single byte.
   452  		if _, err = io.ReadFull(r, flag[:]); err != nil {
   453  			return nil, err
   454  		}
   455  
   456  		// Flag bits 0 or 3 must be set.
   457  		if flag[0]&0b1001 == 0 {
   458  			return nil, fmt.Errorf("witness tx but flag byte is %x", flag)
   459  		}
   460  
   461  		// With the Segregated Witness specific fields decoded, we can
   462  		// now read in the actual txin count.
   463  		count, err = dec.readCompactSize()
   464  		if err != nil {
   465  			return nil, err
   466  		}
   467  	}
   468  
   469  	if count > maxTxInPerMessage {
   470  		return nil, fmt.Errorf("too many transaction inputs to fit into "+
   471  			"max message size [count %d, max %d]", count, maxTxInPerMessage)
   472  	}
   473  
   474  	msgTx.TxIn = make([]*wire.TxIn, count)
   475  	for i := range msgTx.TxIn {
   476  		txIn := &wire.TxIn{}
   477  		err = dec.readTxIn(txIn)
   478  		if err != nil {
   479  			return nil, err
   480  		}
   481  		msgTx.TxIn[i] = txIn
   482  	}
   483  
   484  	count, err = dec.readCompactSize()
   485  	if err != nil {
   486  		return nil, err
   487  	}
   488  	if count > maxTxOutPerMessage {
   489  		return nil, fmt.Errorf("too many transactions outputs to fit into "+
   490  			"max message size [count %d, max %d]", count, maxTxOutPerMessage)
   491  	}
   492  
   493  	msgTx.TxOut = make([]*wire.TxOut, count)
   494  	for i := range msgTx.TxOut {
   495  		txOut := &wire.TxOut{}
   496  		err = dec.readTxOut(txOut)
   497  		if err != nil {
   498  			return nil, err
   499  		}
   500  		msgTx.TxOut[i] = txOut
   501  	}
   502  
   503  	if flag[0]&0x01 != 0 {
   504  		for _, txIn := range msgTx.TxIn {
   505  			witCount, err := dec.readCompactSize()
   506  			if err != nil {
   507  				return nil, err
   508  			}
   509  			if witCount > maxWitnessItemsPerInput {
   510  				return nil, fmt.Errorf("too many witness items: %d > max %d",
   511  					witCount, maxWitnessItemsPerInput)
   512  			}
   513  			txIn.Witness = make(wire.TxWitness, witCount)
   514  			for j := range txIn.Witness {
   515  				txIn.Witness[j], err = wire.ReadVarBytes(r, pver,
   516  					maxWitnessItemSize, "script witness item")
   517  				if err != nil {
   518  					return nil, err
   519  				}
   520  			}
   521  		}
   522  	}
   523  
   524  	// check for a MW tx based on flag 0x08
   525  	// src/primitives/transaction.h - class CTransaction
   526  	// Serialized like normal tx except with an optional MWEB::Tx after outputs
   527  	// and before locktime.
   528  	var kern0 []byte
   529  	var isHogEx bool
   530  	if flag[0]&0x08 != 0 {
   531  		kern0, isHogEx, err = dec.readMWTX()
   532  		if err != nil {
   533  			return nil, err
   534  		}
   535  		if isHogEx && len(msgTx.TxOut) == 0 {
   536  			return nil, errors.New("no outputs on HogEx txn")
   537  		}
   538  	}
   539  
   540  	msgTx.LockTime, err = dec.readUint32()
   541  	if err != nil {
   542  		return nil, err
   543  	}
   544  
   545  	return &Tx{msgTx, isHogEx, kern0}, nil
   546  }