@@ -62,39 +62,64 @@ int keccak256_slice(slice s) inline {
6262{-
6363This function reads a specified number of bits from the input slice and stores them in a cell structure,
6464handling data that may exceed the maximum cell capacity in FunC (1023 bits).
65+ Optimized to build cells directly in forward order without double reversal.
6566
6667Parameters:
6768 - in_msg_body: The input slice containing the data to be read
6869 - size: The number of bits to read from the input
6970Returns:
7071 - A tuple containing:
7172 1. A cell containing the read data, potentially spanning multiple cells if the size exceeds 1016 bits
72- 2. A slice containing the remaining unread data from the input
73+ 2. A slice containing the remaining unread data from the input
7374
7475Note:
7576 - The function uses a maximum of 1016 bits per cell (instead of 1023) to ensure byte alignment
7677 - If the input data exceeds 1016 bits, it is split into multiple cells linked by references
78+ - Uses direct forward construction to avoid gas-inefficient double reversal
7779-}
7880(cell, slice) read_and_store_large_data(slice in_msg_body, int size) {
79- (cell chunks, slice remaining) = split_into_reverse_chunks(in_msg_body, size);
80- cell last_cell = null();
81- while (~ cell_null?(chunks)) {
82- slice chunk = chunks.begin_parse();
83- builder cb = begin_cell().store_slice(chunk~load_bits(chunk.slice_bits()));
84- if (~ cell_null?(last_cell)) {
85- cb = cb.store_ref(last_cell);
81+ ;; Collect chunks in order as we build them
82+ tuple chunk_list = empty_tuple();
83+ int total_bits_loaded = 0;
84+ builder current_builder = begin_cell();
85+
86+ while ((~ in_msg_body.slice_empty?()) & (total_bits_loaded < size)) {
87+ int bits_to_load = min(min(in_msg_body.slice_bits(), MAX_BITS - current_builder.builder_bits()), size - total_bits_loaded);
88+ current_builder = current_builder.store_slice(in_msg_body~load_bits(bits_to_load));
89+ total_bits_loaded += bits_to_load;
90+
91+ if ((current_builder.builder_bits() == MAX_BITS) | (size - total_bits_loaded == 0)) {
92+ cell current_chunk = current_builder.end_cell();
93+ chunk_list~tpush(current_chunk);
94+ current_builder = begin_cell();
8695 }
87- last_cell = cb.end_cell();
88- if (chunk.slice_refs_empty?()) {
89- chunks = null();
90- } else {
91- chunks = chunk~load_ref();
96+
97+ if ((in_msg_body.slice_bits() == 0) & (~ in_msg_body.slice_refs_empty?())) {
98+ in_msg_body = in_msg_body~load_ref().begin_parse();
9299 }
93100 }
94-
95- return (last_cell, remaining);
101+
102+ ;; Build forward chain: first chunk → second chunk → third chunk etc
103+ cell result = null();
104+ int chunk_count = chunk_list.tlen();
105+
106+ if (chunk_count > 0) {
107+ ;; Start from the last chunk (no references)
108+ result = chunk_list.at(chunk_count - 1);
109+
110+ ;; Build forward by adding references from earlier chunks to later chunks
111+ int i = chunk_count - 2;
112+ while (i >= 0) {
113+ cell current_chunk = chunk_list.at(i);
114+ result = begin_cell().store_slice(current_chunk.begin_parse()).store_ref(result).end_cell();
115+ i -= 1;
116+ }
117+ }
118+
119+ return (result, in_msg_body);
96120}
97121
122+
98123(int) pubkey_to_eth_address(int x1, int x2) {
99124 slice pubkey = begin_cell()
100125 .store_uint(x1, 256)
0 commit comments