@@ -29,6 +29,22 @@ struct __attribute__((aligned(FD_LTHASH_ADDER_ALIGN))) fd_lthash_adder {
29
29
30
30
uint batch_cnt ;
31
31
32
+ struct {
33
+ uchar pubkey [ 32UL ];
34
+ uchar owner [ 32UL ];
35
+ uchar executable ;
36
+ ulong data_len ;
37
+ int valid ;
38
+ } buffered_account ;
39
+
40
+ struct {
41
+ uchar * data ;
42
+ ulong data_sz ;
43
+ ulong data_max ;
44
+ } buffered_data ;
45
+
46
+ fd_blake3_t blake [1 ];
47
+
32
48
#if FD_LTHASH_ADDER_PARA_MAX > 1
33
49
34
50
uchar batch_data [ FD_LTHASH_ADDER_PARA_MAX * FD_BLAKE3_CHUNK_SZ ]
@@ -66,10 +82,9 @@ fd_lthash_adder_push( fd_lthash_adder_t * adder,
66
82
ulong const batch_threshold = 512UL ;
67
83
fd_lthash_value_t value [1 ];
68
84
if ( FD_UNLIKELY ( input_sz > batch_threshold ) ) {
69
- fd_blake3_t blake [1 ];
70
- fd_blake3_init ( blake );
71
- fd_blake3_append ( blake , input , input_sz );
72
- fd_blake3_fini_2048 ( blake , value -> bytes );
85
+ fd_blake3_init ( adder -> blake );
86
+ fd_blake3_append ( adder -> blake , input , input_sz );
87
+ fd_blake3_fini_2048 ( adder -> blake , value -> bytes );
73
88
fd_lthash_add ( sum , value );
74
89
return ;
75
90
}
@@ -99,15 +114,134 @@ fd_lthash_adder_flush( fd_lthash_adder_t * adder,
99
114
uint batch_cnt = adder -> batch_cnt ;
100
115
for ( uint i = 0U ; i < batch_cnt ; i ++ ) {
101
116
fd_lthash_value_t value [1 ];
102
- fd_blake3_t blake [1 ];
103
- fd_blake3_init ( blake );
104
- fd_blake3_append ( blake , (void const * )adder -> batch_ptrs [ i ], adder -> batch_sz [ i ] );
105
- fd_blake3_fini_2048 ( blake , value -> bytes );
117
+ fd_blake3_init ( adder -> blake );
118
+ fd_blake3_append ( adder -> blake , (void const * )adder -> batch_ptrs [ i ], adder -> batch_sz [ i ] );
119
+ fd_blake3_fini_2048 ( adder -> blake , value -> bytes );
106
120
fd_lthash_add ( sum , value );
107
121
}
108
122
adder -> batch_cnt = 0U ;
109
123
}
110
124
125
+ /* fd_lthash_adder_stream_account_hdr buffers account metadata into
126
+ the lthash adder. */
127
+ static inline void
128
+ fd_lthash_adder_stream_account_hdr (
129
+ fd_lthash_adder_t * adder ,
130
+ fd_lthash_value_t * sum ,
131
+ void const * pubkey ,
132
+ ulong data_sz ,
133
+ ulong lamports ,
134
+ uchar executable ,
135
+ void const * owner
136
+ ) {
137
+ fd_lthash_value_t value [1 ];
138
+
139
+ ulong const static_sz = 0UL ;
140
+ ulong const batch_threshold = 0UL ;
141
+
142
+ adder -> buffered_data .data_sz = 0UL ;
143
+ adder -> buffered_data .data_max = 0UL ;
144
+
145
+ if ( FD_UNLIKELY ( data_sz > batch_threshold - static_sz || /* optimize for small appends */
146
+ FD_BLAKE3_PARA_MAX == 0 ) ) {
147
+ adder -> buffered_account .valid = 1 ;
148
+ adder -> buffered_account .executable = executable ;
149
+ adder -> buffered_account .data_len = data_sz ;
150
+ memcpy ( adder -> buffered_account .pubkey , pubkey , 32UL );
151
+ memcpy ( adder -> buffered_account .owner , owner , 32UL );
152
+ adder -> buffered_data .data_max = data_sz ;
153
+
154
+ fd_blake3_init ( adder -> blake );
155
+ fd_blake3_append ( adder -> blake , & lamports , sizeof (ulong ) );
156
+
157
+ if ( FD_UNLIKELY ( data_sz == 0UL ) ) {
158
+ uchar footer [ 65 ];
159
+ footer [ 0 ] = executable ;
160
+ memcpy ( footer + 1 , owner , 32 );
161
+ memcpy ( footer + 33 , pubkey , 32 );
162
+ fd_blake3_append ( adder -> blake , footer , sizeof (footer ) );
163
+ fd_blake3_fini_2048 ( adder -> blake , value -> bytes );
164
+ fd_lthash_add ( sum , value );
165
+ }
166
+ } else {
167
+ uint batch_idx = adder -> batch_cnt ++ ;
168
+ uchar * slot = (uchar * )adder -> batch_ptrs [ batch_idx ];
169
+ uchar * p = slot ;
170
+
171
+ /* Fixed size header */
172
+ FD_STORE ( ulong , p , lamports );
173
+ p += sizeof (ulong );
174
+ /* Variable size content */
175
+ adder -> buffered_data .data = p ;
176
+ adder -> buffered_data .data_max = data_sz ;
177
+ p += data_sz ;
178
+ /* Fixed size footer */
179
+ p [0 ] = executable ; p += 1 ;
180
+ fd_memcpy ( p , owner , 32 ); p += 32 ;
181
+ fd_memcpy ( p , pubkey , 32 ); p += 32 ;
182
+
183
+ adder -> batch_sz [ batch_idx ] = (uint )( p - slot );
184
+
185
+ if ( batch_idx + 1 >=FD_BLAKE3_PARA_MAX && data_sz == 0UL ) {
186
+ # if FD_HAS_AVX512
187
+ fd_blake3_lthash_batch16 ( (void const * * )fd_type_pun_const ( adder -> batch_ptrs ), adder -> batch_sz , value -> words );
188
+ # elif FD_HAS_AVX
189
+ fd_blake3_lthash_batch8 ( (void const * * )fd_type_pun_const ( adder -> batch_ptrs ), adder -> batch_sz , value -> words );
190
+ # endif
191
+ adder -> batch_cnt = 0 ;
192
+ fd_lthash_add ( sum , value );
193
+ }
194
+ }
195
+ }
196
+
197
+ /* fd_lthash_adder_stream_account_data buffers account data
198
+ into the lthash adder. */
199
+
200
+ static inline int
201
+ fd_lthash_adder_stream_account_data (
202
+ fd_lthash_adder_t * adder ,
203
+ fd_lthash_value_t * sum ,
204
+ uchar const * data ,
205
+ ulong data_sz
206
+ ) {
207
+ fd_lthash_value_t value [1 ];
208
+ fd_lthash_zero ( value );
209
+ /* FIXME opportunities for memcpy hax here */
210
+
211
+ if ( FD_UNLIKELY ( adder -> buffered_account .valid ) ) {
212
+ fd_blake3_append ( adder -> blake , data , data_sz );
213
+ } else {
214
+ fd_memcpy ( adder -> buffered_data .data + adder -> buffered_data .data_sz , data , data_sz );
215
+ }
216
+ adder -> buffered_data .data_sz += data_sz ;
217
+
218
+ if ( FD_LIKELY ( adder -> buffered_data .data_sz == adder -> buffered_data .data_max ) ) {
219
+ if ( adder -> buffered_account .valid ) {
220
+ uchar footer [ 65 ];
221
+ footer [ 0 ] = adder -> buffered_account .executable ;
222
+ memcpy ( footer + 1 , adder -> buffered_account .owner , 32 );
223
+ memcpy ( footer + 33 , adder -> buffered_account .pubkey , 32 );
224
+ fd_blake3_append ( adder -> blake , footer , sizeof (footer ) );
225
+ fd_blake3_fini_2048 ( adder -> blake , value -> bytes );
226
+ fd_lthash_add ( sum , value );
227
+ adder -> buffered_account .valid = 0 ;
228
+ return 1 ;
229
+ } else {
230
+ uint batch_idx = adder -> batch_cnt ;
231
+ if ( batch_idx + 1 >=FD_BLAKE3_PARA_MAX ) {
232
+ # if FD_HAS_AVX512
233
+ fd_blake3_lthash_batch16 ( (void const * * )fd_type_pun_const ( adder -> batch_ptrs ), adder -> batch_sz , value -> words );
234
+ # elif FD_HAS_AVX
235
+ fd_blake3_lthash_batch8 ( (void const * * )fd_type_pun_const ( adder -> batch_ptrs ), adder -> batch_sz , value -> words );
236
+ # endif
237
+ adder -> batch_cnt = 0 ;
238
+ fd_lthash_add ( sum , value );
239
+ }
240
+ }
241
+ }
242
+ return 0 ;
243
+ }
244
+
111
245
/* fd_lthash_adder_push_solana_account wraps fd_lthash_adder_push for
112
246
Solana account inputs. */
113
247
@@ -171,6 +305,7 @@ fd_lthash_adder_push_solana_account(
171
305
}
172
306
}
173
307
308
+
174
309
FD_PROTOTYPES_END
175
310
176
311
#endif /* HEADER_fd_src_ballet_lthash_fd_lthash_adder_h */
0 commit comments