Line data Source code
1 : #include "fd_sysvar_slot_hashes.h"
2 : #include "fd_sysvar.h"
3 : #include "../fd_system_ids.h"
4 : #include "../../accdb/fd_accdb_sync.h"
5 :
6 : /* FIXME These constants should be header defines */
7 :
8 : void
9 : fd_sysvar_slot_hashes_write( fd_bank_t * bank,
10 : fd_accdb_user_t * accdb,
11 : fd_funk_txn_xid_t const * xid,
12 : fd_capture_ctx_t * capture_ctx,
13 48 : fd_slot_hashes_global_t * slot_hashes_global ) {
14 48 : uchar __attribute__((aligned(FD_SYSVAR_SLOT_HASHES_ALIGN))) enc[ FD_SYSVAR_SLOT_HASHES_BINCODE_SZ ] = {0};
15 48 : fd_bincode_encode_ctx_t ctx = {
16 48 : .data = enc,
17 48 : .dataend = enc + FD_SYSVAR_SLOT_HASHES_BINCODE_SZ,
18 48 : };
19 48 : if( fd_slot_hashes_encode_global( slot_hashes_global, &ctx ) ) {
20 0 : FD_LOG_ERR(("fd_slot_hashes_encode failed"));
21 0 : }
22 48 : fd_sysvar_account_update( bank, accdb, xid, capture_ctx, &fd_sysvar_slot_hashes_id, enc, FD_SYSVAR_SLOT_HASHES_BINCODE_SZ );
23 48 : }
24 :
25 : ulong
26 0 : fd_sysvar_slot_hashes_footprint( ulong slot_hashes_cap ) {
27 0 : return sizeof(fd_slot_hashes_global_t) +
28 0 : deq_fd_slot_hash_t_footprint( slot_hashes_cap ) + deq_fd_slot_hash_t_align();
29 0 : }
30 :
31 : void *
32 : fd_sysvar_slot_hashes_new( void * mem,
33 24 : ulong slot_hashes_cap ) {
34 24 : if( FD_UNLIKELY( !mem ) ) {
35 0 : FD_LOG_ERR(( "Unable to allocate memory for slot hashes" ));
36 0 : }
37 24 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)mem, FD_SYSVAR_SLOT_HASHES_ALIGN ) ) ) {
38 0 : FD_LOG_ERR(( "Memory for slot hashes is not aligned" ));
39 0 : }
40 :
41 24 : fd_slot_hashes_global_t * slot_hashes_global = (fd_slot_hashes_global_t *)mem;
42 :
43 24 : uchar * slot_hash_mem = (uchar*)fd_ulong_align_up( (ulong)((uchar *)mem + sizeof(fd_slot_hashes_global_t)), deq_fd_slot_hash_t_align() );
44 24 : deq_fd_slot_hash_t_new( (void*)slot_hash_mem, slot_hashes_cap );
45 24 : slot_hashes_global->hashes_offset = (ulong)slot_hash_mem - (ulong)slot_hashes_global;
46 :
47 24 : return slot_hashes_global;
48 24 : }
49 :
50 : fd_slot_hashes_global_t *
51 : fd_sysvar_slot_hashes_join( void * shmem,
52 48 : fd_slot_hash_t ** slot_hash ) {
53 48 : fd_slot_hashes_global_t * slot_hashes_global = (fd_slot_hashes_global_t *)shmem;
54 48 : *slot_hash = deq_fd_slot_hash_t_join( (uchar*)shmem + slot_hashes_global->hashes_offset );
55 :
56 48 : return slot_hashes_global;
57 48 : }
58 :
59 : void *
60 : fd_sysvar_slot_hashes_leave( fd_slot_hashes_global_t * slot_hashes_global,
61 48 : fd_slot_hash_t * slot_hash ) {
62 48 : deq_fd_slot_hash_t_leave( slot_hash );
63 :
64 48 : return slot_hashes_global;
65 48 : }
66 :
67 : void *
68 0 : fd_sysvar_slot_hashes_delete( void * mem ) {
69 0 : void * slot_hash_mem = (void *)fd_ulong_align_up( (ulong)((uchar *)mem + sizeof(fd_slot_hashes_global_t)), deq_fd_slot_hash_t_align() );
70 0 : deq_fd_slot_hash_t_delete( slot_hash_mem );
71 :
72 0 : return mem;
73 0 : }
74 :
75 : /* https://github.com/anza-xyz/agave/blob/b11ca828cfc658b93cb86a6c5c70561875abe237/runtime/src/bank.rs#L2283-L2294 */
76 : void
77 : fd_sysvar_slot_hashes_update( fd_bank_t * bank,
78 : fd_accdb_user_t * accdb,
79 : fd_funk_txn_xid_t const * xid,
80 48 : fd_capture_ctx_t * capture_ctx ) {
81 48 : uchar __attribute__((aligned(FD_SYSVAR_SLOT_HASHES_ALIGN))) slot_hashes_mem[FD_SYSVAR_SLOT_HASHES_FOOTPRINT];
82 48 : fd_slot_hashes_global_t * slot_hashes_global = fd_sysvar_slot_hashes_read( accdb, xid, slot_hashes_mem );
83 48 : fd_slot_hash_t * hashes = NULL;
84 48 : if( FD_UNLIKELY( !slot_hashes_global ) ) {
85 : /* Note: Agave's implementation initializes a new slot_hashes if it doesn't already exist (refer to above URL). */
86 24 : slot_hashes_global = fd_sysvar_slot_hashes_new( slot_hashes_mem, FD_SYSVAR_SLOT_HASHES_CAP );
87 24 : }
88 48 : slot_hashes_global = fd_sysvar_slot_hashes_join( slot_hashes_global, &hashes );
89 :
90 48 : uchar found = 0;
91 48 : for( deq_fd_slot_hash_t_iter_t iter = deq_fd_slot_hash_t_iter_init( hashes );
92 156 : !deq_fd_slot_hash_t_iter_done( hashes, iter );
93 108 : iter = deq_fd_slot_hash_t_iter_next( hashes, iter ) ) {
94 108 : fd_slot_hash_t * ele = deq_fd_slot_hash_t_iter_ele( hashes, iter );
95 108 : if( ele->slot == fd_bank_parent_slot_get( bank ) ) {
96 0 : fd_hash_t const * bank_hash = fd_bank_bank_hash_query( bank );
97 0 : memcpy( &ele->hash, bank_hash, sizeof(fd_hash_t) );
98 0 : found = 1;
99 0 : }
100 108 : }
101 :
102 48 : if( !found ) {
103 : // https://github.com/firedancer-io/solana/blob/08a1ef5d785fe58af442b791df6c4e83fe2e7c74/runtime/src/bank.rs#L2371
104 48 : fd_slot_hash_t slot_hash = {
105 48 : .hash = fd_bank_bank_hash_get( bank ), // parent hash?
106 48 : .slot = fd_bank_parent_slot_get( bank ), // parent_slot
107 48 : };
108 :
109 48 : if( deq_fd_slot_hash_t_full( hashes ) )
110 0 : memset( deq_fd_slot_hash_t_pop_tail_nocopy( hashes ), 0, sizeof(fd_slot_hash_t) );
111 :
112 48 : deq_fd_slot_hash_t_push_head( hashes, slot_hash );
113 48 : }
114 :
115 48 : fd_sysvar_slot_hashes_write( bank, accdb, xid, capture_ctx, slot_hashes_global );
116 48 : fd_sysvar_slot_hashes_leave( slot_hashes_global, hashes );
117 48 : }
118 :
119 : fd_slot_hashes_global_t *
120 : fd_sysvar_slot_hashes_read( fd_accdb_user_t * accdb,
121 : fd_funk_txn_xid_t const * xid,
122 48 : uchar * slot_hashes_mem ) {
123 48 : fd_accdb_ro_t ro[1];
124 48 : if( FD_UNLIKELY( !fd_accdb_open_ro( accdb, ro, xid, &fd_sysvar_slot_hashes_id ) ) ) {
125 24 : return NULL;
126 24 : }
127 :
128 : /* This check is needed as a quirk of the fuzzer. If a sysvar account
129 : exists in the accounts database, but doesn't have any lamports,
130 : this means that the account does not exist. This wouldn't happen
131 : in a real execution environment. */
132 24 : if( FD_UNLIKELY( fd_accdb_ref_lamports( ro )==0UL ) ) {
133 0 : fd_accdb_close_ro( accdb, ro );
134 0 : return NULL;
135 0 : }
136 :
137 24 : fd_bincode_decode_ctx_t decode = {
138 24 : .data = fd_accdb_ref_data_const( ro ),
139 24 : .dataend = (uchar *)fd_accdb_ref_data_const( ro ) + fd_accdb_ref_data_sz( ro )
140 24 : };
141 :
142 24 : fd_slot_hashes_global_t * rc = fd_slot_hashes_decode_global( slot_hashes_mem, &decode );
143 24 : fd_accdb_close_ro( accdb, ro );
144 24 : return rc;
145 24 : }
|