Line data Source code
1 : #include "fd_sysvar_slot_hashes.h"
2 : #include "fd_sysvar.h"
3 : #include "../fd_system_ids.h"
4 : #include "../fd_accdb_svm.h"
5 :
6 : void
7 : fd_sysvar_slot_hashes_init( fd_bank_t * bank,
8 : fd_accdb_t * accdb,
9 18 : fd_capture_ctx_t * capture_ctx ) {
10 18 : uchar data[ FD_SYSVAR_SLOT_HASHES_BINCODE_SZ ] = {0};
11 18 : fd_sysvar_account_update( bank, accdb, capture_ctx, &fd_sysvar_slot_hashes_id, data, FD_SYSVAR_SLOT_HASHES_BINCODE_SZ );
12 18 : }
13 :
14 : void
15 : fd_sysvar_slot_hashes_update( fd_bank_t * bank,
16 : fd_accdb_t * accdb,
17 5340 : fd_capture_ctx_t * capture_ctx ) {
18 5340 : fd_accdb_svm_update_t update[1];
19 5340 : fd_acc_t acc = fd_accdb_svm_open_rw( bank, accdb, update, &fd_sysvar_slot_hashes_id, 0 );
20 5340 : if( FD_UNLIKELY( !acc.lamports ) ) {
21 : /* Agave initializes a new empty slot_hashes if it doesn't exist */
22 12 : fd_sysvar_slot_hashes_init( bank, accdb, capture_ctx );
23 12 : acc = fd_accdb_svm_open_rw( bank, accdb, update, &fd_sysvar_slot_hashes_id, 0 );
24 12 : if( FD_UNLIKELY( !acc.lamports ) ) {
25 0 : FD_LOG_ERR(( "state is missing slot hashes sysvar" ));
26 0 : }
27 12 : }
28 5340 : if( FD_UNLIKELY( 0!=memcmp( acc.owner, &fd_sysvar_owner_id, sizeof(fd_pubkey_t) ) ) ) {
29 0 : FD_LOG_ERR(( "slot hashes sysvar not owned by sysvar owner" ));
30 0 : }
31 5340 : uchar * data = acc.data;
32 5340 : ulong data_sz = acc.data_len;
33 5340 : if( FD_UNLIKELY( data_sz < FD_SYSVAR_SLOT_HASHES_BINCODE_SZ ) ) {
34 0 : FD_LOG_HEXDUMP_ERR(( "invalid slot hashes sysvar", data, data_sz ));
35 0 : }
36 :
37 5340 : ulong cnt = FD_LOAD( ulong, data );
38 5340 : if( FD_UNLIKELY( cnt > FD_SYSVAR_SLOT_HASHES_CAP ) ) {
39 0 : FD_LOG_HEXDUMP_ERR(( "corrupt slot hashes sysvar", data, data_sz ));
40 0 : }
41 :
42 : /* Search for existing entry with parent_slot */
43 5340 : fd_slot_hash_t * entries = (fd_slot_hash_t *)(data + sizeof(ulong));
44 5340 : int found = 0;
45 400431 : for( ulong i=0UL; i<cnt; i++ ) {
46 395094 : if( entries[i].slot == bank->f.parent_slot ) {
47 3 : fd_memcpy( &entries[i].hash, &bank->f.bank_hash, sizeof(fd_hash_t) );
48 3 : found = 1;
49 3 : break;
50 3 : }
51 395094 : }
52 :
53 5340 : if( !found ) {
54 5337 : ulong keep = fd_ulong_min( cnt, FD_SYSVAR_SLOT_HASHES_CAP - 1UL );
55 5337 : memmove( &entries[1], &entries[0], keep * sizeof(fd_slot_hash_t) );
56 5337 : entries[0].slot = bank->f.parent_slot;
57 5337 : fd_memcpy( &entries[0].hash, &bank->f.bank_hash, sizeof(fd_hash_t) );
58 5337 : FD_STORE( ulong, data, keep + 1UL );
59 5337 : }
60 :
61 5340 : fd_accdb_svm_close_rw( bank, accdb, capture_ctx, &acc, update );
62 5340 : }
63 :
64 : int
65 : fd_sysvar_slot_hashes_validate( uchar const * data,
66 7569 : ulong sz ) {
67 7569 : if( FD_UNLIKELY( sz < sizeof(ulong) ) ) return 0;
68 7563 : ulong cnt = FD_LOAD( ulong, data );
69 7563 : if( FD_UNLIKELY( cnt > FD_SYSVAR_SLOT_HASHES_CAP ) ) return 0;
70 7560 : if( FD_UNLIKELY( sz < sizeof(ulong) + cnt*sizeof(fd_slot_hash_t) ) ) return 0;
71 7554 : return 1;
72 7560 : }
73 :
74 : fd_slot_hashes_t *
75 : fd_sysvar_slot_hashes_view( fd_slot_hashes_t * view,
76 : uchar const * data,
77 153 : ulong sz ) {
78 153 : if( FD_UNLIKELY( !fd_sysvar_slot_hashes_validate( data, sz ) ) ) return NULL;
79 150 : ulong cnt = FD_LOAD( ulong, data );
80 150 : view->elems = (fd_slot_hash_t const *)( data + sizeof(ulong) );
81 150 : view->cnt = cnt;
82 150 : return view;
83 153 : }
|