Skip to content
This repository has been archived by the owner on Aug 2, 2022. It is now read-only.

chainbase uniqueness violation fixes #7266

Merged
merged 6 commits into from
May 6, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 11 additions & 4 deletions libraries/chain/apply_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -480,10 +480,17 @@ void apply_context::schedule_deferred_transaction( const uint128_t& sender_id, a
control.add_to_ram_correction( ptr->payer, orig_trx_ram_bytes );
}

db.modify<generated_transaction_object>( *ptr, [&]( auto& gtx ) {
if( replace_deferred_activated ) {
gtx.trx_id = trx.id();
}
transaction_id_type trx_id_for_new_obj;
if( replace_deferred_activated ) {
trx_id_for_new_obj = trx.id();
} else {
trx_id_for_new_obj = ptr->trx_id;
}

// Use remove and create rather than modify because mutating the trx_id field in a modifier is unsafe.
db.remove( *ptr );
db.create<generated_transaction_object>( [&]( auto& gtx ) {
gtx.trx_id = trx_id_for_new_obj;
gtx.sender = receiver;
gtx.sender_id = sender_id;
gtx.payer = payer;
Expand Down
1 change: 0 additions & 1 deletion libraries/chain/eosio_contract.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
#include <eosio/chain/permission_link_object.hpp>
#include <eosio/chain/global_property_object.hpp>
#include <eosio/chain/contract_types.hpp>
#include <eosio/chain/producer_object.hpp>

#include <eosio/chain/wasm_interface.hpp>
#include <eosio/chain/abi_serializer.hpp>
Expand Down
6 changes: 3 additions & 3 deletions libraries/chain/include/eosio/chain/account_object.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ namespace eosio { namespace chain {
OBJECT_CTOR(account_object,(abi))

id_type id;
account_name name;
account_name name; //< name should not be changed within a chainbase modifier lambda
block_timestamp_type creation_date;
shared_blob abi;

Expand Down Expand Up @@ -56,7 +56,7 @@ namespace eosio { namespace chain {
};

id_type id;
account_name name;
account_name name; //< name should not be changed within a chainbase modifier lambda
uint64_t recv_sequence = 0;
uint64_t auth_sequence = 0;
uint64_t code_sequence = 0;
Expand Down Expand Up @@ -88,7 +88,7 @@ namespace eosio { namespace chain {
OBJECT_CTOR(account_ram_correction_object);

id_type id;
account_name name;
account_name name; //< name should not be changed within a chainbase modifier lambda
uint64_t ram_correction = 0;
};

Expand Down
6 changes: 3 additions & 3 deletions libraries/chain/include/eosio/chain/code_object.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ namespace eosio { namespace chain {
OBJECT_CTOR(code_object, (code))

id_type id;
digest_type code_hash;
digest_type code_hash; //< code_hash should not be changed within a chainbase modifier lambda
shared_blob code;
uint64_t code_ref_count;
uint32_t first_block_used;
uint8_t vm_type = 0;
uint8_t vm_version = 0;
uint8_t vm_type = 0; //< vm_type should not be changed within a chainbase modifier lambda
uint8_t vm_version = 0; //< vm_version should not be changed within a chainbase modifier lambda
};

struct by_code_hash;
Expand Down
16 changes: 8 additions & 8 deletions libraries/chain/include/eosio/chain/contract_table_objects.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ namespace eosio { namespace chain {
OBJECT_CTOR(table_id_object)

id_type id;
account_name code;
scope_name scope;
table_name table;
account_name code; //< code should not be changed within a chainbase modifier lambda
scope_name scope; //< scope should not be changed within a chainbase modifier lambda
table_name table; //< table should not be changed within a chainbase modifier lambda
account_name payer;
uint32_t count = 0; /// the number of elements in the table
};
Expand Down Expand Up @@ -59,8 +59,8 @@ namespace eosio { namespace chain {
static const int number_of_keys = 1;

id_type id;
table_id t_id;
uint64_t primary_key;
table_id t_id; //< t_id should not be changed within a chainbase modifier lambda
uint64_t primary_key; //< primary_key should not be changed within a chainbase modifier lambda
account_name payer = 0;
shared_blob value;
};
Expand Down Expand Up @@ -90,10 +90,10 @@ namespace eosio { namespace chain {
typedef SecondaryKey secondary_key_type;

typename chainbase::object<ObjectTypeId,index_object>::id_type id;
table_id t_id;
uint64_t primary_key;
table_id t_id; //< t_id should not be changed within a chainbase modifier lambda
uint64_t primary_key; //< primary_key should not be changed within a chainbase modifier lambda
account_name payer = 0;
SecondaryKey secondary_key;
SecondaryKey secondary_key; //< secondary_key should not be changed within a chainbase modifier lambda
};


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ namespace eosio { namespace chain {
OBJECT_CTOR(generated_transaction_object, (packed_trx) )

id_type id;
transaction_id_type trx_id;
account_name sender;
uint128_t sender_id = 0; /// ID given this transaction by the sender
transaction_id_type trx_id; //< trx_id should not be changed within a chainbase modifier lambda
account_name sender; //< sender should not be changed within a chainbase modifier lambda
uint128_t sender_id = 0; /// ID given this transaction by the sender (should not be changed within a chainbase modifier lambda)
account_name payer;
time_point delay_until; /// this generated transaction will not be applied until the specified time
time_point expiration; /// this generated transaction will not be applied after this time
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ namespace eosio { namespace chain {
/// May be empty; if so, it sets a default @ref required_permission for all messages to @ref code
action_name message_type;
/// The permission level which @ref account requires for the specified message types
/// all of the above fields should not be changed within a chainbase modifier lambda
permission_name required_permission;
};

Expand All @@ -61,8 +62,7 @@ namespace eosio { namespace chain {
composite_key<permission_link_object,
BOOST_MULTI_INDEX_MEMBER(permission_link_object, account_name, account),
BOOST_MULTI_INDEX_MEMBER(permission_link_object, permission_name, required_permission),
BOOST_MULTI_INDEX_MEMBER(permission_link_object, account_name, code),
BOOST_MULTI_INDEX_MEMBER(permission_link_object, action_name, message_type)
BOOST_MULTI_INDEX_MEMBER(permission_link_object, permission_link_object::id_type, id)
>
>
>
Expand Down
4 changes: 2 additions & 2 deletions libraries/chain/include/eosio/chain/permission_object.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ namespace eosio { namespace chain {
id_type id;
permission_usage_object::id_type usage_id;
id_type parent; ///< parent permission
account_name owner; ///< the account this permission belongs to
permission_name name; ///< human-readable name for the permission
account_name owner; ///< the account this permission belongs to (should not be changed within a chainbase modifier lambda)
permission_name name; ///< human-readable name for the permission (should not be changed within a chainbase modifier lambda)
time_point last_updated; ///< the last time this authority was updated
shared_authority auth; ///< authority required to execute this permission

Expand Down
49 changes: 0 additions & 49 deletions libraries/chain/include/eosio/chain/producer_object.hpp

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,8 @@ namespace eosio { namespace chain { namespace resource_limits {
OBJECT_CTOR(resource_limits_object)

id_type id;
account_name owner;
bool pending = false;
account_name owner; //< owner should not be changed within a chainbase modifier lambda
bool pending = false; //< pending should not be changed within a chainbase modifier lambda

int64_t net_weight = -1;
int64_t cpu_weight = -1;
Expand Down Expand Up @@ -162,7 +162,7 @@ namespace eosio { namespace chain { namespace resource_limits {
OBJECT_CTOR(resource_usage_object)

id_type id;
account_name owner;
account_name owner; //< owner should not be changed within a chainbase modifier lambda

usage_accumulator net_usage;
usage_accumulator cpu_usage;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ namespace eosio { namespace chain {
OBJECT_CTOR(reversible_block_object,(packedblock) )

id_type id;
uint32_t blocknum = 0;
uint32_t blocknum = 0; //< blocknum should not be changed within a chainbase modifier lambda
shared_string packedblock;

void set_block( const signed_block_ptr& b ) {
Expand Down
2 changes: 1 addition & 1 deletion libraries/chain/include/eosio/chain/transaction_object.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ namespace eosio { namespace chain {

id_type id;
time_point_sec expiration;
transaction_id_type trx_id;
transaction_id_type trx_id; //< trx_id should not be changed within a chainbase modifier lambda
};

struct by_expiration;
Expand Down
50 changes: 48 additions & 2 deletions libraries/chain/include/eosio/chain/types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ namespace eosio { namespace chain {
block_summary_object_type,
transaction_object_type,
generated_transaction_object_type,
producer_object_type,
UNUSED_producer_object_type,
UNUSED_chain_property_object_type,
account_control_history_object_type, ///< Defined by history_plugin
UNUSED_account_transaction_history_object_type,
Expand All @@ -195,8 +195,54 @@ namespace eosio { namespace chain {
OBJECT_TYPE_COUNT ///< Sentry value which contains the number of different object types
};

/**
* Important notes on using chainbase objects in EOSIO code:
*
* There are several constraints that need to be followed when using chainbase objects.
* Some of these constraints are due to the requirements imposed by the chainbase library,
* others are due to requirements to ensure determinism in the EOSIO chain library.
*
* Before listing the constraints, the "restricted field set" must be defined.
*
* Every chainbase object includes a field called id which has the type id_type.
* The id field is always included in the restricted field set.
*
* A field of a chainbase object is considered to be in the restricted field set if it is involved in the
* derivation of the key used for one of the indices in the chainbase multi-index unless its only involvement
* is through being included in composite_keys that end with the id field.
*
* So if the multi-index includes an index like the following
* ```
* ordered_unique< tag<by_sender_id>,
* composite_key< generated_transaction_object,
* BOOST_MULTI_INDEX_MEMBER( generated_transaction_object, account_name, sender),
* BOOST_MULTI_INDEX_MEMBER( generated_transaction_object, uint128_t, sender_id)
* >
* >
* ```
* both `sender` and `sender_id` fields are part of the restricted field set.
*
* On the other hand, an index like the following
* ```
* ordered_unique< tag<by_expiration>,
* composite_key< generated_transaction_object,
* BOOST_MULTI_INDEX_MEMBER( generated_transaction_object, time_point, expiration),
* BOOST_MULTI_INDEX_MEMBER( generated_transaction_object, generated_transaction_object::id_type, id)
* >
* >
* ```
* would not by itself require the `expiration` field to be part of the restricted field set.
*
* The restrictions on usage of the chainbase objects within this code base are:
* + The chainbase object includes the id field discussed above.
* + The multi-index must include an ordered_unique index tagged with by_id that is based on the id field as the sole key.
* + No other types of indices other than ordered_unique are allowed.
* If an index is desired that does not enforce uniqueness, then use a composite key that ends with the id field.
* + When creating a chainbase object, the constructor lambda should never mutate the id field.
* + When modifying a chainbase object, the modifier lambda should never mutate any fields in the restricted field set.
*/

class account_object;
class producer_object;

using block_id_type = fc::sha256;
using checksum_type = fc::sha256;
Expand Down
2 changes: 1 addition & 1 deletion libraries/chainbase
1 change: 0 additions & 1 deletion plugins/chain_plugin/chain_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
#include <eosio/chain/block_log.hpp>
#include <eosio/chain/exceptions.hpp>
#include <eosio/chain/authorization_manager.hpp>
#include <eosio/chain/producer_object.hpp>
#include <eosio/chain/code_object.hpp>
#include <eosio/chain/config.hpp>
#include <eosio/chain/wasm_interface.hpp>
Expand Down
1 change: 0 additions & 1 deletion plugins/producer_plugin/producer_plugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
* @copyright defined in eos/LICENSE
*/
#include <eosio/producer_plugin/producer_plugin.hpp>
#include <eosio/chain/producer_object.hpp>
#include <eosio/chain/plugin_interface.hpp>
#include <eosio/chain/global_property_object.hpp>
#include <eosio/chain/generated_transaction_object.hpp>
Expand Down
Loading