Line data Source code
1 : #include "fd_sysvar_clock.h"
2 : #include "fd_sysvar_epoch_schedule.h"
3 : #include "../fd_system_ids.h"
4 : #include "../sysvar/fd_sysvar.h"
5 :
6 : /* Do all intermediate calculations at nanosecond precision, to mirror
7 : Solana's behavior. */
8 0 : #define NS_IN_S ((long)1e9)
9 :
10 : /* https://github.com/anza-xyz/agave/blob/v2.3.7/runtime/src/bank.rs#L2110-L2117 */
11 : static inline long
12 0 : unix_timestamp_from_genesis( fd_bank_t * bank ) {
13 : /* TODO: genesis_creation_time needs to be a long in the bank. */
14 0 : return fd_long_sat_add(
15 0 : (long)bank->f.genesis_creation_time,
16 0 : (long)( fd_uint128_sat_mul( bank->f.slot, bank->f.slot_params.ns_per_slot ) / NS_IN_S ) );
17 0 : }
18 :
19 : static void
20 : fd_sysvar_clock_write( fd_bank_t * bank,
21 : fd_accdb_t * accdb,
22 : fd_capture_ctx_t * capture_ctx,
23 610 : fd_sol_sysvar_clock_t const * clock ) {
24 610 : fd_sysvar_account_update( bank, accdb, capture_ctx, &fd_sysvar_clock_id, clock, sizeof(fd_sol_sysvar_clock_t) );
25 610 : }
26 :
27 : fd_sol_sysvar_clock_t *
28 : fd_sysvar_clock_read( fd_accdb_t * accdb,
29 : fd_accdb_fork_id_t fork_id,
30 611 : fd_sol_sysvar_clock_t * clock ) {
31 611 : fd_acc_t acc = fd_accdb_read_one( accdb, fork_id, fd_sysvar_clock_id.uc );
32 611 : if( FD_UNLIKELY( !acc.lamports || acc.data_len<sizeof(fd_sol_sysvar_clock_t) ) ) {
33 0 : fd_accdb_unread_one( accdb, &acc );
34 0 : return NULL;
35 0 : }
36 :
37 611 : fd_memcpy( clock, acc.data, sizeof(fd_sol_sysvar_clock_t) );
38 611 : fd_accdb_unread_one( accdb, &acc );
39 611 : return clock;
40 611 : }
41 :
42 : void
43 : fd_sysvar_clock_init( fd_bank_t * bank,
44 : fd_accdb_t * accdb,
45 0 : fd_capture_ctx_t * capture_ctx ) {
46 0 : long timestamp = unix_timestamp_from_genesis( bank );
47 :
48 0 : fd_sol_sysvar_clock_t clock = {
49 0 : .slot = bank->f.slot,
50 0 : .epoch = 0,
51 0 : .epoch_start_timestamp = timestamp,
52 0 : .leader_schedule_epoch = 1,
53 0 : .unix_timestamp = timestamp,
54 0 : };
55 0 : fd_sysvar_clock_write( bank, accdb, capture_ctx, &clock );
56 0 : }
57 :
58 : void
59 : fd_sysvar_clock_update_slot( fd_bank_t * bank,
60 : fd_accdb_t * accdb,
61 611 : fd_capture_ctx_t * capture_ctx ) {
62 611 : fd_sol_sysvar_clock_t clock_[1];
63 611 : fd_sol_sysvar_clock_t * clock = fd_sysvar_clock_read( accdb, bank->accdb_fork_id, clock_ );
64 611 : if( FD_UNLIKELY( !clock ) ) FD_LOG_ERR(( "fd_sysvar_clock_read failed" ));
65 :
66 611 : fd_epoch_schedule_t const * epoch_schedule = &bank->f.epoch_schedule;
67 611 : ulong current_epoch = fd_slot_to_epoch( epoch_schedule, bank->f.slot, NULL );
68 611 : ulong parent_epoch = fd_slot_to_epoch( epoch_schedule, bank->f.parent_slot, NULL );
69 :
70 611 : long epoch_start_timestamp;
71 611 : if( FD_UNLIKELY( !bank->f.slot ) ) epoch_start_timestamp = unix_timestamp_from_genesis( bank );
72 611 : else if( FD_UNLIKELY( parent_epoch!=current_epoch ) ) epoch_start_timestamp = clock->unix_timestamp;
73 583 : else epoch_start_timestamp = clock->epoch_start_timestamp;
74 :
75 611 : *clock = (fd_sol_sysvar_clock_t){
76 611 : .slot = bank->f.slot,
77 611 : .epoch_start_timestamp = epoch_start_timestamp,
78 611 : .epoch = current_epoch,
79 611 : .leader_schedule_epoch = fd_slot_to_leader_schedule_epoch( epoch_schedule, bank->f.slot ),
80 611 : .unix_timestamp = clock->unix_timestamp, /* parent's footer timestamp */
81 611 : };
82 611 : fd_sysvar_clock_write( bank, accdb, capture_ctx, clock );
83 611 : }
|