github.com/decred/dcrd/blockchain@v1.2.1/sequencelock.go (about)

     1  // Copyright (c) 2017-2019 The Decred developers
     2  // Use of this source code is governed by an ISC
     3  // license that can be found in the LICENSE file.
     4  
     5  package blockchain
     6  
     7  import (
     8  	"fmt"
     9  
    10  	"github.com/decred/dcrd/blockchain/stake"
    11  	"github.com/decred/dcrd/blockchain/standalone"
    12  	"github.com/decred/dcrd/dcrutil"
    13  	"github.com/decred/dcrd/wire"
    14  )
    15  
    16  // SequenceLock represents the minimum timestamp and minimum block height after
    17  // which a transaction can be included into a block while satisfying the
    18  // relative lock times of all of its input sequence numbers.  It is calculated
    19  // via the CalcSequenceLock function.  Each field may be -1 if none of the input
    20  // sequence numbers require a specific relative lock time for the respective
    21  // type.  Since all valid heights and times are larger than -1, this implies
    22  // that it will not prevent a transaction from being included due to the
    23  // sequence lock, which is the desired behavior.
    24  type SequenceLock struct {
    25  	MinHeight int64
    26  	MinTime   int64
    27  }
    28  
    29  // isStakeBaseTx determines whether or not a transaction is a stakebase (also
    30  // known as a vote).  A stakebase is a special transaction created by the
    31  // proof-of-stake system that creates subsidy.  This function simply delegates
    32  // to the IsSSGen function in the stake package and exists to make calling code
    33  // that does not care about the specific reason the transaction is not a
    34  // stakebase, rather only if it is one or not.
    35  func isStakeBaseTx(tx *wire.MsgTx) bool {
    36  	return stake.IsSSGen(tx)
    37  }
    38  
    39  // calcSequenceLock computes the relative lock times for the passed transaction
    40  // from the point of view of the block node passed in as the first argument.
    41  //
    42  // See the CalcSequenceLock comments for more details.
    43  func (b *BlockChain) calcSequenceLock(node *blockNode, tx *dcrutil.Tx, view *UtxoViewpoint, isActive bool) (*SequenceLock, error) {
    44  	// A value of -1 for each lock type allows a transaction to be included
    45  	// in a block at any given height or time.
    46  	sequenceLock := &SequenceLock{MinHeight: -1, MinTime: -1}
    47  
    48  	// Sequence locks do not apply if they are not yet active, the tx
    49  	// version is less than 2, or the tx is a coinbase or stakebase, so
    50  	// return now with a sequence lock that indicates the tx can possibly be
    51  	// included in a block at any given height or time.
    52  	msgTx := tx.MsgTx()
    53  	enforce := isActive && msgTx.Version >= 2
    54  	if !enforce || standalone.IsCoinBaseTx(msgTx) || isStakeBaseTx(msgTx) {
    55  		return sequenceLock, nil
    56  	}
    57  
    58  	for txInIndex, txIn := range msgTx.TxIn {
    59  		// Nothing to calculate for this input when relative time locks
    60  		// are disabled for it.
    61  		sequenceNum := txIn.Sequence
    62  		if sequenceNum&wire.SequenceLockTimeDisabled != 0 {
    63  			continue
    64  		}
    65  
    66  		utxo := view.LookupEntry(&txIn.PreviousOutPoint.Hash)
    67  		if utxo == nil {
    68  			str := fmt.Sprintf("output %v referenced from "+
    69  				"transaction %s:%d either does not exist or "+
    70  				"has already been spent", txIn.PreviousOutPoint,
    71  				tx.Hash(), txInIndex)
    72  			return sequenceLock, ruleError(ErrMissingTxOut, str)
    73  		}
    74  
    75  		// Calculate the sequence locks from the point of view of the
    76  		// next block for inputs that are in the mempool.
    77  		inputHeight := utxo.BlockHeight()
    78  		if inputHeight == 0x7fffffff {
    79  			inputHeight = node.height + 1
    80  		}
    81  
    82  		// Mask off the value portion of the sequence number to obtain
    83  		// the time lock delta required before this input can be spent.
    84  		// The relative lock can be time based or block based.
    85  		relativeLock := int64(sequenceNum & wire.SequenceLockTimeMask)
    86  
    87  		if sequenceNum&wire.SequenceLockTimeIsSeconds != 0 {
    88  			// This input requires a time based relative lock
    89  			// expressed in seconds before it can be spent and time
    90  			// based locks are calculated relative to the earliest
    91  			// possible time the block that contains the referenced
    92  			// output could have been.  That time is the past
    93  			// median time of the block before it (technically one
    94  			// second after that, but that complexity is ignored for
    95  			// time based locks which already have a granularity
    96  			// associated with them anyways).  Therefore, the block
    97  			// prior to the one in which the referenced output was
    98  			// included is needed to compute its past median time.
    99  			prevInputHeight := inputHeight - 1
   100  			if prevInputHeight < 0 {
   101  				prevInputHeight = 0
   102  			}
   103  			blockNode := node.Ancestor(prevInputHeight)
   104  			medianTime := blockNode.CalcPastMedianTime()
   105  
   106  			// Calculate the minimum required timestamp based on the
   107  			// sum of the aforementioned past median time and
   108  			// required relative number of seconds.  Since time
   109  			// based relative locks have a granularity associated
   110  			// with them, shift left accordingly in order to convert
   111  			// to the proper number of relative seconds.  Also,
   112  			// subtract one from the relative lock to maintain the
   113  			// original lock time semantics.
   114  			relativeSecs := relativeLock << wire.SequenceLockTimeGranularity
   115  			minTime := medianTime.Unix() + relativeSecs - 1
   116  			if minTime > sequenceLock.MinTime {
   117  				sequenceLock.MinTime = minTime
   118  			}
   119  		} else {
   120  			// This input requires a relative lock expressed in
   121  			// blocks before it can be spent.  Therefore, calculate
   122  			// the minimum required height based on the sum of the
   123  			// input height and required relative number of blocks.
   124  			// Also, subtract one from the relative lock in order to
   125  			// maintain the original lock time semantics.
   126  			minHeight := inputHeight + relativeLock - 1
   127  			if minHeight > sequenceLock.MinHeight {
   128  				sequenceLock.MinHeight = minHeight
   129  			}
   130  		}
   131  	}
   132  
   133  	return sequenceLock, nil
   134  }
   135  
   136  // CalcSequenceLock computes the minimum block height and time after which the
   137  // passed transaction can be included into a block while satisfying the relative
   138  // lock times of all of its input sequence numbers.  The passed view is used to
   139  // obtain the past median time and block heights of the blocks in which the
   140  // referenced outputs of the inputs to the transaction were included.  The
   141  // generated sequence lock can be used in conjunction with a block height and
   142  // median time to determine if all inputs to the transaction have reached the
   143  // required maturity allowing it to be included in a block.
   144  //
   145  // NOTE: This will calculate the sequence locks regardless of the state of the
   146  // agenda which conditionally activates it.  This is acceptable for standard
   147  // transactions, however, callers which are intending to perform any type of
   148  // consensus checking must check the status of the agenda first.
   149  //
   150  // This function is safe for concurrent access.
   151  func (b *BlockChain) CalcSequenceLock(tx *dcrutil.Tx, view *UtxoViewpoint) (*SequenceLock, error) {
   152  	b.chainLock.Lock()
   153  	seqLock, err := b.calcSequenceLock(b.bestChain.Tip(), tx, view, true)
   154  	b.chainLock.Unlock()
   155  	return seqLock, err
   156  }
   157  
   158  // LockTimeToSequence converts the passed relative lock time to a sequence
   159  // number in accordance with DCP0003.
   160  //
   161  // A sequence number is defined as follows:
   162  //
   163  //   - bit 31 is the disable bit
   164  //   - the next 8 bits are reserved
   165  //   - bit 22 is the relative lock type (unset = block height, set = seconds)
   166  //   - the next 6 bites are reserved
   167  //   - the least significant 16 bits represent the value
   168  //     - value has a granularity of 512 when interpreted as seconds (bit 22 set)
   169  //
   170  //   ---------------------------------------------------
   171  //   | Disable | Reserved |  Type | Reserved |  Value  |
   172  //   ---------------------------------------------------
   173  //   |  1 bit  |  8 bits  | 1 bit |  6 bits  | 16 bits |
   174  //   ---------------------------------------------------
   175  //   |   [31]  |  [30-23] |  [22] |  [21-16] | [15-0]  |
   176  //   ---------------------------------------------------
   177  //
   178  // The above implies that the maximum relative block height that can be encoded
   179  // is 65535 and the maximum relative number of seconds that can be encoded is
   180  // 65535*512 = 33,553,920 seconds (~1.06 years).  It also means that seconds are
   181  // truncated to the nearest granularity towards 0 (e.g. 536 seconds will end up
   182  // round tripping as 512 seconds and 1500 seconds will end up round tripping as
   183  // 1024 seconds).
   184  //
   185  // An error will be returned for values that are larger than can be represented.
   186  func LockTimeToSequence(isSeconds bool, lockTime uint32) (uint32, error) {
   187  	// The corresponding sequence number is simply the desired input age
   188  	// when expressing the relative lock time in blocks.
   189  	if !isSeconds {
   190  		if lockTime > wire.SequenceLockTimeMask {
   191  			return 0, fmt.Errorf("max relative block height a "+
   192  				"sequence number can represent is %d",
   193  				wire.SequenceLockTimeMask)
   194  		}
   195  		return lockTime, nil
   196  	}
   197  
   198  	maxSeconds := uint32(wire.SequenceLockTimeMask <<
   199  		wire.SequenceLockTimeGranularity)
   200  	if lockTime > maxSeconds {
   201  		return 0, fmt.Errorf("max relative seconds a sequence number "+
   202  			"can represent is %d", maxSeconds)
   203  	}
   204  
   205  	// Set the 22nd bit which indicates the lock time is in seconds, then
   206  	// shift the lock time over by 9 since the time granularity is in
   207  	// 512-second intervals (2^9). This results in a max lock time of
   208  	// 33,553,920 seconds (~1.06 years).
   209  	return wire.SequenceLockTimeIsSeconds |
   210  		lockTime>>wire.SequenceLockTimeGranularity, nil
   211  }