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

V1 contract state #243

Merged
merged 48 commits into from
Apr 27, 2022
Merged

V1 contract state #243

merged 48 commits into from
Apr 27, 2022

Conversation

abizjak
Copy link
Member

@abizjak abizjak commented Feb 6, 2022

Purpose

Resolves #237
Resolves #254

Changes

The main change is the introduction of the Concordium.GlobalState.ContractStateV1 module and its integration into global state and contract execution (in module Concordium.Scheduler.WasmIntegration.V1).
The remaining changes are essentially boilerplate. The main data structure implementation is in Concordium/concordium-wasm-smart-contracts#25 Rust, and that is also where it is used and integrated into the execution engine.

The implementation there exposes the minimal API through FFI so that the necessary abstractions can be implemented in the node. This in particular means

  • loading and storing the state into blobstore
  • serializing the state, and deserializing it. This is only needed at the time of the protocol update.

The remaining changes are essentially boilerplate changes to make it possible to use two different versions of the contract state in the scheduler. This involved introducing a new abstraction ContractStateOperations, analogous to AccountOperations.

Fallback entrypoints handling is essentially just in the Scheduler and is very straightforward.

Ugliness

The basic state implementation is what I would call not clean. It works, and I believe it is reasonable given the constraints of FFI, but it is nevertheless ugly. A similar ugliness is particularly notable in the paired implementation which uses serialization of contract state to transform it from one form to another, so that contracts only need to be executed once. I don't think there is another reasonable choice since we would have to duplicate the paired "host" implementation on the execution engine side. This is a lot of effort for little gain.

Limitations

The general limitation of state management, and state transfer on a protocol update remains. Namely that the entire state of all contracts is loaded into memory and serialized, and then deserialized at protocol update time. This should be addressed before the next protocol since already now the memory requirements are excessive. This will only be made worse if the new contract state is used. However this is not part of this pull request and is a big project on its own.

There is no intelligent caching of the state. This is in-line with the rest of the state, e.g., accounts since the current design of the node state does not really support an intelligent implementation of caching. Either everything is in-memory, or nothing is. This should also be revised fairly quickly with some form of LRU cache or similar to prevent excessive memory use of the node.
However this will be a substantial revision of the state. For now contract state behaves as the rest of the state.

Depends on

Checklist

  • My code follows the style of this project.
  • The code compiles without warnings.
  • I have performed a self-review of the changes.
  • I have documented my code, in particular the intent of the
    hard-to-understand areas.
  • (If necessary) I have updated the CHANGELOG.

Instead just pass a closure that raises a Haskell exception.
The V1 contract state tests do not yet pass since the contract examples need to
be revised for new state.
The paired implementation is somewhat hacky. It uses basic contract state and
serialization to convert from one type of contract state to another.

This is not ideal, but a more comprehensive solution requires much more
extensive FFI (i.e., paired state constructions, and a paired construction of
state in Rust). This is a lot of complications for something that ultimately
does not matter much. The current solution is useful for basic testing, which is
all that the paired state is used for.
MilkywayPirate and others added 12 commits March 14, 2022 09:16
Checkpointing tests for smart contracts.
Co-authored-by: Aleš Bizjak <ab@concordium.com>
Fixes the broken link to `smart-contracts` repository
* Introduced tests for cross messaging and checkpointing.
This does the following
- revise the format of state storage to optimize for the common case
- changes costs of some operations to better reflect reality.
Previously the cost did not include storage costs.
@abizjak abizjak marked this pull request as ready for review April 6, 2022 06:49
@abizjak abizjak requested review from Bargsteen and td202 April 6, 2022 11:08
Copy link
Contributor

@td202 td202 left a comment

Choose a reason for hiding this comment

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

Small issues, but mostly fine.

Copy link
Contributor

@Bargsteen Bargsteen left a comment

Choose a reason for hiding this comment

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

Looks good, just minor comments 👍

@abizjak abizjak merged commit c7abb8b into main Apr 27, 2022
@abizjak abizjak deleted the v1-contract-state branch April 27, 2022 04:32
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.

Fallback entrypoints: Node support New contract state: node support
5 participants