Line data Source code
1 : #include "fd_forks.h"
2 :
3 : #include "../../flamenco/runtime/context/fd_exec_slot_ctx.h"
4 : #include "../../flamenco/runtime/fd_acc_mgr.h"
5 : #include "../../flamenco/runtime/fd_borrowed_account.h"
6 : #include "../../flamenco/runtime/fd_runtime.h"
7 : #include "../../flamenco/runtime/program/fd_program_util.h"
8 : #include "../../flamenco/runtime/program/fd_vote_program.h"
9 :
10 : void *
11 0 : fd_forks_new( void * shmem, ulong max, ulong seed ) {
12 :
13 0 : if( FD_UNLIKELY( !shmem ) ) {
14 0 : FD_LOG_WARNING( ( "NULL mem" ) );
15 0 : return NULL;
16 0 : }
17 :
18 0 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shmem, fd_forks_align() ) ) ) {
19 0 : FD_LOG_WARNING( ( "misaligned mem" ) );
20 0 : return NULL;
21 0 : }
22 :
23 0 : ulong footprint = fd_forks_footprint( max );
24 0 : if( FD_UNLIKELY( !footprint ) ) {
25 0 : FD_LOG_WARNING( ( "bad mem" ) );
26 0 : return NULL;
27 0 : }
28 :
29 0 : fd_memset( shmem, 0, footprint );
30 0 : ulong laddr = (ulong)shmem;
31 :
32 0 : laddr = fd_ulong_align_up( laddr, alignof( fd_forks_t ) );
33 0 : laddr += sizeof( fd_forks_t );
34 :
35 0 : laddr = fd_ulong_align_up( laddr, fd_fork_pool_align() );
36 0 : fd_fork_pool_new( (void *)laddr, max );
37 0 : laddr += fd_fork_pool_footprint( max );
38 :
39 0 : laddr = fd_ulong_align_up( laddr, fd_fork_frontier_align() );
40 0 : fd_fork_frontier_new( (void *)laddr, max, seed );
41 0 : laddr += fd_fork_frontier_footprint( max );
42 :
43 0 : return shmem;
44 0 : }
45 :
46 : fd_forks_t *
47 0 : fd_forks_join( void * shforks ) {
48 :
49 0 : if( FD_UNLIKELY( !shforks ) ) {
50 0 : FD_LOG_WARNING( ( "NULL forks" ) );
51 0 : return NULL;
52 0 : }
53 :
54 0 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shforks, fd_forks_align() ) ) ) {
55 0 : FD_LOG_WARNING( ( "misaligned forks" ) );
56 0 : return NULL;
57 0 : }
58 :
59 0 : ulong laddr = (ulong)shforks;
60 0 : fd_forks_t * forks = (void *)laddr;
61 :
62 0 : laddr = fd_ulong_align_up( laddr, alignof( fd_forks_t ) );
63 0 : laddr += sizeof( fd_forks_t );
64 :
65 0 : laddr = fd_ulong_align_up( laddr, fd_fork_pool_align() );
66 0 : forks->pool = fd_fork_pool_join( (void *)laddr );
67 0 : ulong max = fd_fork_pool_max( forks->pool );
68 0 : laddr += fd_fork_pool_footprint( max );
69 :
70 0 : laddr = fd_ulong_align_up( laddr, fd_fork_frontier_align() );
71 0 : forks->frontier = fd_fork_frontier_join( (void *)laddr );
72 0 : laddr += fd_fork_frontier_footprint( max );
73 :
74 0 : return (fd_forks_t *)shforks;
75 0 : }
76 :
77 : void *
78 0 : fd_forks_leave( fd_forks_t const * forks ) {
79 :
80 0 : if( FD_UNLIKELY( !forks ) ) {
81 0 : FD_LOG_WARNING( ( "NULL forks" ) );
82 0 : return NULL;
83 0 : }
84 :
85 0 : return (void *)forks;
86 0 : }
87 :
88 : void *
89 0 : fd_forks_delete( void * forks ) {
90 :
91 0 : if( FD_UNLIKELY( !forks ) ) {
92 0 : FD_LOG_WARNING( ( "NULL forks" ) );
93 0 : return NULL;
94 0 : }
95 :
96 0 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)forks, fd_forks_align() ) ) ) {
97 0 : FD_LOG_WARNING( ( "misaligned forks" ) );
98 0 : return NULL;
99 0 : }
100 :
101 0 : return forks;
102 0 : }
103 :
104 : fd_fork_t *
105 0 : fd_forks_init( fd_forks_t * forks, ulong slot ) {
106 :
107 0 : if( FD_UNLIKELY( !forks ) ) {
108 0 : FD_LOG_WARNING( ( "NULL forks" ) );
109 0 : return NULL;
110 0 : }
111 :
112 0 : fd_fork_t * fork = fd_fork_pool_ele_acquire( forks->pool );
113 0 : fork->slot = slot;
114 0 : fork->prev = fd_fork_pool_idx_null( forks->pool );
115 0 : fork->lock = 0;
116 0 : fork->end_idx = UINT_MAX;
117 0 : if( FD_UNLIKELY( !fd_fork_frontier_ele_insert( forks->frontier, fork, forks->pool ) ) ) {
118 0 : FD_LOG_WARNING( ( "Failed to insert fork into frontier" ) );
119 0 : }
120 :
121 0 : return fork;
122 0 : }
123 :
124 : fd_fork_t *
125 0 : fd_forks_query( fd_forks_t * forks, ulong slot ) {
126 0 : return fd_fork_frontier_ele_query( forks->frontier, &slot, NULL, forks->pool );
127 0 : }
128 :
129 : fd_fork_t const *
130 0 : fd_forks_query_const( fd_forks_t const * forks, ulong slot ) {
131 0 : return fd_fork_frontier_ele_query_const( forks->frontier, &slot, NULL, forks->pool );
132 0 : }
133 :
134 : // fd_fork_t *
135 : // fd_forks_advance( fd_forks_t * forks,
136 : // fd_fork_t * fork,
137 : // ulong slot,
138 : // fd_funk_t * funk,
139 : // fd_blockstore_t * blockstore,
140 : // fd_funk_t * funk,
141 : // fd_valloc_t valloc ) {
142 : // // Remove slot ctx from frontier
143 : // fd_fork_t * child = fd_fork_frontier_ele_remove( forks->frontier,
144 : // &fork->slot,
145 : // NULL,
146 : // forks->pool );
147 : // child->slot = curr_slot;
148 : // if( FD_UNLIKELY( fd_fork_frontier_ele_query( forks->frontier,
149 : // &curr_slot,
150 : // NULL,
151 : // forks->pool ) ) ) {
152 : // FD_LOG_ERR( ( "invariant violation: child slot %lu was already in the
153 : // frontier", curr_slot ) );
154 : // }
155 : // fd_fork_frontier_ele_insert( forks->frontier, child, forks->pool );
156 : // FD_TEST( fork == child );
157 :
158 : // // fork is advancing
159 : // FD_LOG_DEBUG(( "new block execution - slot: %lu, parent_slot: %lu", curr_slot, parent_slot ));
160 :
161 : // fork->slot_ctx->slot_bank.prev_slot = fork->slot_ctx->slot;
162 : // fork->slot_ctx->slot = curr_slot;
163 :
164 : // fork->slot_ctx.status_cache = status_cache;
165 : // fd_funk_txn_xid_t xid;
166 :
167 : // fd_memcpy( xid.uc, blockhash.uc, sizeof( fd_funk_txn_xid_t));
168 : // xid.ul[0] = fork->slot_ctx.slot_bank.slot;
169 : // /* push a new transaction on the stack */
170 : // fd_funk_start_write( funk );
171 : // fork->slot_ctx.funk_txn = fd_funk_txn_prepare( funk, fork->slot_ctx.funk_txn, &xid, 1 );
172 : // fd_funk_end_write( funk );
173 :
174 : // int res = fd_runtime_publish_old_txns( &fork->slot_ctx, capture_ctx );
175 : // if( res != FD_RUNTIME_EXECUTE_SUCCESS ) {
176 : // FD_LOG_ERR(( "txn publishing failed" ));
177 : // }
178 : // }
179 :
180 : fd_fork_t *
181 : fd_forks_prepare( fd_forks_t const * forks,
182 : ulong parent_slot,
183 : fd_funk_t * funk,
184 : fd_blockstore_t * blockstore,
185 0 : fd_spad_t * runtime_spad ) {
186 :
187 : /* Check the parent block is present in the blockstore and executed. */
188 :
189 0 : if( FD_UNLIKELY( !fd_blockstore_shreds_complete( blockstore, parent_slot ) ) ) {
190 0 : FD_LOG_WARNING( ( "fd_forks_prepare missing parent_slot %lu", parent_slot ) );
191 0 : }
192 :
193 : /* Query for parent_slot in the frontier. */
194 :
195 0 : fd_fork_t * fork = fd_fork_frontier_ele_query( forks->frontier, &parent_slot, NULL, forks->pool );
196 :
197 : /* If the parent block is both present and executed, but isn't in the
198 : frontier, that means this block is starting a new fork and needs to
199 : be added to the frontier. This requires recovering the slot_ctx
200 : as of that parent_slot by executing a funky rollback. */
201 :
202 0 : if( FD_UNLIKELY( !fork ) ) {
203 :
204 : /* Alloc a new slot_ctx */
205 :
206 0 : fork = fd_fork_pool_ele_acquire( forks->pool );
207 0 : fork->prev = fd_fork_pool_idx_null( forks->pool );
208 0 : fork->slot = parent_slot;
209 0 : fork->lock = 1;
210 0 : fork->end_idx = UINT_MAX;
211 :
212 : /* Restore and decode w/ funk */
213 :
214 0 : (void)runtime_spad;
215 0 : (void)funk;
216 : // slot_ctx_restore( fork->slot, funk, blockstore, runtime_spad, slot_ctx );
217 :
218 :
219 : /* Add to frontier */
220 :
221 0 : fd_fork_frontier_ele_insert( forks->frontier, fork, forks->pool );
222 0 : }
223 :
224 0 : return fork;
225 0 : }
226 :
227 : void
228 0 : fd_forks_publish( fd_forks_t * forks, ulong slot ) {
229 0 : fd_fork_t * tail = NULL;
230 0 : fd_fork_t * curr = NULL;
231 :
232 0 : for( fd_fork_frontier_iter_t iter = fd_fork_frontier_iter_init( forks->frontier, forks->pool );
233 0 : !fd_fork_frontier_iter_done( iter, forks->frontier, forks->pool );
234 0 : iter = fd_fork_frontier_iter_next( iter, forks->frontier, forks->pool ) ) {
235 0 : fd_fork_t * fork = fd_fork_frontier_iter_ele( iter, forks->frontier, forks->pool );
236 :
237 : /* Prune any forks not in the ancestry from root.
238 :
239 : Optimize for unlikely because there is usually just one fork. */
240 :
241 0 : if( FD_UNLIKELY( !fork->lock && fork->slot < slot ) ) {
242 0 : if( FD_LIKELY( !curr ) ) {
243 0 : tail = fork;
244 0 : curr = fork;
245 0 : } else {
246 0 : curr->prev = fd_fork_pool_idx( forks->pool, fork );
247 0 : curr = fd_fork_pool_ele( forks->pool, curr->prev );
248 0 : }
249 0 : }
250 0 : }
251 :
252 0 : while( FD_UNLIKELY( tail ) ) {
253 0 : ulong remove = fd_fork_frontier_idx_remove( forks->frontier,
254 0 : &tail->slot,
255 0 : fd_fork_pool_idx_null( forks->pool ),
256 0 : forks->pool );
257 0 : #if FD_FORKS_USE_HANDHOLDING
258 0 : if( FD_UNLIKELY( remove == fd_fork_pool_idx_null( forks->pool ) ) ) {
259 0 : FD_LOG_ERR( ( "failed to remove fork we added to prune." ) );
260 0 : }
261 0 : #endif
262 :
263 : /* pool_idx_release cannot fail given we just removed this from the
264 : frontier directly above. */
265 0 : fd_fork_pool_idx_release( forks->pool, remove );
266 0 : tail = fd_ptr_if( tail->prev != fd_fork_pool_idx_null( forks->pool ),
267 0 : fd_fork_pool_ele( forks->pool, tail->prev ),
268 0 : NULL );
269 0 : }
270 0 : }
271 :
272 : #include <stdio.h>
273 :
274 : void
275 0 : fd_forks_print( fd_forks_t const * forks ) {
276 0 : FD_LOG_NOTICE( ( "\n\n[Forks]" ) );
277 0 : for( fd_fork_frontier_iter_t iter = fd_fork_frontier_iter_init( forks->frontier, forks->pool );
278 0 : !fd_fork_frontier_iter_done( iter, forks->frontier, forks->pool );
279 0 : iter = fd_fork_frontier_iter_next( iter, forks->frontier, forks->pool ) ) {
280 0 : printf( "%lu\n", fd_fork_frontier_iter_ele_const( iter, forks->frontier, forks->pool )->slot );
281 0 : }
282 0 : printf( "\n" );
283 0 : }
|