|
1 | 1 | //! Common calculations for Cardano
|
2 | 2 |
|
3 | 3 | const BYRON_SLOTS_PER_EPOCH: u64 = 21_600;
|
4 |
| -pub const SHELLEY_SLOTS_PER_EPOCH: u64 = 432_000; |
5 |
| -const SHELLEY_START_SLOT: u64 = 4_492_800; |
6 |
| -const SHELLEY_START_EPOCH: u64 = 208; |
7 | 4 |
|
8 | 5 | /// Derive an epoch number from a slot, handling Byron/Shelley era changes
|
9 |
| -pub fn slot_to_epoch(slot: u64) -> u64 { |
10 |
| - slot_to_epoch_with_shelley_params(slot, SHELLEY_START_EPOCH, SHELLEY_SLOTS_PER_EPOCH) |
11 |
| -} |
12 |
| - |
13 | 6 | pub fn slot_to_epoch_with_shelley_params(
|
14 | 7 | slot: u64,
|
15 | 8 | shelley_epoch: u64,
|
16 | 9 | shelley_epoch_len: u64,
|
17 |
| -) -> u64 { |
| 10 | +) -> (u64, u64) { |
18 | 11 | let shelley_start_slot = shelley_epoch * BYRON_SLOTS_PER_EPOCH;
|
19 | 12 | if slot < shelley_start_slot {
|
20 |
| - slot / BYRON_SLOTS_PER_EPOCH |
| 13 | + (slot / BYRON_SLOTS_PER_EPOCH, slot % BYRON_SLOTS_PER_EPOCH) |
21 | 14 | } else {
|
22 |
| - shelley_epoch + (slot - shelley_start_slot) / shelley_epoch_len |
| 15 | + let slots_since_shelley_start = slot - shelley_start_slot; |
| 16 | + ( |
| 17 | + shelley_epoch + slots_since_shelley_start / shelley_epoch_len, |
| 18 | + slots_since_shelley_start % shelley_epoch_len, |
| 19 | + ) |
| 20 | + } |
| 21 | +} |
| 22 | + |
| 23 | +pub fn slot_to_timestamp_with_params(slot: u64, byron_timestamp: u64, shelley_epoch: u64) -> u64 { |
| 24 | + let shelley_start_slot = shelley_epoch * BYRON_SLOTS_PER_EPOCH; |
| 25 | + if slot < shelley_start_slot { |
| 26 | + byron_timestamp + slot * 20 |
| 27 | + } else { |
| 28 | + let shelley_timestamp = byron_timestamp + shelley_start_slot * 20; |
| 29 | + shelley_timestamp + (slot - shelley_start_slot) |
23 | 30 | }
|
24 | 31 | }
|
25 | 32 |
|
26 | 33 | // -- Tests --
|
27 | 34 | #[cfg(test)]
|
28 | 35 | mod tests {
|
29 | 36 | use super::*;
|
| 37 | + const SHELLEY_START_EPOCH: u64 = 208; |
| 38 | + const SHELLEY_SLOTS_PER_EPOCH: u64 = 432_000; |
| 39 | + const BYRON_START_TIMESTAMP: u64 = 1506203091; |
| 40 | + |
| 41 | + fn slot_to_epoch(slot: u64) -> (u64, u64) { |
| 42 | + slot_to_epoch_with_shelley_params(slot, SHELLEY_START_EPOCH, SHELLEY_SLOTS_PER_EPOCH) |
| 43 | + } |
| 44 | + |
| 45 | + fn slot_to_timestamp(slot: u64) -> u64 { |
| 46 | + slot_to_timestamp_with_params(slot, BYRON_START_TIMESTAMP, SHELLEY_START_EPOCH) |
| 47 | + } |
30 | 48 |
|
31 | 49 | #[test]
|
32 | 50 | fn byron_epoch_0() {
|
33 |
| - assert_eq!(0, slot_to_epoch(0)); |
| 51 | + assert_eq!(slot_to_epoch(0), (0, 0)); |
| 52 | + assert_eq!(slot_to_timestamp(0), 1506203091); |
34 | 53 | }
|
35 | 54 |
|
36 | 55 | #[test]
|
37 | 56 | fn byron_epoch_1() {
|
38 |
| - assert_eq!(1, slot_to_epoch(21_600)); |
| 57 | + assert_eq!(slot_to_epoch(21_600), (1, 0)); |
| 58 | + assert_eq!(slot_to_timestamp(21_600), 1506635091); |
39 | 59 | }
|
40 | 60 |
|
41 | 61 | #[test]
|
42 | 62 | fn byron_last_slot() {
|
43 |
| - assert_eq!(slot_to_epoch(4_492_799), 207); |
| 63 | + assert_eq!(slot_to_epoch(4_492_799), (207, 21_599)); |
| 64 | + assert_eq!(slot_to_timestamp(4_492_799), 1596059071); |
44 | 65 | }
|
45 | 66 |
|
46 | 67 | #[test]
|
47 | 68 | fn shelley_first_slot() {
|
48 |
| - assert_eq!(slot_to_epoch(4_492_800), 208); |
| 69 | + assert_eq!(slot_to_epoch(4_492_800), (208, 0)); |
| 70 | + assert_eq!(slot_to_timestamp(4_492_800), 1596059091); |
49 | 71 | }
|
50 | 72 |
|
51 | 73 | #[test]
|
52 | 74 | fn shelley_epoch_209_start() {
|
53 | 75 | // 432_000 slots later
|
54 |
| - assert_eq!(slot_to_epoch(4_492_800 + 432_000), 209); |
55 |
| - } |
56 |
| - |
57 |
| - #[test] |
58 |
| - fn before_transition_boundary() { |
59 |
| - // One slot before Shelley starts |
60 |
| - assert_eq!(slot_to_epoch(4_492_799), 207); |
61 |
| - } |
62 |
| - |
63 |
| - #[test] |
64 |
| - fn after_transition_boundary() { |
65 |
| - // First Shelley slot |
66 |
| - assert_eq!(slot_to_epoch(4_492_800), 208); |
| 76 | + assert_eq!(slot_to_epoch(4_492_800 + 432_000), (209, 0)); |
| 77 | + assert_eq!(slot_to_timestamp(4_492_800 + 432_000), 1596491091); |
67 | 78 | }
|
68 | 79 |
|
69 | 80 | #[test]
|
70 | 81 | fn mainnet_example_from_cexplorer() {
|
71 | 82 | // Slot 98_272_003 maps to epoch 425
|
72 |
| - assert_eq!(slot_to_epoch(98_272_003), 425); |
| 83 | + assert_eq!(slot_to_epoch(98_272_003), (425, 35_203)); |
| 84 | + assert_eq!(slot_to_timestamp(98_272_003), 1689838294); |
73 | 85 | }
|
74 | 86 | }
|
0 commit comments