| 207 | } // namespace |
| 208 | |
| 209 | std::optional<LockPoints> CalculateLockPointsAtTip( |
| 210 | CBlockIndex* tip, |
| 211 | const CCoinsView& coins_view, |
| 212 | const CTransaction& tx) |
| 213 | { |
| 214 | assert(tip); |
| 215 | |
| 216 | auto prev_heights{CalculatePrevHeights(*tip, coins_view, tx)}; |
| 217 | if (!prev_heights.has_value()) return std::nullopt; |
| 218 | |
| 219 | CBlockIndex next_tip; |
| 220 | next_tip.pprev = tip; |
| 221 | // When SequenceLocks() is called within ConnectBlock(), the height |
| 222 | // of the block *being* evaluated is what is used. |
| 223 | // Thus if we want to know if a transaction can be part of the |
| 224 | // *next* block, we need to use one more than active_chainstate.m_chain.Height() |
| 225 | next_tip.nHeight = tip->nHeight + 1; |
| 226 | const auto [min_height, min_time] = CalculateSequenceLocks(tx, STANDARD_LOCKTIME_VERIFY_FLAGS, prev_heights.value(), next_tip); |
| 227 | |
| 228 | // Also store the hash of the block with the highest height of |
| 229 | // all the blocks which have sequence locked prevouts. |
| 230 | // This hash needs to still be on the chain |
| 231 | // for these LockPoint calculations to be valid |
| 232 | // Note: It is impossible to correctly calculate a maxInputBlock |
| 233 | // if any of the sequence locked inputs depend on unconfirmed txs, |
| 234 | // except in the special case where the relative lock time/height |
| 235 | // is 0, which is equivalent to no sequence lock. Since we assume |
| 236 | // input height of tip+1 for mempool txs and test the resulting |
| 237 | // min_height and min_time from CalculateSequenceLocks against tip+1. |
| 238 | int max_input_height{0}; |
| 239 | for (const int height : prev_heights.value()) { |
| 240 | // Can ignore mempool inputs since we'll fail if they had non-zero locks |
| 241 | if (height != next_tip.nHeight) { |
| 242 | max_input_height = std::max(max_input_height, height); |
| 243 | } |
| 244 | } |
| 245 | |
| 246 | // tip->GetAncestor(max_input_height) should never return a nullptr |
| 247 | // because max_input_height is always less than the tip height. |
| 248 | // It would, however, be a bad bug to continue execution, since a |
| 249 | // LockPoints object with the maxInputBlock member set to nullptr |
| 250 | // signifies no relative lock time. |
| 251 | return LockPoints{min_height, min_time, Assert(tip->GetAncestor(max_input_height))}; |
| 252 | } |
| 253 | |
| 254 | bool CheckSequenceLocksAtTip(CBlockIndex* tip, |
| 255 | const LockPoints& lock_points) |