|
12 | 12 | #include "history/HistoryUtils.h" |
13 | 13 | #include "historywork/Progress.h" |
14 | 14 | #include "ledger/CheckpointRange.h" |
| 15 | +#include "ledger/LedgerHeaderUtils.h" |
15 | 16 | #include "ledger/LedgerManager.h" |
16 | 17 | #include "main/Application.h" |
17 | 18 | #include "util/GlobalChecks.h" |
@@ -286,31 +287,40 @@ ApplyCheckpointWork::getNextLedgerCloseData() |
286 | 287 | } |
287 | 288 |
|
288 | 289 | // Check that we use the correct time format in the ledger header. |
289 | | - bool const msActive = protocolVersionStartsFrom( |
290 | | - lclHeader.header.ledgerVersion, MS_CLOSE_TIME_PROTOCOL_VERSION); |
291 | | - if (!validateMsCloseTimeFormat(header.scpValue, |
292 | | - /*allowMsTime=*/msActive, |
293 | | - /*allowWholeSecondTime=*/!msActive)) |
| 290 | + if (!hasValidCloseTime(header.scpValue)) |
294 | 291 | { |
295 | 292 | throw std::runtime_error(fmt::format( |
296 | | - FMT_STRING("ledger header for {:d} has an invalid ms close time " |
297 | | - "(StellarValue type {:d}, closeTimeMs {:d}) under " |
298 | | - "protocol {:d}"), |
299 | | - header.ledgerSeq, static_cast<int32_t>(header.scpValue.ext.v()), |
300 | | - getCloseTimeMs(header.scpValue), lclHeader.header.ledgerVersion)); |
| 293 | + FMT_STRING("ledger header for {:d} has inconsistent close time " |
| 294 | + "fields: closeTime {:d}, consensus close time {}"), |
| 295 | + header.ledgerSeq, header.scpValue.closeTime, |
| 296 | + getConsensusTime(header.scpValue).toString())); |
| 297 | + } |
| 298 | + |
| 299 | + bool const hasMsCloseTime = isMsCloseTimeStellarValue(header.scpValue); |
| 300 | + bool const protocolRequiresMsCloseTime = |
| 301 | + protocolHasMsCloseTime(lclHeader.header.ledgerVersion); |
| 302 | + if (hasMsCloseTime != protocolRequiresMsCloseTime) |
| 303 | + { |
| 304 | + throw std::runtime_error(fmt::format( |
| 305 | + FMT_STRING("ledger header for {:d} has a {} close time " |
| 306 | + "(StellarValue type {:d}) but protocol {:d} requires a " |
| 307 | + "{} close time"), |
| 308 | + header.ledgerSeq, hasMsCloseTime ? "millisecond" : "whole-second", |
| 309 | + static_cast<int32_t>(header.scpValue.ext.v()), |
| 310 | + lclHeader.header.ledgerVersion, |
| 311 | + protocolRequiresMsCloseTime ? "millisecond" : "whole-second")); |
301 | 312 | } |
302 | 313 |
|
303 | | - // Check that close time never decreases |
304 | | - if (getCloseTime(header.scpValue) <= |
305 | | - getCloseTime(lclHeader.header.scpValue)) |
| 314 | + // Close times must strictly increase from ledger to ledger |
| 315 | + auto const previousCloseTime = getConsensusTime(lclHeader.header.scpValue); |
| 316 | + auto const nextCloseTime = getConsensusTime(header.scpValue); |
| 317 | + if (nextCloseTime <= previousCloseTime) |
306 | 318 | { |
307 | 319 | throw std::runtime_error(fmt::format( |
308 | 320 | FMT_STRING("ledger header for {:d} has a non-advancing close " |
309 | | - "time {:d}.{:03d} (previous {:d}.{:03d})"), |
310 | | - header.ledgerSeq, header.scpValue.closeTime, |
311 | | - getCloseTimeMs(header.scpValue), |
312 | | - lclHeader.header.scpValue.closeTime, |
313 | | - getCloseTimeMs(lclHeader.header.scpValue))); |
| 321 | + "time {} (previous ledger closed at {})"), |
| 322 | + header.ledgerSeq, nextCloseTime.toString(), |
| 323 | + previousCloseTime.toString())); |
314 | 324 | } |
315 | 325 |
|
316 | 326 | // We've verified the ledgerHeader (in the "trusted part of history" |
|
0 commit comments