Skip to content

Commit 386c416

Browse files
authored
Merge branch 'main' into validate_action_mroot
2 parents ae22ee1 + 5247431 commit 386c416

26 files changed

+170
-97
lines changed

libraries/chain/block_log.cpp

+12-8
Original file line numberDiff line numberDiff line change
@@ -664,10 +664,11 @@ namespace eosio { namespace chain {
664664

665665
signed_block_ptr read_block_by_num(uint32_t block_num) final {
666666
try {
667-
uint64_t pos = get_block_pos(block_num);
667+
auto [ pos, size ] = get_block_position_and_size(block_num);
668668
if (pos != block_log::npos) {
669669
block_file.seek(pos);
670-
return read_block(block_file, block_num);
670+
fc::datastream_mirror ds(block_file, size);
671+
return read_block(ds, block_num);
671672
}
672673
return retry_read_block_by_num(block_num);
673674
}
@@ -804,7 +805,7 @@ namespace eosio { namespace chain {
804805

805806
void reset(const genesis_state& gs, const signed_block_ptr& first_block) override {
806807
this->reset(1, gs, default_initial_version);
807-
this->append(first_block, first_block->calculate_id(), fc::raw::pack(*first_block));
808+
this->append(first_block, first_block->calculate_id(), first_block->packed_signed_block());
808809
}
809810

810811
void reset(const chain_id_type& chain_id, uint32_t first_block_num) override {
@@ -1097,9 +1098,13 @@ namespace eosio { namespace chain {
10971098
}
10981099

10991100
signed_block_ptr retry_read_block_by_num(uint32_t block_num) final {
1100-
auto ds = catalog.ro_stream_for_block(block_num);
1101-
if (ds)
1102-
return read_block(*ds, block_num);
1101+
uint64_t block_size = 0;
1102+
1103+
auto ds = catalog.ro_stream_and_size_for_block(block_num, block_size);
1104+
if (ds) {
1105+
fc::datastream_mirror dsm(*ds, block_size);
1106+
return read_block(dsm, block_num);
1107+
}
11031108
return {};
11041109
}
11051110

@@ -1280,9 +1285,8 @@ namespace eosio { namespace chain {
12801285
}
12811286

12821287
void block_log::append(const signed_block_ptr& b, const block_id_type& id) {
1283-
std::vector<char> packed_block = fc::raw::pack(*b);
12841288
std::lock_guard g(my->mtx);
1285-
my->append(b, id, packed_block);
1289+
my->append(b, id, b->packed_signed_block());
12861290
}
12871291

12881292
void block_log::append(const signed_block_ptr& b, const block_id_type& id, const std::vector<char>& packed_block) {

libraries/chain/block_state.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ block_state::block_state(const block_header_state& bhs,
114114
, cached_trxs(std::move(trx_metas))
115115
, action_mroot(action_mroot)
116116
{
117-
mutable_signed_block_ptr new_block = std::make_shared<signed_block>(signed_block_header{bhs.header});
117+
mutable_block_ptr new_block = signed_block::create_mutable_block(signed_block_header{bhs.header});
118118
new_block->transactions = std::move(trx_receipts);
119119

120120
if( qc ) {
@@ -125,7 +125,7 @@ block_state::block_state(const block_header_state& bhs,
125125

126126
sign(*new_block, block_id, signer, valid_block_signing_authority);
127127

128-
block = std::move(new_block);
128+
block = signed_block::create_signed_block(std::move(new_block));
129129
}
130130

131131
// Used for transition from dpos to Savanna.

libraries/chain/block_state_legacy.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -64,15 +64,15 @@ namespace eosio::chain {
6464
{}
6565

6666
block_state_legacy::block_state_legacy( pending_block_header_state_legacy&& cur,
67-
mutable_signed_block_ptr&& b,
67+
mutable_block_ptr&& b,
6868
deque<transaction_metadata_ptr>&& trx_metas,
6969
const std::optional<digests_t>& action_receipt_digests_savanna,
7070
const protocol_feature_set& pfs,
7171
const validator_t& validator,
7272
const signer_callback_type& signer
7373
)
7474
:block_header_state_legacy( inject_additional_signatures( std::move(cur), *b, pfs, validator, signer ) )
75-
,block( std::move(b) )
75+
,block( signed_block::create_signed_block(std::move(b)) )
7676
,_pub_keys_recovered( true ) // called by produce_block so signature recovery of trxs must have been done
7777
,_cached_trxs( std::move(trx_metas) )
7878
,action_mroot_savanna( action_receipt_digests_savanna ? std::optional<digest_type>(calculate_merkle(*action_receipt_digests_savanna)) : std::nullopt )

libraries/chain/controller.cpp

+5-17
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ struct assembled_block {
231231
block_id_type id;
232232
pending_block_header_state_legacy pending_block_header_state;
233233
deque<transaction_metadata_ptr> trx_metas;
234-
mutable_signed_block_ptr unsigned_block;
234+
mutable_block_ptr unsigned_block;
235235

236236
// if the unsigned_block pre-dates block-signing authorities this may be present.
237237
std::optional<producer_authority_schedule> new_producer_authority_cache;
@@ -728,7 +728,7 @@ struct building_block {
728728
}
729729

730730
// in dpos, we create a signed_block here. In IF mode, we do it later (when we are ready to sign it)
731-
auto block_ptr = std::make_shared<signed_block>(bb.pending_block_header_state.make_block_header(
731+
auto block_ptr = signed_block::create_mutable_block(bb.pending_block_header_state.make_block_header(
732732
transaction_mroot, action_mroot, bb.new_pending_producer_schedule, std::move(new_finalizer_policy),
733733
vector<digest_type>(bb.new_protocol_feature_activations), pfs));
734734

@@ -1567,20 +1567,8 @@ struct controller_impl {
15671567
return irreversible_mode() || bsp->is_valid();
15681568
};
15691569

1570-
using packed_block_future = std::future<std::vector<char>>;
1571-
std::vector<packed_block_future> v;
1572-
if (!irreversible_mode()) {
1573-
v.reserve( branch.size() );
1574-
for( auto bitr = branch.rbegin(); bitr != branch.rend() && should_process(*bitr); ++bitr ) {
1575-
v.emplace_back( post_async_task( thread_pool.get_executor(), [b=(*bitr)->block]() { return fc::raw::pack(*b); } ) );
1576-
}
1577-
}
1578-
auto it = v.begin();
1579-
15801570
for( auto bitr = branch.rbegin(); bitr != branch.rend() && should_process(*bitr); ++bitr ) {
1581-
packed_block_future f;
15821571
if (irreversible_mode()) {
1583-
f = post_async_task( thread_pool.get_executor(), [b=(*bitr)->block]() { return fc::raw::pack(*b); } );
15841572
result = apply_irreversible_block(fork_db, *bitr);
15851573
if (result != controller::apply_blocks_result::complete)
15861574
break;
@@ -1590,7 +1578,7 @@ struct controller_impl {
15901578

15911579
// blog.append could fail due to failures like running out of space.
15921580
// Do it before commit so that in case it throws, DB can be rolled back.
1593-
blog.append( (*bitr)->block, (*bitr)->id(), irreversible_mode() ? f.get() : it++->get() );
1581+
blog.append( (*bitr)->block, (*bitr)->id(), (*bitr)->block->packed_signed_block() );
15941582

15951583
db.commit( (*bitr)->block_num() );
15961584
root_id = (*bitr)->id();
@@ -1659,7 +1647,7 @@ struct controller_impl {
16591647
auto head = std::make_shared<block_state_legacy>();
16601648
static_cast<block_header_state_legacy&>(*head) = genheader;
16611649
head->activated_protocol_features = std::make_shared<protocol_feature_activation_set>(); // no activated protocol features in genesis
1662-
head->block = std::make_shared<signed_block>(genheader.header);
1650+
head->block = signed_block::create_signed_block(signed_block::create_mutable_block(genheader.header));
16631651
chain_head = block_handle{head};
16641652

16651653
db.set_revision( chain_head.block_num() );
@@ -5549,7 +5537,7 @@ signed_block_ptr controller::fetch_block_by_number( uint32_t block_num )const {
55495537

55505538
std::vector<char> controller::fetch_serialized_block_by_number( uint32_t block_num)const { try {
55515539
if (signed_block_ptr b = my->fork_db_fetch_block_on_best_branch_by_num(block_num)) {
5552-
return fc::raw::pack(*b);
5540+
return b->packed_signed_block();
55535541
}
55545542

55555543
return my->blog.read_serialized_block_by_num(block_num);

libraries/chain/deep_mind.cpp

+1-2
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,6 @@ namespace eosio::chain {
9191
{
9292
assert(b);
9393
assert(active_proposer_policy);
94-
auto packed_blk = fc::raw::pack(*b);
9594
auto finality_data = fc::raw::pack(fd);
9695
auto packed_proposer_policy = fc::raw::pack(*active_proposer_policy);
9796
auto packed_finalizer_policy = fc::raw::pack(active_finalizer_policy);
@@ -100,7 +99,7 @@ namespace eosio::chain {
10099
("id", id)
101100
("num", b->block_num())
102101
("lib", lib)
103-
("blk", fc::to_hex(packed_blk))
102+
("blk", fc::to_hex(b->packed_signed_block()))
104103
("fd", fc::to_hex(finality_data))
105104
("pp", fc::to_hex(packed_proposer_policy))
106105
("fp", fc::to_hex(packed_finalizer_policy))

libraries/chain/include/eosio/chain/block.hpp

+37-5
Original file line numberDiff line numberDiff line change
@@ -85,21 +85,28 @@ namespace eosio { namespace chain {
8585

8686
using block_extension = block_extension_types::block_extension_t;
8787

88+
using signed_block_ptr = std::shared_ptr<const signed_block>;
89+
// mutable_block_ptr is built up until it is signed and converted to signed_block_ptr
90+
// mutable_block_ptr is not thread safe and should be moved into signed_block_ptr when complete
91+
using mutable_block_ptr = std::unique_ptr<signed_block>;
92+
8893
/**
8994
*/
9095
struct signed_block : public signed_block_header{
9196
private:
9297
signed_block( const signed_block& ) = default;
98+
explicit signed_block( const signed_block_header& h ):signed_block_header(h){}
9399
public:
94100
signed_block() = default;
95-
explicit signed_block( const signed_block_header& h ):signed_block_header(h){}
96101
signed_block( signed_block&& ) = default;
97102
signed_block& operator=(const signed_block&) = delete;
98103
signed_block& operator=(signed_block&&) = default;
99-
signed_block clone() const { return *this; }
104+
mutable_block_ptr clone() const { return std::unique_ptr<signed_block>(new signed_block(*this)); }
105+
static mutable_block_ptr create_mutable_block(const signed_block_header& h) { return std::unique_ptr<signed_block>(new signed_block(h)); }
106+
static signed_block_ptr create_signed_block(mutable_block_ptr&& b) { b->pack(); return signed_block_ptr{std::move(b)}; }
100107

101108
deque<transaction_receipt> transactions; /// new or generated transactions
102-
extensions_type block_extensions;
109+
extensions_type block_extensions;
103110

104111
flat_multimap<uint16_t, block_extension> validate_and_extract_extensions()const;
105112
std::optional<block_extension> extract_extension(uint16_t extension_id)const;
@@ -108,9 +115,17 @@ namespace eosio { namespace chain {
108115
return std::get<Ext>(*extract_extension(Ext::extension_id()));
109116
}
110117
bool contains_extension(uint16_t extension_id)const;
118+
119+
const bytes& packed_signed_block() const { assert(!packed_block.empty()); return packed_block; }
120+
121+
private:
122+
friend struct block_state;
123+
friend struct block_state_legacy;
124+
template<typename Stream> friend void fc::raw::unpack(Stream& s, eosio::chain::signed_block& v);
125+
void pack() { packed_block = fc::raw::pack( *this ); }
126+
127+
bytes packed_block; // packed this
111128
};
112-
using signed_block_ptr = std::shared_ptr<const signed_block>;
113-
using mutable_signed_block_ptr = std::shared_ptr<signed_block>;
114129

115130
struct producer_confirmation {
116131
block_id_type block_id;
@@ -129,3 +144,20 @@ FC_REFLECT_DERIVED(eosio::chain::transaction_receipt, (eosio::chain::transaction
129144
FC_REFLECT(eosio::chain::additional_block_signatures_extension, (signatures));
130145
FC_REFLECT(eosio::chain::quorum_certificate_extension, (qc));
131146
FC_REFLECT_DERIVED(eosio::chain::signed_block, (eosio::chain::signed_block_header), (transactions)(block_extensions) )
147+
148+
namespace fc::raw {
149+
template <typename Stream>
150+
void unpack(Stream& s, eosio::chain::signed_block& v) {
151+
try {
152+
if constexpr (requires { s.extract_mirror(); }) {
153+
fc::reflector<eosio::chain::signed_block>::visit( fc::raw::detail::unpack_object_visitor<Stream, eosio::chain::signed_block>( v, s ) );
154+
v.packed_block = s.extract_mirror();
155+
} else {
156+
fc::datastream_mirror<Stream> ds(s, sizeof(eosio::chain::signed_block) + 4096);
157+
fc::reflector<eosio::chain::signed_block>::visit( fc::raw::detail::unpack_object_visitor<fc::datastream_mirror<Stream>, eosio::chain::signed_block>( v, ds ) );
158+
v.packed_block = ds.extract_mirror();
159+
}
160+
} FC_RETHROW_EXCEPTIONS(warn, "error unpacking signed_block")
161+
}
162+
}
163+

libraries/chain/include/eosio/chain/block_log.hpp

-4
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,6 @@ namespace eosio { namespace chain {
5858
std::optional<signed_block_header> read_block_header_by_num(uint32_t block_num)const;
5959
std::optional<block_id_type> read_block_id_by_num(uint32_t block_num)const;
6060

61-
signed_block_ptr read_block_by_id(const block_id_type& id)const {
62-
return read_block_by_num(block_header::num_from_id(id));
63-
}
64-
6561
/**
6662
* Return offset of block in file, or block_log::npos if it does not exist.
6763
*/

libraries/chain/include/eosio/chain/block_state_legacy.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ namespace eosio::chain {
2121
);
2222

2323
block_state_legacy( pending_block_header_state_legacy&& cur,
24-
mutable_signed_block_ptr&& b, // unsigned block
24+
mutable_block_ptr&& b, // unsigned block
2525
deque<transaction_metadata_ptr>&& trx_metas,
2626
const std::optional<digests_t>& action_receipt_digests_savanna,
2727
const protocol_feature_set& pfs,

libraries/chain/transaction_context.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ namespace eosio::chain {
6464

6565
auto sw = executed_action_receipts.store_which();
6666
executed_action_receipts = action_digests_t{sw};
67-
bill_to_accounts.clear();
67+
// bill_to_accounts should only be updated in init(), not updated during transaction execution
6868
validate_ram_usage.clear();
6969
}
7070

libraries/libfc/include/fc/io/datastream.hpp

+34
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,40 @@ class datastream<Container, typename std::enable_if_t<(std::is_same_v<std::vecto
176176
const Container& storage() const { return _container; }
177177
};
178178

179+
/**
180+
* Datastream wrapper that creates a copy of the datastream data read. After reading
181+
* the data is available via extract_mirror()
182+
* @tparam DataStream datastream to wrap
183+
*/
184+
template <typename DataStream>
185+
class datastream_mirror {
186+
public:
187+
explicit datastream_mirror( DataStream& ds, size_t reserve = 0 ) : ds(ds) {
188+
mirror.reserve(reserve);
189+
}
190+
191+
void skip( size_t s ) { ds.skip(s); }
192+
bool read( char* d, size_t s ) {
193+
if (ds.read(d, s)) {
194+
auto size = mirror.size();
195+
if (mirror.capacity() < size + s)
196+
mirror.reserve(std::bit_ceil(size + s));
197+
mirror.resize(size + s);
198+
memcpy(mirror.data() + size, d, s);
199+
return true;
200+
}
201+
return false;
202+
}
203+
204+
bool get( unsigned char& c ) { return read(&c, 1); }
205+
bool get( char& c ) { return read(&c, 1); }
206+
207+
std::vector<char> extract_mirror() { return std::move(mirror); }
208+
209+
private:
210+
DataStream& ds;
211+
std::vector<char> mirror;
212+
};
179213

180214

181215
template<typename ST>

libraries/libfc/include/fc/io/raw_fwd.hpp

+6
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@
1313
#include <variant>
1414
#include <filesystem>
1515

16+
namespace eosio::chain {
17+
struct signed_block;
18+
}
19+
1620
namespace fc {
1721
class time_point;
1822
class time_point_sec;
@@ -32,6 +36,8 @@ namespace fc {
3236
template<typename T>
3337
inline size_t pack_size( const T& v );
3438

39+
template <typename Stream> void unpack(Stream& s, eosio::chain::signed_block& v);
40+
3541
template<typename Stream, typename Storage> inline void pack( Stream& s, const fc::fixed_string<Storage>& u );
3642
template<typename Stream, typename Storage> inline void unpack( Stream& s, fc::fixed_string<Storage>& u );
3743

plugins/net_plugin/net_plugin.cpp

+5-2
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <fc/network/message_buffer.hpp>
1616
#include <fc/io/json.hpp>
1717
#include <fc/io/raw.hpp>
18+
#include <fc/io/datastream.hpp>
1819
#include <fc/variant_object.hpp>
1920
#include <fc/crypto/rand.hpp>
2021
#include <fc/exception/exception.hpp>
@@ -3190,8 +3191,10 @@ namespace eosio {
31903191
return true;
31913192
}
31923193

3193-
auto ds = pending_message_buffer.create_datastream();
3194-
fc::raw::unpack( ds, which );
3194+
auto mb_ds = pending_message_buffer.create_datastream();
3195+
fc::raw::unpack( mb_ds, which );
3196+
3197+
fc::datastream_mirror ds(mb_ds, message_length);
31953198
shared_ptr<signed_block> ptr = std::make_shared<signed_block>();
31963199
fc::raw::unpack( ds, *ptr );
31973200

plugins/test_control_plugin/test_control_plugin.cpp

+4-3
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ void test_control_plugin_impl::swap_action_in_block(const chain::signed_block_pt
126126
return;
127127
}
128128

129-
auto copy_b = std::make_shared<chain::signed_block>(b->clone());
129+
auto copy_b = b->clone();
130130
copy_b->previous = b->calculate_id();
131131
copy_b->block_extensions.clear(); // remove QC extension since header will claim same as previous block
132132
copy_b->timestamp = b->timestamp.next();
@@ -159,12 +159,13 @@ void test_control_plugin_impl::swap_action_in_block(const chain::signed_block_pt
159159
copy_b->transaction_mroot = chain::calculate_merkle( std::move(trx_digests) );
160160
// Re-sign the block
161161
copy_b->producer_signature = _swap_on_options.blk_priv_key.sign(copy_b->calculate_id());
162+
auto copy_b_signed = signed_block::create_signed_block(std::move(copy_b));
162163

163164
// will be processed on the next start_block if is_new_best_head
164-
const auto&[add_result, bh] = _chain.accept_block(copy_b->calculate_id(), copy_b);
165+
const auto&[add_result, bh] = _chain.accept_block(copy_b_signed->calculate_id(), copy_b_signed);
165166
ilog("Swapped action ${f} to ${t}, add_result ${a}, block ${bn}",
166167
("f", _swap_on_options.from)("t", _swap_on_options.to)("a", add_result)("bn", bh ? bh->block_num() : 0));
167-
app().find_plugin<net_plugin>()->broadcast_block(copy_b, copy_b->calculate_id());
168+
app().find_plugin<net_plugin>()->broadcast_block(copy_b_signed, copy_b_signed->calculate_id());
168169
if (_swap_on_options.shutdown)
169170
app().quit();
170171
reset_swap_action();

0 commit comments

Comments
 (0)