Skip to content

Conversation

@Pedrozo
Copy link
Contributor

@Pedrozo Pedrozo commented Jan 15, 2025

This work was initially just a refactoring of the big and complex ContractHost class, but later many flaws were found and will be fixed with this PR.

Some important changes include:

  • Proper reversion of EVM contracts. Basically, we did not support reverting single contract calls. This PR includes a family of functions for allowing that.

  • Fixed gas usage. During the execution flow of the ContractHost, sometimes the wrong amount of gas was charged.

  • The call tracer previous implementation was uglier, slower, less flexible, and error-prone. The new implementation is way more robust and correct.

  • Delegate calls are now working.

  • ContractHost responsibilities were divided between the classes MessageDispatcher, CallTracer, ExecutionContext, CppContractExecutor, EvmContractExecutor, and PrecompiledContractExecutor. Thus, the new ContractHost class is smaller and simpler.

  • The new ExecutionContext class is now responsible for reverting the contracts state during calls reversions.

  • Used a lot of generic code to reuse code that process contract calls. (Take a look at the MessageDispatcher class)

  • A family of types for Encoded Messages (EVM) and Packed Messages (CPP), allowing us to reuse common message
    processing code, and preventing us from the temptation of using the terrible evmc_message class.

  • C++ concepts added for selecting specific message types during overload resolution. (MessageDispatcher is a good usage example for that)

  • C++ traits added for functions and messages

Additionally, this PR introduces a family of "view" types and new algorithms for byte manipulation:

  • Introduced View<Address>, View<Hash>, View<Signature>, and View<Bytes>. In short, they aim to replace a constant reference with a view object, just like std::string_view replaces const std::string&. For example, a View<Address> can be cheaply created from both Address and evmc::address types.
// BAD: if called with evmc::address, a conversion will be required (i.e. bytes copying)
void foo(const Address& addr);

// GOOD: no conversion required if called with Address, evmc::address, or pretty much any type that can construct a View<Address>
void bar(View<Address> addr);
  • SafeHash and the new SafeCompare now allow "transparent search". That means calls to .find() in map objects with different types than Key are allowed as long as they are equally comparable with the key type and the hash function accepts them. This is especially useful for the ContractHost needs, where we have maps whose key type is Address, but often searches use evmc::address objects. In this case, we would need to convert (i.e. copy the bytes) from one type to another, but with transparent search a call to find() with a evmc::address argument is perfectly valid.

  • Introduced bytes::random() and bytes::random(size_t) functions. They initialize byte containers with random data. The bytes::random() matches the container size, while the bytes::random(size_t) can be used where a sized initializer is required.

Address addr = bytes::random(); // exactly 20 random bytes generated
Hash hash = bytes::random();    // exactly 32 random bytes generated
Bytes bytes = Utils::makeBytes(bytes::random(666)); // 666 random bytes generated
  • Introduced bytes::hex() for initializing a container with a hexadecimal string representation. Ex: Address addr = bytes::hex("0xfb6916095ca1df60bb79ce92ce3ea74c37c5d359");

  • Introduced bytes::cast() function for general-purpose bytes range conversion. For example:

Hash hash; // some hash object
evmc::bytes32 asBytes32 = bytes::cast<evmc::bytes32>(hash); // instead of hash.toEvmcBytes()
  • Hash and View<Hash> can now be converted to uint256_t by using static_cast. Example:
Hash hash; // some hash object
uint256_t value = static_cast<uint256_t>(hash);
  • bytes::View deprecated and replaced by View<Bytes>.

  • strings.h header broke into multiple header files: fixedbytes.h, signature.h, address.h, and hash.h.

@Pedrozo Pedrozo self-assigned this Jan 15, 2025
@Pedrozo Pedrozo added the enhancement New feature or request label Jan 15, 2025
Copy link
Collaborator

@Jean-Lessa Jean-Lessa left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall great work! Aside from my comments here, I see the branch has some compilation errors yet to be resolved (probably due to the massive alterations I did for SonarQube coverage). If that becomes too much work to fix, let me know and I'll see what I can do to help.

@Pedrozo Pedrozo merged commit 8ec5a19 into development Jan 20, 2025
2 of 3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants