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 57 : fd_funk_txn_t const ** txn_out ) {
12 57 : 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 57 : for ( ; ; ) {
19 :
20 57 : fd_funk_rec_query_t query[1];
21 57 : fd_funk_txn_t const * dummy_txn_out[1];
22 57 : if( !txn_out ) txn_out = dummy_txn_out;
23 57 : fd_funk_rec_t const * rec = fd_funk_rec_query_try_global( funk, txn, &id, txn_out, query );
24 :
25 57 : if( FD_UNLIKELY( !rec || !!( rec->flags & FD_FUNK_REC_FLAG_ERASE ) ) ) {
26 12 : fd_int_store_if( !!opt_err, opt_err, FD_ACC_MGR_ERR_UNKNOWN_ACCOUNT );
27 12 : return NULL;
28 12 : }
29 45 : if( NULL != orec )
30 15 : *orec = rec;
31 :
32 45 : void const * raw = fd_funk_val( rec, fd_funk_wksp(funk) );
33 :
34 45 : fd_account_meta_t const * metadata = fd_type_pun_const( raw );
35 45 : 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 45 : if( FD_LIKELY( fd_funk_rec_query_test( query ) == FD_FUNK_SUCCESS ) ) {
41 45 : return metadata;
42 45 : }
43 :
44 45 : }
45 :
46 : /* unreachable */
47 0 : return NULL;
48 57 : }
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 30 : int * opt_err ) {
59 30 : fd_wksp_t * wksp = fd_funk_wksp(funk);
60 30 : fd_funk_rec_key_t id = fd_funk_acc_key( pubkey );
61 :
62 30 : fd_funk_rec_query_t query[1];
63 30 : fd_funk_rec_t * rec = (fd_funk_rec_t *)fd_funk_rec_query_try( funk, txn, &id, query );
64 :
65 30 : int funk_err = 0;
66 :
67 : /* the record does not exist in the current funk transaction */
68 30 : if( !rec ) {
69 : /* clones a record from an ancestor transaction */
70 24 : rec = fd_funk_rec_clone( funk, txn, &id, out_prepare, &funk_err );
71 :
72 24 : if( rec == NULL ) {
73 : /* the record does not exist at all */
74 21 : if( FD_LIKELY( funk_err==FD_FUNK_ERR_KEY ) ) {
75 : /* create a new record */
76 21 : if( do_create ) {
77 21 : rec = fd_funk_rec_prepare( funk, txn, &id, out_prepare, &funk_err );
78 21 : 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 21 : } else {
83 0 : fd_int_store_if( !!opt_err, opt_err, FD_ACC_MGR_ERR_UNKNOWN_ACCOUNT );
84 0 : return NULL;
85 0 : }
86 21 : } 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 21 : }
91 24 : }
92 :
93 30 : ulong sz = sizeof(fd_account_meta_t)+min_data_sz;
94 30 : void * val;
95 30 : if( fd_funk_val_sz( rec ) < sz ) {
96 21 : val = fd_funk_val_truncate(
97 21 : rec,
98 21 : fd_funk_alloc( funk ),
99 21 : wksp,
100 21 : 0UL,
101 21 : sz,
102 21 : &funk_err );
103 21 : 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 21 : } else {
105 9 : val = fd_funk_val( rec, wksp );
106 9 : }
107 :
108 30 : if (NULL != opt_out_rec) {
109 30 : *opt_out_rec = rec;
110 30 : }
111 :
112 30 : fd_account_meta_t * meta = val;
113 30 : if( do_create && meta->magic==0UL ) {
114 21 : fd_account_meta_init( meta );
115 21 : }
116 30 : 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 30 : return meta;
122 30 : }
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 : }
|