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

Contract runtime in dylibs #1168

Merged
merged 45 commits into from
Mar 24, 2023
Merged

Contract runtime in dylibs #1168

merged 45 commits into from
Mar 24, 2023

Conversation

kvinwang
Copy link
Collaborator

@kvinwang kvinwang commented Feb 16, 2023

This PR turns pink runtime(the phat contract execution engine) into dynamic libraries.

The problem this PR solves

PRruntime can run ink contracts with an embedded substrate runtime with pallets-contracts enabled. However, PRuntime only ships with one version of the runtime in the binary. This is a problem because when we release new versions of the pruntime, the pink runtime will be updated as well. If transactions are executed in different versions of the pruntime, it is hard to guarantee the consistency of the state. It would likely result in a divergence of the state between different workers or a single worker replayed with different versions of pruntime. That would totally break down the whole system.

The solution

Therefore, we need to ship multiple versions of pink runtime with pruntime and make sure each transaction is always executed in the same version of the runtime no matter when and where it is executed.

Because it is difficult to compile multiple versions of the runtime in the same statically linked binary, we decided to turn the runtime into dynamic libraries. The pruntime will load different versions of the runtime dynamically at runtime.

Version management

We will bound multiple versions of pink runtime in a single pruntime distribution in future releases. The library filenames are postfixed with versions like: libpink.so.1.0. The version is set to 1.0 for now.
pruntime load different versions of the pink runtime library via libc::dlopen.
Libraries with different versions are distinguished by their filenames and identified by the version number.

There is an on-chain configuration PhalaFatContracts::PinkRuntimeVersion to specify the active version of pink runtime to be used to create new clusters.
Once a cluster is created, the version of the pink runtime won't be changed unless the cluster owner manually upgrades the runtime.

Cluster owners can upgrade the runtime by calling System::upgrade_runtime(to_version) in transaction. If the pruntime doesn't have the specified version of the runtime, it will panic with a message asking to upgrade the pruntime.

Cross boundary calls ABI

To enable cross-boundary calls between the main binary and dynamic libraries, a C ABI is used due to the lack of a stable ABI in Rust. However, the v1 implementation uses the parity SCALE codec to encode and decode cross-call arguments, which results in inefficient argument copying and en/decoding. To improve efficiency, a more efficient cross-call ABI should be developed for future versions, especially if the SCALE codec becomes a performance bottleneck.

Rust memory allocator in dynamic libraries

By default, Rust std comes with a default allocator which uses the alloc APIs from libc. As a result, every dynamic library written in Rust will have its own allocator. This is not what we want because we have a common allocator in the main executable which have some metrices and statistics. If we use the default allocator, the statistics will be not accurate. So we make this allocator in the runtime and delegate the calls to the allocator in the main executable.

Other changes

  • A new field estimating is added to the contract querying API.

    It is used to indicate whether the query is for estimating gas usage. If it is, the contract will emulate a transaction execution environment in which some off-chain ext functions are disabled. Phat-UI should use this flag to estimate gas usage.

  • Only one cluster per worker is allowed.

    We did allow multiple clusters per worker in the past, but it is not necessary and complicates the runtime code. It is removed in this PR and the corresponding info structures in the response of get_info are changed.

  • The ability to push mq messages for a contract is removed.

    Currently, no contract is using this feature. And it has some security concerns. It is removed in this PR. It needs a more secure design to be added back.

  • System contract upgrading

    The system contract upgrading is done on the contract side now, using the ink::env::set_code_hash API. It was implemented in the runtime side in the past and is removed in this PR.

@kvinwang kvinwang changed the title Dylib contract runtime Contract runtime in dylibs Feb 17, 2023
@@ -16,7 +16,7 @@ pub enum SystemMessage {
PinkLog {
block_number: u32,
contract: AccountId,
in_query: bool,
exec_mode: String,
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This breaks the previous version of logserver.

@@ -31,6 +31,7 @@ export const types: RegistryTypes = {
payload: "Vec<u8>",
deposit: "u128",
transfer: "u128",
estimating: "bool",
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Please set this field to true when estimating gas fee on the UI. @Leechael

Copy link
Contributor

Choose a reason for hiding this comment

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

In order to implement this change, we will need to ensure that it is synced across all testnets.

@kvinwang kvinwang marked this pull request as ready for review February 27, 2023 15:16
@kvinwang
Copy link
Collaborator Author

@h4x3rotab Ready for review

@h4x3rotab
Copy link
Contributor

A bit busy, but will review soon...

@h4x3rotab h4x3rotab self-assigned this Mar 16, 2023
Cargo.toml Show resolved Hide resolved
pallets/phala/src/fat.rs Show resolved Hide resolved
@@ -350,7 +350,12 @@ export async function create({
id: dest,
},
data: {
InkMessage: inputData,
InkMessage: {
Copy link
Contributor

Choose a reason for hiding this comment

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

May be related: #1159

e2e/package.json Outdated Show resolved Hide resolved
crates/pink/pink-extension/src/lib.rs Show resolved Hide resolved
crates/pink/runner/src/runtimes/v1.rs Outdated Show resolved Hide resolved
crates/pink/runner/src/storage.rs Show resolved Hide resolved
crates/pink/capi/src/v1/mod.rs Outdated Show resolved Hide resolved
crates/pink/capi/src/types.rs Show resolved Hide resolved
crates/pink/runner/tests/test_pink_contract.rs Outdated Show resolved Hide resolved
@h4x3rotab
Copy link
Contributor

h4x3rotab commented Mar 23, 2023

Still haven't reviewed: system/mod.rs, pink.rs

@h4x3rotab
Copy link
Contributor

I've reviewed all the files.

@kvinwang kvinwang merged commit 9ee4bc4 into master Mar 24, 2023
@kvinwang kvinwang deleted the dylib branch March 24, 2023 13:12
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