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 }