Skip to content

Commit a83c8e3

Browse files
committed
allow only read-only access to state DB for consumers outside of the chain library
Currently an exception is made to the deprecated history_plugin until either that plugin is removed or redesigned to use its own independent chainbase DB rather than piggybacking off the main state DB.
1 parent 56f6347 commit a83c8e3

15 files changed

+78
-52
lines changed

contracts/eosio.bios/eosio.bios.abi

+32
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,28 @@
5353
{"name":"accounts", "type":"permission_level_weight[]"},
5454
{"name":"waits", "type":"wait_weight[]"}
5555
]
56+
},{
57+
"name": "blockchain_parameters",
58+
"base": "",
59+
"fields": [
60+
{"name":"max_block_net_usage", "type":"uint64"},
61+
{"name":"target_block_net_usage_pct", "type":"uint32"},
62+
{"name":"max_transaction_net_usage", "type":"uint32"},
63+
{"name":"base_per_transaction_net_usage", "type":"uint32"},
64+
{"name":"net_usage_leeway", "type":"uint32"},
65+
{"name":"context_free_discount_net_usage_num", "type":"uint32"},
66+
{"name":"context_free_discount_net_usage_den", "type":"uint32"},
67+
{"name":"max_block_cpu_usage", "type":"uint32"},
68+
{"name":"target_block_cpu_usage_pct", "type":"uint32"},
69+
{"name":"max_transaction_cpu_usage", "type":"uint32"},
70+
{"name":"min_transaction_cpu_usage", "type":"uint32"},
71+
{"name":"max_transaction_lifetime", "type":"uint32"},
72+
{"name":"deferred_trx_expiration_window", "type":"uint32"},
73+
{"name":"max_transaction_delay", "type":"uint32"},
74+
{"name":"max_inline_action_size", "type":"uint32"},
75+
{"name":"max_inline_action_depth", "type":"uint16"},
76+
{"name":"max_authority_depth", "type":"uint16"}
77+
]
5678
},{
5779
"name": "newaccount",
5880
"base": "",
@@ -160,6 +182,12 @@
160182
"fields": [
161183
{"name":"schedule", "type":"producer_key[]"}
162184
]
185+
},{
186+
"name": "setparams",
187+
"base": "",
188+
"fields": [
189+
{"name":"params", "type":"blockchain_parameters"}
190+
]
163191
},{
164192
"name": "require_auth",
165193
"base": "",
@@ -219,6 +247,10 @@
219247
"name": "setprods",
220248
"type": "set_producers",
221249
"ricardian_contract": ""
250+
},{
251+
"name": "setparams",
252+
"type": "setparams",
253+
"ricardian_contract": ""
222254
},{
223255
"name": "reqauth",
224256
"type": "require_auth",

contracts/eosio.bios/eosio.bios.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
#include <eosio.bios/eosio.bios.hpp>
22

3-
EOSIO_ABI( eosio::bios, (setpriv)(setalimits)(setglimits)(setprods)(reqauth) )
3+
EOSIO_ABI( eosio::bios, (setpriv)(setalimits)(setglimits)(setprods)(setparams)(reqauth) )

contracts/eosio.bios/eosio.bios.hpp

+5
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ namespace eosio {
3434
set_proposed_producers(buffer, size);
3535
}
3636

37+
void setparams( const eosio::blockchain_parameters& params ) {
38+
require_auth( _self );
39+
set_blockchain_parameters( params );
40+
}
41+
3742
void reqauth( action_name from ) {
3843
require_auth( from );
3944
}

libraries/chain/apply_context.cpp

+3-4
Original file line numberDiff line numberDiff line change
@@ -272,8 +272,7 @@ void apply_context::schedule_deferred_transaction( const uint128_t& sender_id, a
272272
}
273273

274274
uint32_t trx_size = 0;
275-
auto& d = control.db();
276-
if ( auto ptr = d.find<generated_transaction_object,by_sender_id>(boost::make_tuple(receiver, sender_id)) ) {
275+
if ( auto ptr = db.find<generated_transaction_object,by_sender_id>(boost::make_tuple(receiver, sender_id)) ) {
277276
EOS_ASSERT( replace_existing, deferred_tx_duplicate, "deferred transaction with the same sender_id and payer already exists" );
278277

279278
// TODO: Remove the following subjective check when the deferred trx replacement RAM bug has been fixed with a hard fork.
@@ -283,7 +282,7 @@ void apply_context::schedule_deferred_transaction( const uint128_t& sender_id, a
283282
// TODO: The logic of the next line needs to be incorporated into the next hard fork.
284283
// add_ram_usage( ptr->payer, -(config::billable_size_v<generated_transaction_object> + ptr->packed_trx.size()) );
285284

286-
d.modify<generated_transaction_object>( *ptr, [&]( auto& gtx ) {
285+
db.modify<generated_transaction_object>( *ptr, [&]( auto& gtx ) {
287286
gtx.sender = receiver;
288287
gtx.sender_id = sender_id;
289288
gtx.payer = payer;
@@ -294,7 +293,7 @@ void apply_context::schedule_deferred_transaction( const uint128_t& sender_id, a
294293
trx_size = gtx.set( trx );
295294
});
296295
} else {
297-
d.create<generated_transaction_object>( [&]( auto& gtx ) {
296+
db.create<generated_transaction_object>( [&]( auto& gtx ) {
298297
gtx.trx_id = trx.id();
299298
gtx.sender = receiver;
300299
gtx.sender_id = sender_id;

libraries/chain/controller.cpp

+5-3
Original file line numberDiff line numberDiff line change
@@ -1051,7 +1051,7 @@ struct controller_impl {
10511051
// on replay irreversible is not emitted by fork database, so emit it explicitly here
10521052
if( s == controller::block_status::irreversible )
10531053
emit( self.irreversible_block, new_header_state );
1054-
1054+
10551055
} FC_LOG_AND_RETHROW( )
10561056
}
10571057

@@ -1399,9 +1399,11 @@ void controller::startup() {
13991399
my->init();
14001400
}
14011401

1402-
chainbase::database& controller::db()const { return my->db; }
1402+
const chainbase::database& controller::db()const { return my->db; }
1403+
1404+
chainbase::database& controller::mutable_db()const { return my->db; }
14031405

1404-
fork_database& controller::fork_db()const { return my->fork_db; }
1406+
const fork_database& controller::fork_db()const { return my->fork_db; }
14051407

14061408

14071409
void controller::start_block( block_timestamp_type when, uint16_t confirm_block_count) {

libraries/chain/include/eosio/chain/apply_context.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,7 @@ class apply_context {
453453
public:
454454
apply_context(controller& con, transaction_context& trx_ctx, const action& a, uint32_t depth=0)
455455
:control(con)
456-
,db(con.db())
456+
,db(con.mutable_db())
457457
,trx_context(trx_ctx)
458458
,act(a)
459459
,receiver(act.account)

libraries/chain/include/eosio/chain/controller.hpp

+6-2
Original file line numberDiff line numberDiff line change
@@ -146,9 +146,9 @@ namespace eosio { namespace chain {
146146
*/
147147
void push_confirmation( const header_confirmation& c );
148148

149-
chainbase::database& db()const;
149+
const chainbase::database& db()const;
150150

151-
fork_database& fork_db()const;
151+
const fork_database& fork_db()const;
152152

153153
const account_object& get_account( account_name n )const;
154154
const global_property_object& get_global_properties()const;
@@ -286,6 +286,10 @@ namespace eosio { namespace chain {
286286
}
287287

288288
private:
289+
friend class apply_context;
290+
friend class transaction_context;
291+
292+
chainbase::database& mutable_db()const;
289293

290294
std::unique_ptr<controller_impl> my;
291295

libraries/chain/transaction_context.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ namespace eosio { namespace chain {
2323
,pseudo_start(s)
2424
{
2525
if (!c.skip_db_sessions()) {
26-
undo_session = c.db().start_undo_session(true);
26+
undo_session = c.mutable_db().start_undo_session(true);
2727
}
2828
trace->id = id;
2929
trace->block_num = c.pending_block_state()->block_num;
@@ -451,7 +451,7 @@ namespace eosio { namespace chain {
451451
auto first_auth = trx.first_authorizor();
452452

453453
uint32_t trx_size = 0;
454-
const auto& cgto = control.db().create<generated_transaction_object>( [&]( auto& gto ) {
454+
const auto& cgto = control.mutable_db().create<generated_transaction_object>( [&]( auto& gto ) {
455455
gto.trx_id = id;
456456
gto.payer = first_auth;
457457
gto.sender = account_name(); /// delayed transactions have no sender
@@ -467,7 +467,7 @@ namespace eosio { namespace chain {
467467

468468
void transaction_context::record_transaction( const transaction_id_type& id, fc::time_point_sec expire ) {
469469
try {
470-
control.db().create<transaction_object>([&](transaction_object& transaction) {
470+
control.mutable_db().create<transaction_object>([&](transaction_object& transaction) {
471471
transaction.trx_id = id;
472472
transaction.expiration = expire;
473473
});

plugins/db_size_api_plugin/db_size_api_plugin.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ void db_size_api_plugin::plugin_startup() {
3636
}
3737

3838
db_size_stats db_size_api_plugin::get() {
39-
chainbase::database& db = app().get_plugin<chain_plugin>().chain().db();
39+
const chainbase::database& db = app().get_plugin<chain_plugin>().chain().db();
4040
db_size_stats ret;
4141

4242
ret.free_bytes = db.get_segment_manager()->get_free_memory();

plugins/history_plugin/history_plugin.cpp

+9-7
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ namespace eosio {
206206

207207
void record_account_action( account_name n, const base_action_trace& act ) {
208208
auto& chain = chain_plug->chain();
209-
auto& db = chain.db();
209+
chainbase::database& db = const_cast<chainbase::database&>( chain.db() ); // Override read-only access to state DB (highly unrecommended practice!)
210210

211211
const auto& idx = db.get_index<account_history_index, by_account_action_seq>();
212212
auto itr = idx.lower_bound( boost::make_tuple( name(n.value+1), 0 ) );
@@ -227,7 +227,7 @@ namespace eosio {
227227

228228
void on_system_action( const action_trace& at ) {
229229
auto& chain = chain_plug->chain();
230-
auto& db = chain.db();
230+
chainbase::database& db = const_cast<chainbase::database&>( chain.db() ); // Override read-only access to state DB (highly unrecommended practice!)
231231
if( at.act.name == N(newaccount) )
232232
{
233233
const auto create = at.act.data_as<chain::newaccount>();
@@ -256,7 +256,7 @@ namespace eosio {
256256
if( filter( at ) ) {
257257
//idump((fc::json::to_pretty_string(at)));
258258
auto& chain = chain_plug->chain();
259-
auto& db = chain.db();
259+
chainbase::database& db = const_cast<chainbase::database&>( chain.db() ); // Override read-only access to state DB (highly unrecommended practice!)
260260

261261
db.create<action_history_object>( [&]( auto& aho ) {
262262
auto ps = fc::raw::pack_size( at );
@@ -344,10 +344,12 @@ namespace eosio {
344344
EOS_ASSERT( my->chain_plug, chain::missing_chain_plugin_exception, "" );
345345
auto& chain = my->chain_plug->chain();
346346

347-
chain.db().add_index<account_history_index>();
348-
chain.db().add_index<action_history_index>();
349-
chain.db().add_index<account_control_history_multi_index>();
350-
chain.db().add_index<public_key_history_multi_index>();
347+
chainbase::database& db = const_cast<chainbase::database&>( chain.db() ); // Override read-only access to state DB (highly unrecommended practice!)
348+
// TODO: Use separate chainbase database for managing the state of the history_plugin (or remove deprecated history_plugin entirely)
349+
db.add_index<account_history_index>();
350+
db.add_index<action_history_index>();
351+
db.add_index<account_control_history_multi_index>();
352+
db.add_index<public_key_history_multi_index>();
351353

352354
my->applied_transaction_connection.emplace(
353355
chain.applied_transaction.connect( [&]( const transaction_trace_ptr& p ) {

unittests/api_tests.cpp

+3-17
Original file line numberDiff line numberDiff line change
@@ -1964,23 +1964,9 @@ BOOST_FIXTURE_TEST_CASE(new_api_feature_tests, TESTER) { try {
19641964
});
19651965

19661966
// change privilege
1967-
{
1968-
chainbase::database &db = control->db();
1969-
const account_object &account = db.get<account_object, by_name>(N(testapi));
1970-
db.modify(account, [&](account_object &v) {
1971-
v.privileged = true;
1972-
});
1973-
}
1974-
1975-
#ifndef NON_VALIDATING_TEST
1976-
{
1977-
chainbase::database &db = validating_node->db();
1978-
const account_object &account = db.get<account_object, by_name>(N(testapi));
1979-
db.modify(account, [&](account_object &v) {
1980-
v.privileged = true;
1981-
});
1982-
}
1983-
#endif
1967+
push_action(config::system_account_name, N(setpriv), config::system_account_name, mutable_variant_object()
1968+
("account", "testapi")
1969+
("is_priv", 1));
19841970

19851971
CALL_TEST_FUNCTION( *this, "test_transaction", "new_feature", {} );
19861972

unittests/auth_tests.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -383,7 +383,7 @@ try {
383383
chain.create_account(acc1a);
384384
chain.produce_block();
385385

386-
chainbase::database &db = chain.control->db();
386+
const chainbase::database &db = chain.control->db();
387387

388388
using resource_usage_object = eosio::chain::resource_limits::resource_usage_object;
389389
using by_owner = eosio::chain::resource_limits::by_owner;

unittests/database_tests.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ BOOST_AUTO_TEST_SUITE(database_tests)
2626
BOOST_AUTO_TEST_CASE(undo_test) {
2727
try {
2828
TESTER test;
29-
auto &db = test.control->db();
29+
30+
// Bypass read-only restriction on state DB access for this unit test which really needs to mutate the DB to properly conduct its test.
31+
eosio::chain::database& db = const_cast<eosio::chain::database&>( test.control->db() );
3032

3133
auto ses = db.start_undo_session(true);
3234

unittests/delay_tests.cpp

+4-10
Original file line numberDiff line numberDiff line change
@@ -2317,16 +2317,10 @@ BOOST_AUTO_TEST_CASE( max_transaction_delay_execute ) { try {
23172317
chain.produce_blocks();
23182318

23192319
//change max_transaction_delay to 60 sec
2320-
chain.control->db().modify( chain.control->get_global_properties(),
2321-
[&]( auto& gprops ) {
2322-
gprops.configuration.max_transaction_delay = 60;
2323-
});
2324-
#ifndef NON_VALIDATING_TEST
2325-
chain.validating_node->db().modify( chain.validating_node->get_global_properties(),
2326-
[&]( auto& gprops ) {
2327-
gprops.configuration.max_transaction_delay = 60;
2328-
});
2329-
#endif
2320+
auto params = chain.control->get_global_properties().configuration;
2321+
params.max_transaction_delay = 60;
2322+
chain.push_action( config::system_account_name, N(setparams), config::system_account_name, mutable_variant_object()
2323+
("params", params) );
23302324

23312325
chain.produce_blocks();
23322326
//should be able to create transaction with delay 60 sec, despite permission delay being 30 days, because max_transaction_delay is 60 sec

unittests/special_accounts_tests.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ BOOST_FIXTURE_TEST_CASE(accounts_exists, tester)
3535

3636
tester test;
3737
chain::controller *control = test.control.get();
38-
chain::database &chain1_db = control->db();
38+
const chain::database& chain1_db = control->db();
3939

4040
auto nobody = chain1_db.find<account_object, by_name>(config::null_account_name);
4141
BOOST_CHECK(nobody != nullptr);

0 commit comments

Comments
 (0)