tx.go raw

   1  package util
   2  
   3  import (
   4  	"bytes"
   5  	"io"
   6  	
   7  	"github.com/p9c/p9/pkg/chainhash"
   8  	"github.com/p9c/p9/pkg/wire"
   9  )
  10  
  11  // TxIndexUnknown is the value returned for a transaction index that is unknown.
  12  // This is typically because the transaction has not been inserted into a block
  13  // yet.
  14  const TxIndexUnknown = -1
  15  
  16  // Tx defines a bitcoin transaction that provides easier and more efficient
  17  // manipulation of raw transactions. It also memorizes the hash for the
  18  // transaction on its first access so subsequent accesses don't have to repeat
  19  // the relatively expensive hashing operations.
  20  type Tx struct {
  21  	msgTx         *wire.MsgTx     // Underlying MsgTx
  22  	txHash        *chainhash.Hash // Cached transaction hash
  23  	txHashWitness *chainhash.Hash // Cached transaction witness hash
  24  	txHasWitness  *bool           // If the transaction has witness data
  25  	txIndex       int             // Position within a block or TxIndexUnknown
  26  }
  27  
  28  // MsgTx returns the underlying wire.MsgTx for the transaction.
  29  func (t *Tx) MsgTx() *wire.MsgTx {
  30  	// Return the cached transaction.
  31  	return t.msgTx
  32  }
  33  
  34  // Hash returns the hash of the transaction. This is equivalent to calling
  35  // TxHash on the underlying wire.MsgTx, however it caches the result so
  36  // subsequent calls are more efficient.
  37  func (t *Tx) Hash() *chainhash.Hash {
  38  	// Return the cached hash if it has already been generated.
  39  	if t.txHash != nil {
  40  		return t.txHash
  41  	}
  42  	// Cache the hash and return it.
  43  	hash := t.msgTx.TxHash()
  44  	t.txHash = &hash
  45  	return &hash
  46  }
  47  
  48  // // WitnessHash returns the witness hash (wtxid) of the transaction. This is
  49  // // equivalent to calling WitnessHash on the underlying wire.MsgTx, however it
  50  // // caches the result so subsequent calls are more efficient.
  51  // func (t *Tx) WitnessHash() *chainhash.Hash {
  52  // 	// Return the cached hash if it has already been generated.
  53  // 	if t.txHashWitness != nil {
  54  // 		return t.txHashWitness
  55  // 	}
  56  // 	// Cache the hash and return it.
  57  // 	hash := t.msgTx.WitnessHash()
  58  // 	t.txHashWitness = &hash
  59  // 	return &hash
  60  // }
  61  
  62  // // HasWitness returns false if none of the inputs within the transaction contain
  63  // // witness data, true false otherwise. This equivalent to calling HasWitness on
  64  // // the underlying wire.MsgTx, however it caches the result so subsequent calls
  65  // // are more efficient.
  66  // func (t *Tx) HasWitness() bool {
  67  // 	if t.txHashWitness != nil {
  68  // 		return *t.txHasWitness
  69  // 	}
  70  // 	hasWitness := t.msgTx.HasWitness()
  71  // 	t.txHasWitness = &hasWitness
  72  // 	return hasWitness
  73  // }
  74  
  75  // Index returns the saved index of the transaction within a block. This value
  76  // will be TxIndexUnknown if it hasn't already explicitly been set.
  77  func (t *Tx) Index() int {
  78  	return t.txIndex
  79  }
  80  
  81  // SetIndex sets the index of the transaction in within a block.
  82  func (t *Tx) SetIndex(index int) {
  83  	t.txIndex = index
  84  }
  85  
  86  // NewTx returns a new instance of a bitcoin transaction given an underlying
  87  // wire.MsgTx. See Tx.
  88  func NewTx(msgTx *wire.MsgTx) *Tx {
  89  	return &Tx{
  90  		msgTx:   msgTx,
  91  		txIndex: TxIndexUnknown,
  92  	}
  93  }
  94  
  95  // NewTxFromBytes returns a new instance of a bitcoin transaction given the
  96  // serialized bytes. See Tx.
  97  func NewTxFromBytes(serializedTx []byte) (*Tx, error) {
  98  	br := bytes.NewReader(serializedTx)
  99  	return NewTxFromReader(br)
 100  }
 101  
 102  // NewTxFromReader returns a new instance of a bitcoin transaction given a
 103  // Reader to deserialize the transaction. See Tx.
 104  func NewTxFromReader(r io.Reader) (*Tx, error) {
 105  	// Deserialize the bytes into a MsgTx.
 106  	var msgTx wire.MsgTx
 107  	e := msgTx.Deserialize(r)
 108  	if e != nil {
 109  		return nil, e
 110  	}
 111  	t := Tx{
 112  		msgTx:   &msgTx,
 113  		txIndex: TxIndexUnknown,
 114  	}
 115  	return &t, nil
 116  }
 117