@@ -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,136 @@ 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 int
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
+ return 1 ;
166
+ }
167
+ } else {
168
+ uint batch_idx = adder -> batch_cnt ++ ;
169
+ uchar * slot = (uchar * )adder -> batch_ptrs [ batch_idx ];
170
+ uchar * p = slot ;
171
+
172
+ /* Fixed size header */
173
+ FD_STORE ( ulong , p , lamports );
174
+ p += sizeof (ulong );
175
+ /* Variable size content */
176
+ adder -> buffered_data .data = p ;
177
+ adder -> buffered_data .data_max = data_sz ;
178
+ p += data_sz ;
179
+ /* Fixed size footer */
180
+ p [0 ] = executable ; p += 1 ;
181
+ fd_memcpy ( p , owner , 32 ); p += 32 ;
182
+ fd_memcpy ( p , pubkey , 32 ); p += 32 ;
183
+
184
+ adder -> batch_sz [ batch_idx ] = (uint )( p - slot );
185
+
186
+ if ( batch_idx + 1 >=FD_BLAKE3_PARA_MAX && data_sz == 0UL ) {
187
+ # if FD_HAS_AVX512
188
+ fd_blake3_lthash_batch16 ( (void const * * )fd_type_pun_const ( adder -> batch_ptrs ), adder -> batch_sz , value -> words );
189
+ # elif FD_HAS_AVX
190
+ fd_blake3_lthash_batch8 ( (void const * * )fd_type_pun_const ( adder -> batch_ptrs ), adder -> batch_sz , value -> words );
191
+ # endif
192
+ adder -> batch_cnt = 0 ;
193
+ fd_lthash_add ( sum , value );
194
+ }
195
+ }
196
+ return 0 ;
197
+ }
198
+
199
+ /* fd_lthash_adder_stream_account_data buffers account data
200
+ into the lthash adder. */
201
+
202
+ static inline int
203
+ fd_lthash_adder_stream_account_data (
204
+ fd_lthash_adder_t * adder ,
205
+ fd_lthash_value_t * sum ,
206
+ uchar const * data ,
207
+ ulong data_sz
208
+ ) {
209
+ fd_lthash_value_t value [1 ];
210
+ fd_lthash_zero ( value );
211
+ /* FIXME opportunities for memcpy hax here */
212
+
213
+ if ( FD_UNLIKELY ( adder -> buffered_account .valid ) ) {
214
+ fd_blake3_append ( adder -> blake , data , data_sz );
215
+ } else {
216
+ fd_memcpy ( adder -> buffered_data .data + adder -> buffered_data .data_sz , data , data_sz );
217
+ }
218
+ adder -> buffered_data .data_sz += data_sz ;
219
+
220
+ if ( FD_LIKELY ( adder -> buffered_data .data_sz == adder -> buffered_data .data_max ) ) {
221
+ if ( adder -> buffered_account .valid ) {
222
+ uchar footer [ 65 ];
223
+ footer [ 0 ] = adder -> buffered_account .executable ;
224
+ memcpy ( footer + 1 , adder -> buffered_account .owner , 32 );
225
+ memcpy ( footer + 33 , adder -> buffered_account .pubkey , 32 );
226
+ fd_blake3_append ( adder -> blake , footer , sizeof (footer ) );
227
+ fd_blake3_fini_2048 ( adder -> blake , value -> bytes );
228
+ fd_lthash_add ( sum , value );
229
+ adder -> buffered_account .valid = 0 ;
230
+ return 1 ;
231
+ } else {
232
+ uint batch_idx = adder -> batch_cnt ;
233
+ if ( batch_idx + 1 >=FD_BLAKE3_PARA_MAX ) {
234
+ # if FD_HAS_AVX512
235
+ fd_blake3_lthash_batch16 ( (void const * * )fd_type_pun_const ( adder -> batch_ptrs ), adder -> batch_sz , value -> words );
236
+ # elif FD_HAS_AVX
237
+ fd_blake3_lthash_batch8 ( (void const * * )fd_type_pun_const ( adder -> batch_ptrs ), adder -> batch_sz , value -> words );
238
+ # endif
239
+ adder -> batch_cnt = 0 ;
240
+ fd_lthash_add ( sum , value );
241
+ }
242
+ }
243
+ }
244
+ return 0 ;
245
+ }
246
+
111
247
/* fd_lthash_adder_push_solana_account wraps fd_lthash_adder_push for
112
248
Solana account inputs. */
113
249
@@ -171,6 +307,7 @@ fd_lthash_adder_push_solana_account(
171
307
}
172
308
}
173
309
310
+
174
311
FD_PROTOTYPES_END
175
312
176
313
#endif /* HEADER_fd_src_ballet_lthash_fd_lthash_adder_h */
0 commit comments