@@ -29,8 +29,6 @@ namespace libbitcoin {
2929namespace database {
3030namespace table {
3131
32- // TODO: merge coinbase bit (saves about 1GB).
33-
3432// / Transaction is a canonical record hash table.
3533struct transaction
3634 : public hash_map<schema::transaction>
@@ -39,13 +37,17 @@ struct transaction
3937 using outs = schema::outs::link;
4038 using out = schema::output::link;
4139 using ix = linkage<schema::index>;
42- using bytes = linkage<schema::size>;
40+ using bytes = linkage<schema::size, sub1(to_bits(schema::size)) >;
4341 using hash_map<schema::transaction>::hashmap;
42+ static constexpr auto offset = bytes::bits;
43+ static_assert (offset < to_bits(bytes::size));
4444
45- static constexpr size_t skip_to_version =
46- schema::bit +
47- bytes::size +
45+ static constexpr size_t skip_to_locktime =
4846 bytes::size +
47+ bytes::size;
48+
49+ static constexpr size_t skip_to_version =
50+ skip_to_locktime +
4951 sizeof (uint32_t );
5052
5153 static constexpr size_t skip_to_ins =
@@ -56,13 +58,31 @@ struct transaction
5658 skip_to_ins +
5759 ix::size;
5860
61+ static constexpr bytes::integer merge (bool is_coinbase,
62+ bytes::integer light) NOEXCEPT
63+ {
64+ BC_ASSERT_MSG (!system::get_right (light, offset), " overflow" );
65+ return system::set_right (light, offset, is_coinbase);
66+ }
67+
68+ static constexpr bool is_coinbase (bytes::integer merged) NOEXCEPT
69+ {
70+ return system::get_right (merged, offset);
71+ }
72+
73+ static constexpr bytes::integer to_light (bytes::integer merged) NOEXCEPT
74+ {
75+ return system::set_right (merged, offset, false );
76+ }
77+
5978 struct record
6079 : public schema::transaction
6180 {
6281 inline bool from_data (reader& source) NOEXCEPT
6382 {
64- coinbase = to_bool (source.read_byte ());
65- light = source.read_little_endian <bytes::integer, bytes::size>();
83+ const auto merged = source.read_little_endian <bytes::integer, bytes::size>();
84+ coinbase = is_coinbase (merged);
85+ light = to_light (merged);
6686 heavy = source.read_little_endian <bytes::integer, bytes::size>();
6787 locktime = source.read_little_endian <uint32_t >();
6888 version = source.read_little_endian <uint32_t >();
@@ -76,8 +96,7 @@ struct transaction
7696
7797 inline bool to_data (finalizer& sink) const NOEXCEPT
7898 {
79- sink.write_byte (to_int<uint8_t >(coinbase));
80- sink.write_little_endian <bytes::integer, bytes::size>(light);
99+ sink.write_little_endian <bytes::integer, bytes::size>(merge (coinbase, light));
81100 sink.write_little_endian <bytes::integer, bytes::size>(heavy);
82101 sink.write_little_endian <uint32_t >(locktime);
83102 sink.write_little_endian <uint32_t >(version);
@@ -103,8 +122,8 @@ struct transaction
103122 }
104123
105124 bool coinbase{};
106- bytes::integer light{}; // tx.serialized_size(false)
107- bytes::integer heavy{}; // tx.serialized_size(true)
125+ bytes::integer light{};
126+ bytes::integer heavy{};
108127 uint32_t locktime{};
109128 uint32_t version{};
110129 ix::integer ins_count{};
@@ -118,12 +137,7 @@ struct transaction
118137 {
119138 inline bool from_data (reader& source) NOEXCEPT
120139 {
121- static constexpr size_t skip_size =
122- schema::bit +
123- bytes::size +
124- bytes::size;
125-
126- source.skip_bytes (skip_size);
140+ source.skip_bytes (skip_to_locktime);
127141 locktime = source.read_little_endian <uint32_t >();
128142 version = source.read_little_endian <uint32_t >();
129143 ins_count = source.read_little_endian <ix::integer, ix::size>();
@@ -148,13 +162,12 @@ struct transaction
148162 inline bool to_data (finalizer& sink) const NOEXCEPT
149163 {
150164 using namespace system ;
151- const auto light = possible_narrow_cast<bytes::integer>(
152- tx.serialized_size (false ));
153- const auto heavy = possible_narrow_cast<bytes::integer>
154- (tx.serialized_size (true ));
155-
156- sink.write_byte (to_int<uint8_t >(tx.is_coinbase ()));
157- sink.write_little_endian <bytes::integer, bytes::size>(light);
165+ const auto coinbase = tx.is_coinbase ();
166+ const auto light_ = tx.serialized_size (false );
167+ const auto heavy_ = tx.serialized_size (true );
168+ const auto light = possible_narrow_cast<bytes::integer>(light_);
169+ const auto heavy = possible_narrow_cast<bytes::integer>(heavy_);
170+ sink.write_little_endian <bytes::integer, bytes::size>(merge (coinbase, light));
158171 sink.write_little_endian <bytes::integer, bytes::size>(heavy);
159172 sink.write_little_endian <uint32_t >(tx.locktime ());
160173 sink.write_little_endian <uint32_t >(tx.version ());
@@ -304,7 +317,7 @@ struct transaction
304317 {
305318 inline bool from_data (reader& source) NOEXCEPT
306319 {
307- coinbase = to_bool (source.read_byte ());
320+ coinbase = is_coinbase (source.read_little_endian <bytes::integer, bytes::size> ());
308321 return source;
309322 }
310323
@@ -316,8 +329,7 @@ struct transaction
316329 {
317330 inline bool from_data (reader& source) NOEXCEPT
318331 {
319- source.skip_byte ();
320- light = source.read_little_endian <bytes::integer, bytes::size>();
332+ light = to_light (source.read_little_endian <bytes::integer, bytes::size>());
321333 heavy = source.read_little_endian <bytes::integer, bytes::size>();
322334 return source;
323335 }
0 commit comments