Line data Source code
1 : #include "fd_genesis_parse.h"
2 : #include "fd_runtime_const.h"
3 : #include "../../util/bits/fd_bits.h"
4 :
5 : /* Adapted from fd_txn_parse.c */
6 : #define CHECK_INIT( payload, payload_sz, offset ) \
7 0 : uchar const * _payload = (payload); \
8 0 : ulong const _payload_sz = (payload_sz); \
9 0 : ulong const _offset = (offset); \
10 0 : ulong _i = (offset); \
11 0 : (void) _payload; \
12 0 : (void) _offset; \
13 :
14 0 : #define CHECK( cond ) do { \
15 0 : if( FD_UNLIKELY( !(cond) ) ) { \
16 0 : return 0; \
17 0 : } \
18 0 : } while( 0 )
19 :
20 0 : #define CHECK_LEFT( n ) CHECK( (n)<=(_payload_sz-_i) )
21 :
22 0 : #define INC( n ) (_i += (ulong)(n))
23 : #define CUR_OFFSET ((ushort)_i)
24 0 : #define CURSOR (_payload+_i)
25 :
26 :
27 : fd_genesis_t *
28 : fd_genesis_parse( void * genesis_mem,
29 : uchar const * bin,
30 0 : ulong bin_sz ) {
31 0 : FD_SCRATCH_ALLOC_INIT( l, genesis_mem );
32 0 : fd_genesis_t * genesis = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_genesis_t), sizeof(fd_genesis_t) );
33 :
34 0 : CHECK_INIT( bin, bin_sz, 0U );
35 :
36 0 : CHECK_LEFT( 8U ); genesis->creation_time = FD_LOAD( ulong, CURSOR ); INC( 8U );
37 :
38 0 : CHECK_LEFT( 8U ); genesis->accounts_len = FD_LOAD( ulong, CURSOR ); INC( 8U );
39 0 : if( FD_UNLIKELY( genesis->accounts_len>FD_GENESIS_ACCOUNT_MAX_COUNT ) ) {
40 0 : FD_LOG_WARNING(( "genesis accounts length %lu exceeds supported max count %lu", genesis->accounts_len, FD_GENESIS_ACCOUNT_MAX_COUNT ));
41 0 : return NULL;
42 0 : }
43 0 : for( ulong i=0UL; i<genesis->accounts_len; i++ ) {
44 0 : fd_genesis_account_t * account = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_genesis_account_t), sizeof(fd_genesis_account_t) );
45 0 : genesis->accounts_off[ i ] = (uint)((ulong)account-(ulong)genesis);
46 0 : if( FD_UNLIKELY( genesis->accounts_off[ i ] + sizeof(fd_genesis_account_t) > FD_GENESIS_MAX_MESSAGE_SIZE ) ) {
47 0 : FD_LOG_WARNING(( "genesis accounts offset %u exceeds supported max size %lu", genesis->accounts_off[ i ], FD_GENESIS_MAX_MESSAGE_SIZE ));
48 0 : return NULL;
49 0 : }
50 0 : CHECK_LEFT( 32U ); fd_memcpy( account->pubkey, CURSOR, 32U ); INC( 32U );
51 0 : CHECK_LEFT( 8U ); account->meta.lamports = FD_LOAD( ulong, CURSOR ); INC( 8U );
52 0 : CHECK_LEFT( 8U ); account->meta.dlen = (uint)FD_LOAD( ulong, CURSOR ); INC( 8U );
53 0 : if( FD_UNLIKELY( account->meta.dlen>FD_RUNTIME_ACC_SZ_MAX ) ) {
54 0 : FD_LOG_WARNING(( "genesis builtin account data length %u exceeds supported max size %lu", account->meta.dlen, FD_RUNTIME_ACC_SZ_MAX ));
55 0 : return NULL;
56 0 : }
57 0 : if( FD_UNLIKELY( genesis->accounts_off[ i ] + sizeof(fd_genesis_account_t) + account->meta.dlen > FD_GENESIS_MAX_MESSAGE_SIZE ) ) {
58 0 : FD_LOG_WARNING(( "genesis builtin account data length %lu exceeds supported max size %lu", genesis->accounts_off[ i ] + sizeof(fd_genesis_account_t) + account->meta.dlen, FD_GENESIS_MAX_MESSAGE_SIZE ));
59 0 : return NULL;
60 0 : }
61 0 : CHECK_LEFT( account->meta.dlen );
62 0 : uchar * data = FD_SCRATCH_ALLOC_APPEND( l, alignof(uchar), account->meta.dlen );
63 0 : fd_memcpy( data, CURSOR, account->meta.dlen ); INC( account->meta.dlen );
64 0 : CHECK_LEFT( 32U ); fd_memcpy( account->meta.owner, CURSOR, 32U ); INC( 32U );
65 0 : CHECK_LEFT( 1U ); account->meta.executable = FD_LOAD( uchar, CURSOR ); INC( 1U );
66 0 : CHECK_LEFT( 8U ); INC( 8U ); /* don't care about rent epoch */
67 0 : }
68 :
69 0 : CHECK_LEFT( 8U ); genesis->builtin_len = FD_LOAD( ulong, CURSOR ); INC( 8U );
70 0 : if( FD_UNLIKELY( genesis->builtin_len>FD_GENESIS_BUILTIN_MAX_COUNT ) ) {
71 0 : FD_LOG_WARNING(( "genesis builtin length %lu exceeds supported max count %lu", genesis->builtin_len, FD_GENESIS_BUILTIN_MAX_COUNT ));
72 0 : return NULL;
73 0 : }
74 0 : for( ulong i=0UL; i<genesis->builtin_len; i++ ) {
75 : /* The built in accounts are laid out with the data first followed
76 : by the pubkey. */
77 0 : fd_genesis_builtin_t * account = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_genesis_builtin_t), sizeof(fd_genesis_builtin_t) );
78 0 : genesis->builtin_off[ i ] = (uint)((ulong)account-(ulong)genesis);
79 0 : if( FD_UNLIKELY( genesis->builtin_off[ i ] + sizeof(fd_genesis_builtin_t) > FD_GENESIS_MAX_MESSAGE_SIZE ) ) {
80 0 : FD_LOG_WARNING(( "genesis builtin offset %lu exceeds supported max size %lu", genesis->builtin_off[ i ] + sizeof(fd_genesis_builtin_t), FD_GENESIS_MAX_MESSAGE_SIZE ));
81 0 : return NULL;
82 0 : }
83 0 : CHECK_LEFT( 8U ); account->data_len = FD_LOAD( ulong, CURSOR ); INC( 8U );
84 0 : if( FD_UNLIKELY( account->data_len>FD_RUNTIME_ACC_SZ_MAX ) ) {
85 0 : FD_LOG_WARNING(( "genesis builtin account data length %lu exceeds supported max size %lu", account->data_len, FD_RUNTIME_ACC_SZ_MAX ));
86 0 : return NULL;
87 0 : }
88 0 : if( FD_UNLIKELY( genesis->builtin_off[ i ] + sizeof(fd_genesis_builtin_t) + account->data_len > FD_GENESIS_MAX_MESSAGE_SIZE ) ) {
89 0 : FD_LOG_WARNING(( "genesis builtin account data length %lu exceeds supported max size %lu", genesis->builtin_off[ i ] + sizeof(fd_genesis_builtin_t) + account->data_len, FD_GENESIS_MAX_MESSAGE_SIZE ));
90 0 : return NULL;
91 0 : }
92 0 : CHECK_LEFT( account->data_len );
93 0 : uchar * data = FD_SCRATCH_ALLOC_APPEND( l, alignof(uchar), account->data_len );
94 0 : fd_memcpy( data, CURSOR, account->data_len ); INC( account->data_len );
95 :
96 0 : CHECK_LEFT( 32U ); fd_memcpy( account->pubkey, CURSOR, 32U ); INC( 32U );
97 0 : }
98 :
99 0 : genesis->total_sz = (ulong)(FD_SCRATCH_ALLOC_FINI( l, alignof(fd_genesis_t) )) - (ulong)genesis_mem;
100 :
101 0 : CHECK_LEFT( 8U ); ulong rewards_len = FD_LOAD( ulong, CURSOR ); INC( 8U );
102 0 : for( ulong i=0UL; i<rewards_len; i++ ) {
103 0 : CHECK_LEFT( 32U ); INC( 32U ); /* pubkey */
104 0 : CHECK_LEFT( 8U ); INC( 8U ); /* lamports */
105 0 : CHECK_LEFT( 8U ); ulong dlen = FD_LOAD( ulong, CURSOR ); INC( 8U ); /* dlen */
106 0 : CHECK_LEFT( dlen ); INC( dlen ); /* data */
107 0 : CHECK_LEFT( 32U ); INC( 32U ); /* owner */
108 0 : CHECK_LEFT( 1U ); INC( 1U ); /* executable */
109 0 : CHECK_LEFT( 8U ); INC( 8U ); /* rent epoch */
110 0 : }
111 :
112 0 : CHECK_LEFT( 8U ); genesis->poh.ticks_per_slot = FD_LOAD( ulong, CURSOR ); INC( 8U );
113 :
114 0 : CHECK_LEFT( sizeof(ulong) ); INC( sizeof(ulong) ); /* unused */
115 :
116 0 : CHECK_LEFT( 8U ); genesis->poh.tick_duration_secs = FD_LOAD( ulong, CURSOR ); INC( 8U );
117 0 : CHECK_LEFT( 4U ); genesis->poh.tick_duration_ns = FD_LOAD( uint, CURSOR ); INC( 4U );
118 0 : CHECK_LEFT( 1U ); int has_target_tick_count = FD_LOAD( uchar, CURSOR ); INC( 1U );
119 0 : if( has_target_tick_count ) { CHECK_LEFT( 8U ); genesis->poh.target_tick_count = FD_LOAD( ulong, CURSOR ); INC( 8U ); }
120 0 : else genesis->poh.target_tick_count = 0UL;
121 0 : CHECK_LEFT( 1U ); int has_hashes_per_tick = FD_LOAD( uchar, CURSOR ); INC( 1U );
122 0 : if( has_hashes_per_tick ) { CHECK_LEFT( 8U ); genesis->poh.hashes_per_tick = FD_LOAD( ulong, CURSOR ); INC( 8U ); }
123 0 : else genesis->poh.hashes_per_tick = 0UL;
124 :
125 0 : CHECK_LEFT( sizeof(ulong) ); INC( sizeof(ulong) ); /* bakcward compat v23 */
126 :
127 0 : CHECK_LEFT( 8U ); genesis->fee_rate_governor.target_lamports_per_signature = FD_LOAD( ulong, CURSOR ); INC( 8U );
128 0 : CHECK_LEFT( 8U ); genesis->fee_rate_governor.target_signatures_per_slot = FD_LOAD( ulong, CURSOR ); INC( 8U );
129 0 : CHECK_LEFT( 8U ); genesis->fee_rate_governor.min_lamports_per_signature = FD_LOAD( ulong, CURSOR ); INC( 8U );
130 0 : CHECK_LEFT( 8U ); genesis->fee_rate_governor.max_lamports_per_signature = FD_LOAD( ulong, CURSOR ); INC( 8U );
131 0 : CHECK_LEFT( 1U ); genesis->fee_rate_governor.burn_percent = FD_LOAD( uchar, CURSOR ); INC( 1U );
132 :
133 0 : CHECK_LEFT( 8U ); genesis->rent.lamports_per_uint8_year = FD_LOAD( ulong, CURSOR ); INC( 8U );
134 0 : CHECK_LEFT( 8U ); genesis->rent.exemption_threshold = FD_LOAD( double, CURSOR ); INC( 8U );
135 0 : CHECK_LEFT( 1U ); genesis->rent.burn_percent = FD_LOAD( uchar, CURSOR ); INC( 1U );
136 :
137 0 : CHECK_LEFT( 8U ); genesis->inflation.initial = FD_LOAD( double, CURSOR ); INC( 8U );
138 0 : CHECK_LEFT( 8U ); genesis->inflation.terminal = FD_LOAD( double, CURSOR ); INC( 8U );
139 0 : CHECK_LEFT( 8U ); genesis->inflation.taper = FD_LOAD( double, CURSOR ); INC( 8U );
140 0 : CHECK_LEFT( 8U ); genesis->inflation.foundation = FD_LOAD( double, CURSOR ); INC( 8U );
141 0 : CHECK_LEFT( 8U ); genesis->inflation.foundation_term = FD_LOAD( double, CURSOR ); INC( 8U );
142 0 : CHECK_LEFT( 8U ); INC( 8U ); /* unused */
143 :
144 0 : CHECK_LEFT( 8U ); genesis->epoch_schedule.slots_per_epoch = FD_LOAD( ulong, CURSOR ); INC( 8U );
145 0 : CHECK_LEFT( 8U ); genesis->epoch_schedule.leader_schedule_slot_offset = FD_LOAD( ulong, CURSOR ); INC( 8U );
146 0 : CHECK_LEFT( 1U ); genesis->epoch_schedule.warmup = FD_LOAD( uchar, CURSOR ); INC( 1U );
147 0 : CHECK_LEFT( 8U ); genesis->epoch_schedule.first_normal_epoch = FD_LOAD( ulong, CURSOR ); INC( 8U );
148 0 : CHECK_LEFT( 8U ); genesis->epoch_schedule.first_normal_slot = FD_LOAD( ulong, CURSOR ); INC( 8U );
149 :
150 0 : CHECK_LEFT( 4U ); genesis->cluster_type = FD_LOAD( uint, CURSOR ); INC( 4U );
151 :
152 0 : return genesis;
153 0 : }
|