mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	test: Improve precision of SSTORE cost in EVMHost
Add "original" field to storage_value to precise track "dirty" state of a storage slot as defined in EIP-2200. In case a current storage value is restored to original (after multiple modifications in a single transaction), the storage slot is not considered "dirty" any more. Previously, we only had a bool dirty flag to model this and a storage slot was always considered "dirty" after first modification.
This commit is contained in:
		
							parent
							
								
									9db2da0385
								
							
						
					
					
						commit
						199f36585a
					
				| @ -179,7 +179,7 @@ void EVMHost::newTransactionFrame() | ||||
| 		for (auto& [slot, value]: account.storage) | ||||
| 		{ | ||||
| 			value.access_status = EVMC_ACCESS_COLD; // Clear EIP-2929 storage access indicator
 | ||||
| 			value.dirty = false;					// Clear EIP-2200 dirty slot flag
 | ||||
| 			value.original = value.current;			// Clear EIP-2200 dirty slot
 | ||||
| 		} | ||||
| 	// Process selfdestruct list
 | ||||
| 	for (auto& [address, _]: recorded_selfdestructs) | ||||
| @ -1195,7 +1195,7 @@ void EVMHostPrinter::storage() | ||||
| 			m_stateStream << "  " | ||||
| 				<< m_host.convertFromEVMC(slot) | ||||
| 				<< ": " | ||||
| 				<< m_host.convertFromEVMC(value.value) | ||||
| 				<< m_host.convertFromEVMC(value.current) | ||||
| 				<< endl; | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -282,7 +282,7 @@ bool ExecutionFramework::storageEmpty(h160 const& _addr) const | ||||
| 	if (it != m_evmcHost->accounts.end()) | ||||
| 	{ | ||||
| 		for (auto const& entry: it->second.storage) | ||||
| 			if (!(entry.second.value == evmc::bytes32{})) | ||||
| 			if (entry.second.current != evmc::bytes32{}) | ||||
| 				return false; | ||||
| 	} | ||||
| 	return true; | ||||
|  | ||||
| @ -15,30 +15,20 @@ namespace evmc | ||||
| /// The string of bytes.
 | ||||
| using bytes = std::basic_string<uint8_t>; | ||||
| 
 | ||||
| /// Extended value (by dirty flag) for account storage.
 | ||||
| /// Extended value (with original value and access flag) for account storage.
 | ||||
| struct storage_value | ||||
| { | ||||
|     /// The storage value.
 | ||||
|     bytes32 value; | ||||
|     /// The current storage value.
 | ||||
|     bytes32 current; | ||||
| 
 | ||||
|     /// True means this value has been modified already by the current transaction.
 | ||||
|     bool dirty{false}; | ||||
|     /// The original storage value.
 | ||||
|     bytes32 original; | ||||
| 
 | ||||
|     /// Is the storage key cold or warm.
 | ||||
|     evmc_access_status access_status{EVMC_ACCESS_COLD}; | ||||
|     evmc_access_status access_status = EVMC_ACCESS_COLD; | ||||
| 
 | ||||
|     /// Default constructor.
 | ||||
|     storage_value() noexcept = default; | ||||
| 
 | ||||
|     /// Constructor.
 | ||||
|     storage_value(const bytes32& _value, bool _dirty = false) noexcept  // NOLINT
 | ||||
|       : value{_value}, dirty{_dirty} | ||||
|     {} | ||||
| 
 | ||||
|     /// Constructor with initial access status.
 | ||||
|     storage_value(const bytes32& _value, evmc_access_status _access_status) noexcept | ||||
|       : value{_value}, access_status{_access_status} | ||||
|     {} | ||||
| }; | ||||
| 
 | ||||
| /// Mocked account.
 | ||||
| @ -176,7 +166,7 @@ public: | ||||
| 
 | ||||
|         const auto storage_iter = account_iter->second.storage.find(key); | ||||
|         if (storage_iter != account_iter->second.storage.end()) | ||||
|             return storage_iter->second.value; | ||||
|             return storage_iter->second.current; | ||||
|         return {}; | ||||
|     } | ||||
| 
 | ||||
| @ -195,14 +185,13 @@ public: | ||||
|         // Follow https://eips.ethereum.org/EIPS/eip-1283 specification.
 | ||||
|         // WARNING! This is not complete implementation as refund is not handled here.
 | ||||
| 
 | ||||
|         if (old.value == value) | ||||
|         if (old.current == value) | ||||
|             return EVMC_STORAGE_UNCHANGED; | ||||
| 
 | ||||
|         evmc_storage_status status{}; | ||||
|         if (!old.dirty) | ||||
|         if (old.original == old.current)  // Storage slot not dirty
 | ||||
|         { | ||||
|             old.dirty = true; | ||||
|             if (!old.value) | ||||
|             if (!old.current) | ||||
|                 status = EVMC_STORAGE_ADDED; | ||||
|             else if (value) | ||||
|                 status = EVMC_STORAGE_MODIFIED; | ||||
| @ -212,7 +201,7 @@ public: | ||||
|         else | ||||
|             status = EVMC_STORAGE_MODIFIED_AGAIN; | ||||
| 
 | ||||
|         old.value = value; | ||||
|         old.current = value; | ||||
|         return status; | ||||
|     } | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user