Comments (4)
Commit 45e2f71 is an initial attempt at solving this issue as stated above.
It features
/// The result of a storage allocation.
struct MaybeUninitialized<T>(T);
/// Implemented by all types that allow to be allocated on the storage.
trait AllocateUsing {
unsafe fn allocate_using<A>(alloc: &mut A) -> MaybeUninitialized<Self>
where
A: Allocator;
}
/// Implemented by all types that need special initialization after allocation on the storage.
///
/// # Example
///
/// The utility wrapper `storage::Value` is such a type.
trait Initialize {
type Args;
fn initialize(&mut self, args: Self::Args);
}
MaybeUninitialized
provides two methods, unwrap
to just directly access the maybe uninitialized underlying value and initialize
that is only implemented if the underlying type implements Initialize
. The initialize
method basically forwards its arguments to the Initialize
implementation and returns the result.
Summary
With this all three scenarios are approachable.
- CREATE:
Foo::allocate_using(&mut bump_alloc).initialize(bar)
or- No code needed to deploy the smart contract.
- CALL:
Foo::allocate_using(&mut bump_alloc).unwrap()
- DYNAMIC:
Foo::allocate_using(&mut cc_alloc).initialize(baz)
orFoo::allocate_using(&mut cc_alloc).unwrap()
if initialization is not required
Note that all of this is going to be hidden from users normally as soon as the pdsl_derive
is done.
from ink.
Due to problems involving recursive calls to allocate_using
we shifted the approach slightly.
The helper struct MaybeUninitialized<T>
has been removed and allocate_using
now returns Self
instead of MaybeUninitialized<Self>
.
Besides that we introduced another helper trait method Initialize::initialize_into(self, Self::Args) -> Self
so that users can still use chaining.
Summary
With these changes the following scenarios are approachable in the following ways.
- CREATE
Foo::allocate_using(&mut bump_alloc).initialize_into(bar)
or- No code required to deploy the smart contract.
- CALL
Foo::allocate_using(&mut bump_alloc)
- DYNAMIC
Foo::allocate_using(&mut cc_alloc).initialize_into(baz)
orFoo::allocate_using(&mut cc_alloc)
if no initialization is required
Note that all of this is going to be hidden from users normally as soon as the pdsl_derive
is done.
from ink.
To improve safety and security we should transit towards encapsulating the state and everything that modifies it.
For this we should separate state modifying environment functions out of Env
into an own dedicated State
trait.
This State
trait could look like the following:
trait State {
fn store(key: Key, bytes: &[u8]);
fn load(key: Key) -> Option<Vec<u8>>;
fn clear(key: Key);
}
It would be nice to have some compile-time niceties to check that a certain instance exists only once.
For runtime-based check there is https://crates.io/crates/once. With such a check we can secure that there is really just one state operating on contract state so that we can actually have single ownership of it. Maybe the future eDSL
could provide this check to its users. Also note that the State
trait is agnostic over EnvTypes
and thus doesn't need to be generic over them.
The Env
trait needs more polish. Types implementing it must also include in their state a type implementing the State
trait. With this setup we can determine an ownership when using a single environment which is the default. Also the Env
implementation could handle all dynamic and static allocations.
struct SrmlEnv<S: State> {
state: S,
bump_alloc: BumpAlloc,
dyn_alloc: DynAlloc,
}
impl Env for SrmlEnv { ... }
Now we can actually form an API to allocate contract entities dynamically using an Env
implementer for that purpose.
impl SrmlEnv {
fn on_storage<T>(&mut self, args: <T as Initialize>::Args>) -> T
where
T: AllocateUsing + Initialize
{
T::allocate_using(&mut self.dyn_alloc).initialize_into(args)
}
}
Note that dynamically allocated storage entities clear their associated storage upon Drop
(going out of scope) whereas statically allocated storage entities do not. To fix the current situation for statically allocated entities we need to wrap them in a certain utility type in order to not clear their associated storage upon Drop
.
struct NoDrop<T>(PhantomData<T>);
impl Drop for NoDrop {
fn drop(&mut self) {
// Do nothing on purpose!
// Note that this should not break types that require cleanup on `Drop`
// since we are leaving contract execution anyway when calling `Drop`
// of statically allocated storage entities.
}
}
from ink.
Done (since ages). Closed.
from ink.
Related Issues (20)
- The function `set_contract_storage` in integration test it's missing a size check.
- Linter: Unprotected `terminate_contract`
- Linter: Unprotected `DelegateCall` call
- Immutable contracts allowed to change state via `env` HOT 4
- Add a lint for missing `no_main`
- IIP-3: Allow messages without `&self` receiver; opt out of automatic storage loading HOT 5
- Different gas value for `weight_to_fee()` in ink! integration and e2e tests HOT 6
- Split up `ink_linting` into two `dylint` libraries HOT 1
- Use standard Github's machines for test jobs
- Linter: Warn about using non-fallible APIs for `Lazy` and `Mapping` HOT 1
- Support expressions for `extension` and `function` during chain extension definition
- Event defintions with generics
- Deprecation of "legacy" inline events HOT 1
- Unify `call-runtime` and `e2e-call-runtime` examples
- Linter: Dangereous `self.env().transferred_value()` pattern
- Linter: Divide before multiply
- Add support and integration test for `caller_is_root`
- Migrate ink! CI from organization runners to standard GitHub runners
- Add links to linter warning details on use.ink
- Cross contract calling produces unsupported code HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from ink.