-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathblock.cpp
More file actions
155 lines (125 loc) · 6.72 KB
/
block.cpp
File metadata and controls
155 lines (125 loc) · 6.72 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#include <eosio/chain/block.hpp>
#include <eosio/chain/types.hpp>
namespace eosio { namespace chain {
void additional_block_signatures_extension::reflector_init() {
static_assert( fc::raw::has_feature_reflector_init_on_unpacked_reflected_types,
"additional_block_signatures_extension expects FC to support reflector_init" );
EOS_ASSERT( signatures.size() > 0, ill_formed_additional_block_signatures_extension,
"Additional block signatures extension must contain at least one signature",
);
set<signature_type> unique_sigs;
for( const auto& s : signatures ) {
auto res = unique_sigs.insert( s );
EOS_ASSERT( res.second, ill_formed_additional_block_signatures_extension,
"Signature {s} was repeated in the additional block signatures extension",
("s", s.to_string())
);
}
}
struct transaction_receipt_translator {
bool legacy = true;
std::variant<transaction_id_type, packed_transaction> operator()(const transaction_id_type& tid) const {
return tid;
}
std::variant<transaction_id_type, packed_transaction> operator()(const packed_transaction_v0& ptrx) const {
return packed_transaction(ptrx, legacy);
}
std::variant<transaction_id_type, packed_transaction> operator()(packed_transaction_v0&& ptrx) const {
return packed_transaction(std::move(ptrx), legacy);
}
};
transaction_receipt::transaction_receipt(const transaction_receipt_v0& other, bool legacy)
: transaction_receipt_header(static_cast<const transaction_receipt_header&>(other)),
trx(std::visit(transaction_receipt_translator{legacy}, other.trx))
{}
transaction_receipt::transaction_receipt(transaction_receipt_v0&& other, bool legacy)
: transaction_receipt_header(std::move(static_cast<transaction_receipt_header&>(other))),
trx(std::visit(transaction_receipt_translator{legacy}, std::move(other.trx)))
{}
static flat_multimap<uint16_t, block_extension> validate_and_extract_block_extensions(const extensions_type& block_extensions) {
using decompose_t = block_extension_types::decompose_t;
flat_multimap<uint16_t, block_extension> results;
uint16_t id_type_lower_bound = 0;
for( size_t i = 0; i < block_extensions.size(); ++i ) {
const auto& e = block_extensions[i];
auto id = e.first;
EOS_ASSERT( id >= id_type_lower_bound, invalid_block_extension,
"Block extensions are not in the correct order (ascending id types required)"
);
auto iter = results.emplace(std::piecewise_construct,
std::forward_as_tuple(id),
std::forward_as_tuple()
);
auto match = decompose_t::extract<block_extension>( id, e.second, iter->second );
EOS_ASSERT( match, invalid_block_extension,
"Block extension with id type {id} is not supported",
("id", id)
);
if( match->enforce_unique ) {
EOS_ASSERT( i == 0 || id > id_type_lower_bound, invalid_block_header_extension,
"Block extension with id type {id} is not allowed to repeat",
("id", id)
);
}
id_type_lower_bound = id;
}
return results;
}
flat_multimap<uint16_t, block_extension> signed_block_v0::validate_and_extract_extensions()const {
return validate_and_extract_block_extensions( block_extensions );
}
signed_block::signed_block( const signed_block_v0& other, bool legacy )
: signed_block_header(static_cast<const signed_block_header&>(other)),
prune_state(legacy ? prune_state_type::complete_legacy : prune_state_type::complete),
block_extensions(other.block_extensions)
{
for(const auto& trx : other.transactions) {
transactions.emplace_back(trx, legacy);
}
}
signed_block::signed_block( signed_block_v0&& other, bool legacy )
: signed_block_header(std::move(static_cast<signed_block_header&>(other))),
prune_state(legacy ? prune_state_type::complete_legacy : prune_state_type::complete),
block_extensions(std::move(other.block_extensions))
{
for(auto& trx : other.transactions) {
transactions.emplace_back(std::move(trx), legacy);
}
}
static std::size_t pruned_trx_receipt_packed_size(const packed_transaction& obj, packed_transaction::cf_compression_type segment_compression) {
return obj.maximum_pruned_pack_size(segment_compression);
}
static std::size_t pruned_trx_receipt_packed_size(const transaction_id_type& obj, packed_transaction::cf_compression_type) {
return fc::raw::pack_size(obj);
}
std::size_t transaction_receipt::maximum_pruned_pack_size( packed_transaction::cf_compression_type segment_compression ) const {
return fc::raw::pack_size(*static_cast<const transaction_receipt_header*>(this)) + 1 +
std::visit([&](const auto& obj){ return pruned_trx_receipt_packed_size(obj, segment_compression); }, trx);
}
std::size_t signed_block::maximum_pruned_pack_size( packed_transaction::cf_compression_type segment_compression ) const {
std::size_t result = fc::raw::pack_size(fc::unsigned_int(transactions.size()));
for(const transaction_receipt& r: transactions) {
result += r.maximum_pruned_pack_size( segment_compression );
}
return fc::raw::pack_size(*static_cast<const signed_block_header*>(this)) + fc::raw::pack_size(prune_state) + result + fc::raw::pack_size(block_extensions);
}
flat_multimap<uint16_t, block_extension> signed_block::validate_and_extract_extensions()const {
return validate_and_extract_block_extensions( block_extensions );
}
std::optional<signed_block_v0> signed_block::to_signed_block_v0() const {
if (prune_state != prune_state_type::complete_legacy)
return {};
signed_block_v0 result(*static_cast<const signed_block_header*>(this));
result.block_extensions = this->block_extensions;
auto visitor = overloaded{
[](const transaction_id_type &id) -> transaction_receipt_v0::trx_type { return id; },
[](const packed_transaction &trx) -> transaction_receipt_v0::trx_type {
const auto& legacy = std::get<packed_transaction::prunable_data_type::full_legacy>(trx.get_prunable_data().prunable_data);
return packed_transaction_v0(trx.get_packed_transaction(), legacy.signatures, legacy.packed_context_free_data, trx.get_compression());
}};
for (const transaction_receipt &r : transactions){
result.transactions.emplace_back(transaction_receipt_v0{r, std::visit(visitor, r.trx)});
}
return result;
}
} } /// namespace eosio::chain