Line data Source code
1 : #include "fd_accdb_svm.h"
2 : #include "fd_hashes.h"
3 : #include "fd_bank.h"
4 : #include "../accdb/fd_accdb_sync.h"
5 : #include "../capture/fd_capture_ctx.h"
6 :
7 : static void
8 : log_account_change( fd_capture_ctx_t * capture_ctx,
9 : fd_bank_t const * bank,
10 15 : fd_accdb_ro_t * ro ) {
11 15 : if( capture_ctx && capture_ctx->capture_solcap &&
12 15 : bank->f.slot>=capture_ctx->solcap_start_slot ) {
13 0 : fd_solana_account_meta_t solana_meta[1];
14 0 : fd_solana_account_meta_init(
15 0 : solana_meta,
16 0 : fd_accdb_ref_lamports ( ro ),
17 0 : fd_accdb_ref_owner ( ro ),
18 0 : !!fd_accdb_ref_exec_bit( ro )
19 0 : );
20 0 : fd_capture_link_write_account_update(
21 0 : capture_ctx,
22 0 : capture_ctx->current_txn_idx,
23 0 : fd_accdb_ref_address( ro ),
24 0 : solana_meta,
25 0 : bank->f.slot,
26 0 : fd_accdb_ref_data_const( ro ),
27 0 : fd_accdb_ref_data_sz ( ro )
28 0 : );
29 0 : }
30 15 : }
31 :
32 : fd_accdb_rw_t *
33 : fd_accdb_svm_open_rw( fd_accdb_user_t * accdb,
34 : fd_bank_t * bank,
35 : fd_funk_txn_xid_t const * xid,
36 : fd_accdb_rw_t * rw,
37 : fd_accdb_svm_update_t * update,
38 : fd_pubkey_t const * pubkey,
39 : ulong data_max,
40 15 : int flags ) {
41 15 : if( FD_UNLIKELY( !fd_accdb_open_rw( accdb, rw, xid, pubkey, data_max, flags&~FD_ACCDB_FLAG_TRUNCATE ) ) ) {
42 0 : return NULL;
43 0 : }
44 :
45 15 : update->lamports_before = fd_accdb_ref_lamports( rw->ro );
46 :
47 15 : fd_lthash_value_t hash[1];
48 15 : fd_hashes_account_lthash( pubkey, rw->meta, fd_accdb_ref_data_const( rw->ro ), hash );
49 15 : fd_lthash_value_t * bank_lthash = fd_type_pun( fd_bank_lthash_locking_modify( bank ) );
50 15 : fd_lthash_sub( bank_lthash, hash );
51 15 : fd_bank_lthash_end_locking_modify( bank );
52 :
53 15 : return rw;
54 15 : }
55 :
56 : void
57 : fd_accdb_svm_close_rw( fd_accdb_user_t * accdb,
58 : fd_bank_t * bank,
59 : fd_capture_ctx_t * capture_ctx,
60 : fd_accdb_rw_t * rw,
61 15 : fd_accdb_svm_update_t * update ) {
62 :
63 15 : ulong * cap = &bank->f.capitalization;
64 15 : ulong lamports = fd_accdb_ref_lamports( rw->ro );
65 15 : if( lamports > update->lamports_before ) {
66 6 : ulong delta = lamports - update->lamports_before;
67 6 : ulong cap_before = *cap;
68 6 : if( FD_UNLIKELY( __builtin_uaddl_overflow( cap_before, delta, cap ) ) ) {
69 0 : FD_BASE58_ENCODE_32_BYTES( fd_accdb_ref_address( rw->ro ), addr_b58 );
70 0 : FD_LOG_EMERG(( "bank capitalization overflow detected (slot=%lu addr=%s delta=%lu cap_before=%lu)",
71 0 : bank->f.slot, addr_b58, delta, cap_before ));
72 0 : }
73 9 : } else if( lamports < update->lamports_before ) {
74 0 : ulong delta = update->lamports_before - lamports;
75 0 : ulong cap_before = *cap;
76 0 : if( FD_UNLIKELY( __builtin_usubl_overflow( cap_before, delta, cap ) ) ) {
77 0 : FD_BASE58_ENCODE_32_BYTES( fd_accdb_ref_address( rw->ro ), addr_b58 );
78 0 : FD_LOG_EMERG(( "bank capitalization underflow detected (slot=%lu addr=%s delta=%lu cap_before=%lu)",
79 0 : bank->f.slot, addr_b58, delta, cap_before ));
80 0 : }
81 0 : }
82 :
83 15 : fd_lthash_value_t hash[1];
84 15 : fd_hashes_account_lthash( fd_accdb_ref_address( rw->ro ), rw->meta, fd_accdb_ref_data_const( rw->ro ), hash );
85 15 : fd_lthash_value_t * bank_lthash = fd_type_pun( fd_bank_lthash_locking_modify( bank ) );
86 15 : fd_lthash_add( bank_lthash, hash );
87 15 : fd_bank_lthash_end_locking_modify( bank );
88 :
89 15 : log_account_change( capture_ctx, bank, rw->ro );
90 :
91 15 : fd_accdb_close_rw( accdb, rw );
92 15 : }
93 :
94 : void
95 : fd_accdb_svm_credit( fd_accdb_user_t * accdb,
96 : fd_bank_t * bank,
97 : fd_funk_txn_xid_t const * xid,
98 : fd_capture_ctx_t * capture_ctx,
99 : fd_pubkey_t const * pubkey,
100 6 : ulong lamports_add ) {
101 6 : if( FD_UNLIKELY( !lamports_add ) ) return;
102 :
103 6 : fd_accdb_rw_t rw[1];
104 6 : FD_TEST( fd_accdb_open_rw( accdb, rw, xid, pubkey, 0UL, FD_ACCDB_FLAG_CREATE ) );
105 6 : fd_lthash_value_t hash[1];
106 6 : fd_hashes_account_lthash( pubkey, rw->meta, fd_accdb_ref_data_const( rw->ro ), hash );
107 :
108 6 : ulong lamports = fd_accdb_ref_lamports( rw->ro );
109 6 : if( FD_UNLIKELY( __builtin_uaddl_overflow( lamports, lamports_add, &lamports ) ) ) {
110 0 : FD_BASE58_ENCODE_32_BYTES( pubkey->key, addr_b58 );
111 0 : FD_LOG_EMERG(( "integer overflow while crediting %lu lamports to %s (previous balance %lu)",
112 0 : lamports_add, addr_b58, fd_accdb_ref_lamports( rw->ro ) ));
113 0 : }
114 6 : fd_accdb_ref_lamports_set( rw, lamports );
115 :
116 6 : ulong * cap = &bank->f.capitalization;
117 6 : if( FD_UNLIKELY( __builtin_uaddl_overflow( *cap, lamports_add, cap ) ) ) {
118 0 : FD_BASE58_ENCODE_32_BYTES( pubkey->key, addr_b58 );
119 0 : FD_LOG_EMERG(( "bank capitalization overflow detected (slot=%lu addr=%s delta=%lu cap_before=%lu)",
120 0 : bank->f.slot, addr_b58, lamports_add, *cap - lamports_add ));
121 0 : }
122 :
123 6 : fd_hashes_update_lthash( pubkey, rw->meta, hash, bank, capture_ctx );
124 6 : fd_accdb_close_rw( accdb, rw );
125 6 : }
126 :
127 : void
128 : fd_accdb_svm_write( fd_accdb_user_t * accdb,
129 : fd_bank_t * bank,
130 : fd_funk_txn_xid_t const * xid,
131 : fd_capture_ctx_t * capture_ctx,
132 : fd_pubkey_t const * pubkey,
133 : fd_pubkey_t const * owner,
134 : void const * data,
135 : ulong sz,
136 : ulong lamports_min,
137 : int exec_bit,
138 1830 : int flags ) {
139 1830 : fd_accdb_rw_t rw[1];
140 1830 : if( !fd_accdb_open_rw( accdb, rw, xid, pubkey, sz, flags&FD_ACCDB_FLAG_CREATE ) ) {
141 0 : return;
142 0 : }
143 :
144 1830 : fd_lthash_value_t hash[1];
145 1830 : fd_hashes_account_lthash( pubkey, rw->meta, fd_accdb_ref_data_const( rw->ro ), hash );
146 :
147 1830 : ulong lamports = fd_accdb_ref_lamports( rw->ro );
148 1830 : if( FD_UNLIKELY( lamports < lamports_min ) ) {
149 399 : ulong delta = lamports_min - lamports;
150 399 : fd_accdb_ref_lamports_set( rw, lamports_min );
151 :
152 399 : ulong * cap = &bank->f.capitalization;
153 399 : if( FD_UNLIKELY( __builtin_uaddl_overflow( *cap, delta, cap ) ) ) {
154 0 : FD_BASE58_ENCODE_32_BYTES( pubkey->key, addr_b58 );
155 0 : FD_LOG_EMERG(( "bank capitalization overflow detected (slot=%lu addr=%s delta=%lu cap_before=%lu)",
156 0 : bank->f.slot, addr_b58, delta, *cap - delta ));
157 0 : }
158 399 : }
159 :
160 1830 : fd_accdb_ref_owner_set ( rw, owner );
161 1830 : fd_accdb_ref_exec_bit_set( rw, !!exec_bit );
162 1830 : if( !!( flags & FD_ACCDB_FLAG_TRUNCATE ) ||
163 1830 : fd_accdb_ref_data_sz( rw->ro ) < sz ) {
164 1830 : fd_accdb_ref_data_sz_set( accdb, rw, sz, 0 );
165 1830 : }
166 1830 : fd_memcpy( fd_accdb_ref_data( rw ), data, sz );
167 :
168 1830 : fd_hashes_update_lthash( pubkey, rw->meta, hash, bank, capture_ctx );
169 1830 : fd_accdb_close_rw( accdb, rw );
170 1830 : }
171 :
172 : ulong
173 : fd_accdb_svm_remove( fd_accdb_user_t * accdb,
174 : fd_bank_t * bank,
175 : fd_funk_txn_xid_t const * xid,
176 : fd_capture_ctx_t * capture_ctx,
177 78 : fd_pubkey_t const * pubkey ) {
178 78 : fd_accdb_rw_t rw[1];
179 78 : if( !fd_accdb_open_rw( accdb, rw, xid, pubkey, 0UL, 0 ) ) return 0UL;
180 :
181 0 : fd_lthash_value_t hash[1];
182 0 : fd_hashes_account_lthash( pubkey, rw->meta, fd_accdb_ref_data_const( rw->ro ), hash );
183 :
184 0 : ulong lamports = fd_accdb_ref_lamports( rw->ro );
185 0 : bank->f.capitalization -= lamports;
186 0 : fd_accdb_ref_lamports_set( rw, 0UL );
187 :
188 0 : fd_hashes_update_lthash( pubkey, rw->meta, hash, bank, capture_ctx );
189 0 : fd_accdb_close_rw( accdb, rw );
190 0 : return lamports;
191 78 : }
|