Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implemented contract instantiation and invocation for integration tests #1988

Open
wants to merge 39 commits into
base: master
Choose a base branch
from

Conversation

Helios-vmg
Copy link

Summary

  • [n] y/n | Does it introduce breaking changes?
  • [n] y/n | Is it dependant on the specific version of cargo-contract or pallet-contracts?

This PR implements instantiate_contract(), invoke_contract(), invoke_contract_delegate() and a few other functions for the integration testing environment. More specifically, it permits calling these functions from inside contracts transparently, as if the contract was running on the blockchain.

Description

  • The following off-chain API functions are implemented: instantiate_contract(), invoke_contract(), invoke_contract_delegate(), return_value(), code_hash(), set_code_hash(), own_code_hash().
  • Two additional, testing-only functions called get_return_value() and upload_code() were added. get_return_value() returns the value stored by the modified return_value() (see below). upload_code() simulates uploading the code of a contract to the blockchain and returns a code hash. The actual hash is based on the value of a function pointer, so no attempt is made to reproduce what the blockchain will produce.
  • A trait named ContractReverseReference was added to env. The trait just adds a Type type that links from ContractRef back to Contract. The code generator was also modified to generate the implementation for this trait. This was needed in the instantiate_contract() implementation, as the function only sees the ContractRef type, but it needs the Contract type to decode the serialized input buffer. This change also necessitated propagating some trait requirements, but these changes should be transparent to users.
  • When the test_instantiate feature is enabled, an alternative return_value() is used in the generated dispatch code that stores the encoded return value into key [0xFF_u8; 32]. This value is retrieved later to return it to the caller. Additionally, this alternative implementation returns (), instead of !. A further modification was needed on execute_dispatchable() to avoid a compiler error when return_value() doesn't return !. When test_instantiate is enabled, An Ok(()) is added at the end of the functions (for constructor as well as for message dispatch), thus allowing the test-case to proceed.
  • The files under crates/ink/src/reflect were moved to crates/primitives/src/reflect, as Env now needs some of those types in the instantiate_contract() implementation and it was otherwise impossible to avoid a circular dependence. The crates were updated to expose the same types as before, so nothing changes for users.
  • It was necessary to add a small unsafe block in crates/env/src/engine/off_chain/mod.rs, to the OnInstance implementation for EnvInstance, to be able to return a mut reference while another mut reference was still borrowed, which was necessary because now that contract can invoke other contracts some API functions are called nested. This should be safe, as the object is in a TLS, so there's no possibility of undefined behavior arising from race conditions.
  • My code follows the style guidelines of this project
  • I have added an entry to CHANGELOG.md
  • I have commented my code, particularly in hard-to-understand areas
  • I have added tests that prove my fix is effective or that my feature works
  • Any dependent changes have been merged and published in downstream modules (N/A)

Other notes

To test a contract that uses instantiate_contract() in the off-chain environment, use cargo test --features test_instantiate.
Regarding the build errors in the doc tests, I've been trying to resolve them, but it's difficult without any way to see the macro expansion. When I move the code inside the comments to an actual contract it compiles correctly. Is there any way to move forward with this? Can I mark the comments as no_compile and add equivalent integration tests to catch breaking changes?

Helios-vmg and others added 30 commits October 27, 2023 17:43
# Conflicts:
#	crates/env/src/lib.rs
#	crates/env/src/reflect/event.rs
#	crates/ink/codegen/Cargo.toml
Moved reflection, contract, arithmetic, and miscellaneous types from ink_env
to ink_primitives.
…tation

# Conflicts:
#	crates/engine/src/database.rs
@cmichi
Copy link
Collaborator

cmichi commented Nov 14, 2024

@Helios-vmg Could you merge master into your PR and resolve the conflicts?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants