-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Handle the case for contract creation on an empty but exist account with storage items #10065
Conversation
ethcore/src/externalities.rs
Outdated
@@ -116,6 +116,10 @@ impl<'a, T: 'a, V: 'a, B: 'a> Ext for Externalities<'a, T, V, B> | |||
where T: Tracer, V: VMTracer, B: StateBackend | |||
{ | |||
fn initial_storage_at(&self, key: &H256) -> vm::Result<H256> { | |||
if self.substate.new_contract_with_previously_non_empty_storage.contains(&self.origin_info.address) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it possible that the contract was empty initially, but then it is somehow initialized via CREATE
within the same scope?
I.e. asking if returning zero()
here wouldn't break something else
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed this to use is_base_storage_root_unchanged
. If base storage root is changed from an original storage root value, then the changed base storage root can only be KECCAK_NULL_RLP
(because we only change it in contract creation). From any point after that, we discard the actual original storage value, but use H256::zero()
.
I think it's safe and can't think of any way this will break things, but would love to have more eyes for review.
7584235
to
95e3e32
Compare
@@ -539,6 +539,13 @@ impl<B: Backend> State<B> { | |||
|a| a.as_ref().map_or(self.account_start_nonce, |account| *account.nonce())) | |||
} | |||
|
|||
/// Whether the base storage root of an account remains unchanged. | |||
pub fn is_base_storage_root_unchanged(&self, a: &Address) -> TrieResult<bool> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why not just return bool
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Below State::ensure_cached
can fail, and in that case I think it's better to bail because it's a DB failure.
Co-Authored-By: sorpaas <accounts@that.world>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm
…ith storage items (#10065) * Add is_base_storage_root_unchanged * Fix compile, use a shortcut for check, and remove ignored tests * Add a warn! * Update ethereum/tests to v6.0.0-beta.2 * grumble: use {:#x} instead of 0x{:x} Co-Authored-By: sorpaas <accounts@that.world>
…ith storage items (#10065) * Add is_base_storage_root_unchanged * Fix compile, use a shortcut for check, and remove ignored tests * Add a warn! * Update ethereum/tests to v6.0.0-beta.2 * grumble: use {:#x} instead of 0x{:x} Co-Authored-By: sorpaas <accounts@that.world>
* version: bump stable to 2.2.7 * version: mark 2.2 track stable * version: mark update critical on all networks * version: commit cargo lock * Ping nodes from discovery (#10167) * snap: fix path in script (#10157) * snap: fix path in script * debug, revert me * fix * necromancer awk magic * awk necromancy and path fixing * working track selection * Fix _cannot recursively call into `Core`_ issue (#10144) * Change igd to github:maufl/rust-igd * Run `igd::search_gateway_from_timeout` from own thread * Handle the case for contract creation on an empty but exist account with storage items (#10065) * Add is_base_storage_root_unchanged * Fix compile, use a shortcut for check, and remove ignored tests * Add a warn! * Update ethereum/tests to v6.0.0-beta.2 * grumble: use {:#x} instead of 0x{:x} Co-Authored-By: sorpaas <accounts@that.world> * version: bump fork blocks for kovan and foundation (#10186) * pull constantinople on ethereum network (#10189) * ethcore: pull constantinople on ethereum network * version: mark update as critical * ethcore: remove constantinople alltogether from chain spec * version: revert fork block for ethereum
* version: mark 2.3 track beta * version: mark update critical on all networks * Ping nodes from discovery (#10167) * Fix _cannot recursively call into `Core`_ issue (#10144) * Change igd to github:maufl/rust-igd * Run `igd::search_gateway_from_timeout` from own thread * Handle the case for contract creation on an empty but exist account with storage items (#10065) * Add is_base_storage_root_unchanged * Fix compile, use a shortcut for check, and remove ignored tests * Add a warn! * Update ethereum/tests to v6.0.0-beta.2 * grumble: use {:#x} instead of 0x{:x} Co-Authored-By: sorpaas <accounts@that.world> * version: bump fork blocks for kovan and foundation (#10186) * pull constantinople on ethereum network (#10189) * ethcore: pull constantinople on ethereum network * version: mark update as critical * ethcore: remove constantinople alltogether from chain spec * version: revert fork block for ethereum
In spec it's technically possible to create empty account with existing storage items, thus break the net metering model. This PR creates
is_base_storage_root_unchanged
function in state. However, any sane person wouldn't do that so practicallyis_base_storage_root_unchanged
should always betrue
with the only exception of tests.For any items in the checkpoint, once we set
original_storage_cache
, we carry it on for any further items in the checkpoint. So we can check the newest items in the checkpoint list to determine whether there's any changes of thebase_storage_root
value. It works for current model because the value ofbase_storage_root
can only ever be changed once.