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 4188 : fd_funk_txn_t const ** txn_out ) {
12 4188 : 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 4188 : for ( ; ; ) {
19 :
20 4188 : fd_funk_rec_query_t query[1];
21 4188 : fd_funk_txn_t const * dummy_txn_out[1];
22 4188 : if( !txn_out ) txn_out = dummy_txn_out;
23 4188 : fd_funk_rec_t const * rec = fd_funk_rec_query_try_global( funk, txn, &id, txn_out, query );
24 :
25 4188 : 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 513 : if( NULL != orec )
30 513 : *orec = rec;
31 :
32 513 : void const * raw = fd_funk_val( rec, fd_funk_wksp(funk) );
33 :
34 513 : fd_account_meta_t const * metadata = fd_type_pun_const( raw );
35 513 : if( FD_UNLIKELY( metadata->magic != FD_ACCOUNT_META_MAGIC ) ) {
36 0 : fd_int_store_if( !!opt_err, opt_err, FD_ACC_MGR_ERR_WRONG_MAGIC );
37 0 : return NULL;
38 0 : }
39 :
40 513 : if( FD_LIKELY( fd_funk_rec_query_test( query ) == FD_FUNK_SUCCESS ) ) {
41 513 : return metadata;
42 513 : }
43 :
44 513 : }
45 :
46 : /* unreachable */
47 0 : return NULL;
48 4188 : }
49 :
50 : fd_account_meta_t *
51 : fd_funk_get_acc_meta_mutable( fd_funk_t * funk,
52 : fd_funk_txn_t * txn,
53 : fd_pubkey_t const * pubkey,
54 : int do_create,
55 : ulong min_data_sz,
56 : fd_funk_rec_t ** opt_out_rec,
57 : fd_funk_rec_prepare_t * out_prepare,
58 489 : int * opt_err ) {
59 489 : fd_wksp_t * wksp = fd_funk_wksp(funk);
60 489 : fd_funk_rec_key_t id = fd_funk_acc_key( pubkey );
61 :
62 489 : fd_funk_rec_query_t query[1];
63 489 : fd_funk_rec_t * rec = (fd_funk_rec_t *)fd_funk_rec_query_try( funk, txn, &id, query );
64 :
65 489 : int funk_err = 0;
66 :
67 : /* the record does not exist in the current funk transaction */
68 489 : if( !rec ) {
69 : /* clones a record from an ancestor transaction */
70 36 : rec = fd_funk_rec_clone( funk, txn, &id, out_prepare, &funk_err );
71 :
72 36 : if( rec == NULL ) {
73 : /* the record does not exist at all */
74 36 : if( FD_LIKELY( funk_err==FD_FUNK_ERR_KEY ) ) {
75 : /* create a new record */
76 36 : if( do_create ) {
77 36 : rec = fd_funk_rec_prepare( funk, txn, &id, out_prepare, &funk_err );
78 36 : if( rec == NULL ) {
79 : /* Irrecoverable funky internal error [[noreturn]] */
80 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 ) ));
81 0 : }
82 36 : } else {
83 0 : fd_int_store_if( !!opt_err, opt_err, FD_ACC_MGR_ERR_UNKNOWN_ACCOUNT );
84 0 : return NULL;
85 0 : }
86 36 : } else {
87 : /* Irrecoverable funky internal error [[noreturn]] */
88 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 ) ));
89 0 : }
90 36 : }
91 36 : }
92 :
93 489 : ulong sz = sizeof(fd_account_meta_t)+min_data_sz;
94 489 : void * val;
95 489 : if( fd_funk_val_sz( rec ) < sz ) {
96 36 : val = fd_funk_val_truncate(
97 36 : rec,
98 36 : fd_funk_alloc( funk ),
99 36 : wksp,
100 36 : 0UL,
101 36 : sz,
102 36 : &funk_err );
103 36 : if( FD_UNLIKELY( !val ) ) FD_LOG_CRIT(( "fd_funk_val_truncate(sz=%lu) failed (%i-%s)", sz, funk_err, fd_funk_strerror( funk_err ) ));
104 453 : } else {
105 453 : val = fd_funk_val( rec, wksp );
106 453 : }
107 :
108 489 : if (NULL != opt_out_rec) {
109 489 : *opt_out_rec = rec;
110 489 : }
111 :
112 489 : fd_account_meta_t * meta = val;
113 489 : if( do_create && meta->magic==0UL ) {
114 36 : fd_account_meta_init( meta );
115 36 : }
116 489 : if( meta->magic != FD_ACCOUNT_META_MAGIC ) {
117 0 : fd_int_store_if( !!opt_err, opt_err, FD_ACC_MGR_ERR_WRONG_MAGIC );
118 0 : return NULL;
119 0 : }
120 :
121 489 : return meta;
122 489 : }
123 :
124 : FD_FN_CONST char const *
125 0 : fd_acc_mgr_strerror( int err ) {
126 0 : switch( err ) {
127 0 : case FD_ACC_MGR_SUCCESS:
128 0 : return "success";
129 0 : case FD_ACC_MGR_ERR_UNKNOWN_ACCOUNT:
130 0 : return "unknown account";
131 0 : case FD_ACC_MGR_ERR_WRITE_FAILED:
132 0 : return "write failed";
133 0 : case FD_ACC_MGR_ERR_READ_FAILED:
134 0 : return "read failed";
135 0 : case FD_ACC_MGR_ERR_WRONG_MAGIC:
136 0 : return "wrong magic";
137 0 : default:
138 0 : return "unknown";
139 0 : }
140 0 : }
|