@@ -89,97 +89,42 @@ code CLASS::set_code(tx_link& tx_fk, const transaction& tx) NOEXCEPT
8989 if (tx.is_empty ())
9090 return error::tx_empty;
9191
92+ using ix = linkage<schema::index>;
9293 const auto & ins = tx.inputs_ptr ();
9394 const auto & ous = tx.outputs_ptr ();
94-
95- using ix = linkage<schema::index>;
9695 const auto txs = possible_narrow_cast<tx_link::integer>(one);
9796 const auto inputs = possible_narrow_cast<ix::integer>(ins->size ());
9897 const auto outputs = possible_narrow_cast<ix::integer>(ous->size ());
9998
100- // Declare outs record for output accumulation.
101- table::outs::record outs{};
102- outs.out_fks .reserve (outputs);
10399
104100 // ========================================================================
105101 const auto scope = store_.get_transactor ();
106102
107- // Allocate single tx record.
103+ // Allocate tx record.
108104 tx_fk = store_.tx .allocate (txs);
109105 if (tx_fk.is_terminal ())
110106 return error::tx_tx_allocate;
111107
112- // Allocate points records.
113- const auto point_fk = store_.point .allocate (inputs);
114- auto point_it = point_fk;
115- if (point_fk.is_terminal ())
116- return error::tx_point_allocate;
117-
118- // Expand synchronizes keys with point allocation.
119- if (!store_.ins .expand (point_fk + inputs))
120- return error::tx_ins_allocate;
108+ // Allocate contiguously and store inputs (script & witness).
109+ input_link in_fk{};
110+ if (!store_.input .put_link (in_fk, table::input::put_ref{ {}, tx }))
111+ return error::tx_input_put;
121112
122- // Commit input and ins|point records.
123- for (const auto & in: *ins)
124- {
125- // TODO: preallocate (requires input sizes).
126- input_link input_fk{};
127- if (!store_.input .put_link (input_fk, table::input::put_ref
128- {
129- {},
130- *in
131- }))
132- {
133- return error::tx_input_put;
134- }
113+ // Allocate contiguously and store outputs (script, w/parent).
114+ output_link out_fk{};
115+ if (!store_.output .put_link (out_fk, table::output::put_ref{ {}, tx_fk, tx }))
116+ return error::tx_output_put;
135117
136- if (!store_.ins .put (point_it++, table::ins::record
137- {
138- {},
139- in->sequence (),
140- input_fk,
141- tx_fk
142- }))
143- {
144- return error::tx_ins_put;
145- }
146- }
118+ // Allocate and contiguously store input links (first + tx.input sizes, w/parent & seq).
119+ point_link ins_fk{};
120+ if (!store_.ins .put_link (ins_fk, table::ins::put_ref{ {}, in_fk, tx_fk, tx }))
121+ return error::tx_ins_put;
147122
148- // TODO: preallocate (requires output sizes).
149- // Commit output records.
150- for (const auto & out: *ous)
151- {
152- output_link output_fk{};
153- if (!store_.output .put_link (output_fk, table::output::put_ref
154- {
155- {},
156- tx_fk,
157- *out
158- }))
159- {
160- return error::tx_output_put;
161- }
162-
163- // Accumulate outputs in order.
164- outs.out_fks .push_back (output_fk);
165- }
166-
167- // Commit accumulated outs.
168- const auto outs_fk = store_.outs .put_link (outs);
169- if (outs_fk.is_terminal ())
123+ // Allocate and contiguously store output links (first + tx.output sizes).
124+ point_link outs_fk{};
125+ if (!store_.outs .put_link (outs_fk, table::outs::put_ref{ {}, out_fk, tx }))
170126 return error::tx_outs_put;
171127
172- // Commit accumulated points.
173- point_it = point_fk;
174- for (const auto & in: *ins)
175- {
176- const auto key = table::point::compose (in->point ());
177- if (!store_.point .put (point_it++, key, table::point::record{}))
178- {
179- return error::tx_point_put;
180- }
181- }
182-
183128 // Create tx record.
184129 // Commit is deferred for point/address index consistency.
185130 if (!store_.tx .set (tx_fk, table::transaction::record_put_ref
@@ -188,38 +133,50 @@ code CLASS::set_code(tx_link& tx_fk, const transaction& tx) NOEXCEPT
188133 tx,
189134 inputs,
190135 outputs,
191- point_fk ,
136+ ins_fk ,
192137 outs_fk
193138 }))
194139 {
195140 return error::tx_tx_set;
196141 }
197142
198- // Commit address index records.
143+ // Commit points (hashmap).
144+ {
145+ // Expand synchronizes keys with ins_fk, entries dropped into same offset.
146+ // Allocate contiguous points (at sequential keys matching ins_fk).
147+ if (!store_.point .expand (ins_fk + inputs))
148+ return error::tx_point_allocate;
149+
150+ // This must be set after tx.set and before tx.commit, since searchable and
151+ // produces an association to tx.link, and is also an integral part of tx.
152+ const auto ptr = store_.point .get_memory ();
153+ for (const auto & in: *ins)
154+ {
155+ if (!store_.point .put (ptr, ins_fk++,
156+ table::point::compose (in->point ()), table::point::record{}))
157+ return error::tx_point_put;
158+ }
159+ }
160+
161+ // Commit address index records (hashmap).
199162 if (address_enabled ())
200163 {
201164 auto ad_fk = store_.address .allocate (outputs);
202165 if (ad_fk.is_terminal ())
203166 return error::tx_address_allocate;
204167
205- auto output = ous->begin ();
206168 const auto ptr = store_.address .get_memory ();
207-
208- for (auto out_fk: outs.out_fks )
169+ for (const auto & output: *ous)
209170 {
210- const auto key = (*output++)->script ().hash ();
211- if (!store_.address .put (ptr, ad_fk++, key, table::address::record
212- {
213- {},
214- out_fk
215- }))
216- {
171+ if (!store_.address .put (ptr, ad_fk++, output->script ().hash (),
172+ table::address::record{ {}, out_fk }))
217173 return error::tx_address_put;
218- }
174+
175+ out_fk.value += output->serialized_size ();
219176 }
220177 }
221178
222- // Commit tx to search.
179+ // Commit tx to search (hashmap) .
223180 // tx.get_hash() assumes cached or is not thread safe.
224181 return store_.tx .commit (tx_fk, tx.get_hash (false )) ?
225182 error::success : error::tx_tx_commit;
0 commit comments