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_user_t * accdb,
9 : fd_funk_txn_xid_t const * xid,
10 27 : fd_capture_ctx_t * capture_ctx ) {
11 27 : uchar data[ FD_SYSVAR_SLOT_HASHES_BINCODE_SZ ] = {0};
12 27 : fd_sysvar_account_update( bank, accdb, xid, capture_ctx, &fd_sysvar_slot_hashes_id, data, FD_SYSVAR_SLOT_HASHES_BINCODE_SZ );
13 27 : }
14 :
15 : void
16 : fd_sysvar_slot_hashes_update( fd_bank_t * bank,
17 : fd_accdb_user_t * accdb,
18 : fd_funk_txn_xid_t const * xid,
19 5076 : fd_capture_ctx_t * capture_ctx ) {
20 :
21 5076 : fd_accdb_rw_t rw[1];
22 5076 : fd_accdb_svm_update_t update[1];
23 5076 : if( FD_UNLIKELY( !fd_accdb_svm_open_rw( accdb, bank, xid, rw, update, &fd_sysvar_slot_hashes_id, 0UL, 0 ) ) ) {
24 : /* Agave initializes a new empty slot_hashes if it doesn't exist */
25 21 : fd_sysvar_slot_hashes_init( bank, accdb, xid, capture_ctx );
26 21 : if( FD_UNLIKELY( !fd_accdb_svm_open_rw( accdb, bank, xid, rw, update, &fd_sysvar_slot_hashes_id, 0UL, 0 ) ) ) {
27 0 : FD_LOG_ERR(( "state is missing slot hashes sysvar" ));
28 0 : }
29 21 : }
30 5076 : if( FD_UNLIKELY( 0!=memcmp( fd_accdb_ref_owner( rw->ro ), &fd_sysvar_owner_id, sizeof(fd_pubkey_t) ) ) ) {
31 0 : FD_LOG_ERR(( "slot hashes sysvar not owned by sysvar owner" ));
32 0 : }
33 5076 : uchar * data = fd_accdb_ref_data ( rw );
34 5076 : ulong data_sz = fd_accdb_ref_data_sz( rw->ro );
35 5076 : if( FD_UNLIKELY( data_sz < FD_SYSVAR_SLOT_HASHES_BINCODE_SZ ) ) {
36 0 : FD_LOG_HEXDUMP_ERR(( "invalid slot hashes sysvar", data, data_sz ));
37 0 : }
38 :
39 5076 : ulong cnt = FD_LOAD( ulong, data );
40 5076 : if( FD_UNLIKELY( cnt > FD_SYSVAR_SLOT_HASHES_CAP ) ) {
41 0 : FD_LOG_HEXDUMP_ERR(( "corrupt slot hashes sysvar", data, data_sz ));
42 0 : }
43 :
44 : /* Search for existing entry with parent_slot */
45 5076 : fd_slot_hash_t * entries = (fd_slot_hash_t *)(data + sizeof(ulong));
46 5076 : int found = 0;
47 399210 : for( ulong i=0UL; i<cnt; i++ ) {
48 394137 : if( entries[i].slot == bank->f.parent_slot ) {
49 3 : fd_memcpy( &entries[i].hash, &bank->f.bank_hash, sizeof(fd_hash_t) );
50 3 : found = 1;
51 3 : break;
52 3 : }
53 394137 : }
54 :
55 5076 : if( !found ) {
56 5073 : ulong keep = fd_ulong_min( cnt, FD_SYSVAR_SLOT_HASHES_CAP - 1UL );
57 5073 : memmove( &entries[1], &entries[0], keep * sizeof(fd_slot_hash_t) );
58 5073 : entries[0].slot = bank->f.parent_slot;
59 5073 : fd_memcpy( &entries[0].hash, &bank->f.bank_hash, sizeof(fd_hash_t) );
60 5073 : FD_STORE( ulong, data, keep + 1UL );
61 5073 : }
62 :
63 5076 : fd_accdb_svm_close_rw( accdb, bank, capture_ctx, rw, update );
64 5076 : }
65 :
66 : int
67 : fd_sysvar_slot_hashes_validate( uchar const * data,
68 7122 : ulong sz ) {
69 7122 : if( FD_UNLIKELY( sz < sizeof(ulong) ) ) return 0;
70 7116 : ulong cnt = FD_LOAD( ulong, data );
71 7116 : if( FD_UNLIKELY( cnt > FD_SYSVAR_SLOT_HASHES_CAP ) ) return 0;
72 7113 : if( FD_UNLIKELY( sz < sizeof(ulong) + cnt*sizeof(fd_slot_hash_t) ) ) return 0;
73 7107 : return 1;
74 7113 : }
75 :
76 : fd_slot_hashes_t *
77 : fd_sysvar_slot_hashes_view( fd_slot_hashes_t * view,
78 : uchar const * data,
79 132 : ulong sz ) {
80 132 : if( FD_UNLIKELY( !fd_sysvar_slot_hashes_validate( data, sz ) ) ) return NULL;
81 129 : ulong cnt = FD_LOAD( ulong, data );
82 129 : view->elems = (fd_slot_hash_t const *)( data + sizeof(ulong) );
83 129 : view->cnt = cnt;
84 129 : return view;
85 132 : }
|