Line data Source code
1 : #include "fd_acc_mgr.h"
2 : #include "../../ballet/base58/fd_base58.h"
3 : #include "../../funk/fd_funk.h"
4 :
5 : fd_account_meta_t const *
6 : fd_funk_get_acc_meta_readonly( fd_funk_t const * funk,
7 : fd_funk_txn_t const * txn,
8 : fd_pubkey_t const * pubkey,
9 : fd_funk_rec_t const ** orec,
10 : int * opt_err,
11 4194 : fd_funk_txn_t const ** txn_out ) {
12 4194 : fd_funk_rec_key_t id = fd_funk_acc_key( pubkey );
13 :
14 : /* When we access this pointer later on in the execution pipeline, we assume that
15 : nothing else will change that account. If the account is writable in the solana txn,
16 : then we copy the data. If the account is read-only, we do not. This is safe because of
17 : the read-write locks that the solana transaction holds on the account. */
18 4194 : for( ; ; ) {
19 :
20 4194 : fd_funk_rec_query_t query[1];
21 4194 : fd_funk_txn_t const * dummy_txn_out[1];
22 4194 : if( !txn_out ) txn_out = dummy_txn_out;
23 4194 : fd_funk_rec_t const * rec = fd_funk_rec_query_try_global( funk, txn, &id, txn_out, query );
24 :
25 4194 : if( FD_UNLIKELY( !rec || !!( rec->flags & FD_FUNK_REC_FLAG_ERASE ) ) ) {
26 3675 : fd_int_store_if( !!opt_err, opt_err, FD_ACC_MGR_ERR_UNKNOWN_ACCOUNT );
27 3675 : return NULL;
28 3675 : }
29 519 : if( NULL != orec )
30 0 : *orec = rec;
31 :
32 519 : void const * raw = fd_funk_val( rec, fd_funk_wksp(funk) );
33 :
34 519 : fd_account_meta_t const * metadata = fd_type_pun_const( raw );
35 519 : if( FD_LIKELY( fd_funk_rec_query_test( query ) == FD_FUNK_SUCCESS ) ) {
36 519 : return metadata;
37 519 : }
38 :
39 519 : }
40 :
41 : /* unreachable */
42 0 : return NULL;
43 4194 : }
44 :
45 : fd_account_meta_t *
46 : fd_funk_get_acc_meta_mutable( fd_funk_t * funk,
47 : fd_funk_txn_t * txn,
48 : fd_pubkey_t const * pubkey,
49 : int do_create,
50 : ulong min_data_sz,
51 : fd_funk_rec_t ** opt_out_rec,
52 : fd_funk_rec_prepare_t * out_prepare,
53 495 : int * opt_err ) {
54 495 : fd_wksp_t * wksp = fd_funk_wksp(funk);
55 495 : fd_funk_rec_key_t id = fd_funk_acc_key( pubkey );
56 :
57 495 : fd_funk_rec_query_t query[1];
58 495 : fd_funk_rec_t * rec = (fd_funk_rec_t *)fd_funk_rec_query_try( funk, txn, &id, query );
59 :
60 495 : int funk_err = 0;
61 :
62 : /* the record does not exist in the current funk transaction */
63 495 : if( !rec ) {
64 : /* clones a record from an ancestor transaction */
65 39 : rec = fd_funk_rec_clone( funk, txn, &id, out_prepare, &funk_err );
66 :
67 39 : if( rec == NULL ) {
68 : /* the record does not exist at all */
69 39 : if( FD_LIKELY( funk_err==FD_FUNK_ERR_KEY ) ) {
70 : /* create a new record */
71 39 : if( do_create ) {
72 39 : rec = fd_funk_rec_prepare( funk, txn, &id, out_prepare, &funk_err );
73 39 : if( rec == NULL ) {
74 : /* Irrecoverable funky internal error [[noreturn]] */
75 0 : FD_LOG_ERR(( "fd_funk_rec_write_prepare(%s) failed (%i-%s)", FD_BASE58_ENC_32_ALLOCA( pubkey->key ), funk_err, fd_funk_strerror( funk_err ) ));
76 0 : }
77 39 : } else {
78 0 : fd_int_store_if( !!opt_err, opt_err, FD_ACC_MGR_ERR_UNKNOWN_ACCOUNT );
79 0 : return NULL;
80 0 : }
81 39 : } else {
82 : /* Irrecoverable funky internal error [[noreturn]] */
83 0 : FD_LOG_ERR(( "fd_funk_rec_write_prepare(%s) failed (%i-%s)", FD_BASE58_ENC_32_ALLOCA( pubkey->key ), funk_err, fd_funk_strerror( funk_err ) ));
84 0 : }
85 39 : }
86 39 : }
87 :
88 495 : ulong sz = sizeof(fd_account_meta_t)+min_data_sz;
89 495 : void * val;
90 495 : if( fd_funk_val_sz( rec ) < sz ) {
91 42 : val = fd_funk_val_truncate(
92 42 : rec,
93 42 : fd_funk_alloc( funk ),
94 42 : wksp,
95 42 : 0UL,
96 42 : sz,
97 42 : &funk_err );
98 42 : if( FD_UNLIKELY( !val ) ) FD_LOG_CRIT(( "fd_funk_val_truncate(sz=%lu) failed (%i-%s)", sz, funk_err, fd_funk_strerror( funk_err ) ));
99 453 : } else {
100 453 : val = fd_funk_val( rec, wksp );
101 453 : }
102 :
103 495 : if (NULL != opt_out_rec) {
104 0 : *opt_out_rec = rec;
105 0 : }
106 :
107 495 : fd_account_meta_t * meta = val;
108 495 : if( do_create && meta->lamports==0UL ) {
109 39 : fd_account_meta_init( meta );
110 39 : }
111 :
112 495 : return meta;
113 495 : }
114 :
115 : FD_FN_CONST char const *
116 0 : fd_acc_mgr_strerror( int err ) {
117 0 : switch( err ) {
118 0 : case FD_ACC_MGR_SUCCESS:
119 0 : return "success";
120 0 : case FD_ACC_MGR_ERR_UNKNOWN_ACCOUNT:
121 0 : return "unknown account";
122 0 : case FD_ACC_MGR_ERR_WRITE_FAILED:
123 0 : return "write failed";
124 0 : case FD_ACC_MGR_ERR_READ_FAILED:
125 0 : return "read failed";
126 0 : default:
127 0 : return "unknown";
128 0 : }
129 0 : }
|