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) | 		for (auto& [slot, value]: account.storage) | ||||||
| 		{ | 		{ | ||||||
| 			value.access_status = EVMC_ACCESS_COLD; // Clear EIP-2929 storage access indicator
 | 			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
 | 	// Process selfdestruct list
 | ||||||
| 	for (auto& [address, _]: recorded_selfdestructs) | 	for (auto& [address, _]: recorded_selfdestructs) | ||||||
| @ -1195,7 +1195,7 @@ void EVMHostPrinter::storage() | |||||||
| 			m_stateStream << "  " | 			m_stateStream << "  " | ||||||
| 				<< m_host.convertFromEVMC(slot) | 				<< m_host.convertFromEVMC(slot) | ||||||
| 				<< ": " | 				<< ": " | ||||||
| 				<< m_host.convertFromEVMC(value.value) | 				<< m_host.convertFromEVMC(value.current) | ||||||
| 				<< endl; | 				<< endl; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -282,7 +282,7 @@ bool ExecutionFramework::storageEmpty(h160 const& _addr) const | |||||||
| 	if (it != m_evmcHost->accounts.end()) | 	if (it != m_evmcHost->accounts.end()) | ||||||
| 	{ | 	{ | ||||||
| 		for (auto const& entry: it->second.storage) | 		for (auto const& entry: it->second.storage) | ||||||
| 			if (!(entry.second.value == evmc::bytes32{})) | 			if (entry.second.current != evmc::bytes32{}) | ||||||
| 				return false; | 				return false; | ||||||
| 	} | 	} | ||||||
| 	return true; | 	return true; | ||||||
|  | |||||||
| @ -15,30 +15,20 @@ namespace evmc | |||||||
| /// The string of bytes.
 | /// The string of bytes.
 | ||||||
| using bytes = std::basic_string<uint8_t>; | 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 | struct storage_value | ||||||
| { | { | ||||||
|     /// The storage value.
 |     /// The current storage value.
 | ||||||
|     bytes32 value; |     bytes32 current; | ||||||
| 
 | 
 | ||||||
|     /// True means this value has been modified already by the current transaction.
 |     /// The original storage value.
 | ||||||
|     bool dirty{false}; |     bytes32 original; | ||||||
| 
 | 
 | ||||||
|     /// Is the storage key cold or warm.
 |     /// 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.
 |     /// Default constructor.
 | ||||||
|     storage_value() noexcept = default; |     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.
 | /// Mocked account.
 | ||||||
| @ -176,7 +166,7 @@ public: | |||||||
| 
 | 
 | ||||||
|         const auto storage_iter = account_iter->second.storage.find(key); |         const auto storage_iter = account_iter->second.storage.find(key); | ||||||
|         if (storage_iter != account_iter->second.storage.end()) |         if (storage_iter != account_iter->second.storage.end()) | ||||||
|             return storage_iter->second.value; |             return storage_iter->second.current; | ||||||
|         return {}; |         return {}; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -195,14 +185,13 @@ public: | |||||||
|         // Follow https://eips.ethereum.org/EIPS/eip-1283 specification.
 |         // Follow https://eips.ethereum.org/EIPS/eip-1283 specification.
 | ||||||
|         // WARNING! This is not complete implementation as refund is not handled here.
 |         // WARNING! This is not complete implementation as refund is not handled here.
 | ||||||
| 
 | 
 | ||||||
|         if (old.value == value) |         if (old.current == value) | ||||||
|             return EVMC_STORAGE_UNCHANGED; |             return EVMC_STORAGE_UNCHANGED; | ||||||
| 
 | 
 | ||||||
|         evmc_storage_status status{}; |         evmc_storage_status status{}; | ||||||
|         if (!old.dirty) |         if (old.original == old.current)  // Storage slot not dirty
 | ||||||
|         { |         { | ||||||
|             old.dirty = true; |             if (!old.current) | ||||||
|             if (!old.value) |  | ||||||
|                 status = EVMC_STORAGE_ADDED; |                 status = EVMC_STORAGE_ADDED; | ||||||
|             else if (value) |             else if (value) | ||||||
|                 status = EVMC_STORAGE_MODIFIED; |                 status = EVMC_STORAGE_MODIFIED; | ||||||
| @ -212,7 +201,7 @@ public: | |||||||
|         else |         else | ||||||
|             status = EVMC_STORAGE_MODIFIED_AGAIN; |             status = EVMC_STORAGE_MODIFIED_AGAIN; | ||||||
| 
 | 
 | ||||||
|         old.value = value; |         old.current = value; | ||||||
|         return status; |         return status; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user