Notice: Polkadot has migrated to AssetHub. Balances, data, referenda, and other on-chain activity has moved to AssetHub.Learn more
Patract's treasury proposal for Ask! v0.3 (AssemblyScript Contract)
Ask!'s goal is to provide a set of contract frameworks and compilation tools using AssemblyScript as the programming language. Contracts written through Ask! can run in the FRAME Pallet-Contracts , and eventually can call each other with contracts written by ink!. One month before, Ask! had completed the development of v0.2, and here was Development Report, External Review Form and Review Report for the previous version. After v0.3, we will release Ask! 1.0 as the first production version for massive test and usage for community developers and detailed docs.
Main features of v0.3
This proposal will complete the following functions on the basis of v0.2:
1. Add project management tool ask-cli
The positioning and function of ask-cli is similar to that of cargo contract, it mainly completes the following functions:
- Initialize the Ask! project. Provide
ask-cli initcommand to create a new contract project. It will mainly complete the following tasks:- Check the current latest version of
ask, and the dependencies of ask. - Create a project directory and initialize basic settings.
- Download/update all dependencies to the local directory.
- Check the current latest version of
- Encapsulate the compilation process of ask.
- Provide
ask-cli compilecommand to control the compilation process. Thecompilecommand will provide two modes ofdebugandrelease, and the default is to use thereleasemode to compile. among them:- In the
debugmode, debugging information will be generated in the.wasmfile, and the.wastandmetadata.jsonfiles will be generated at the same time, and the files expanded by Preprocessor will be saved to theextension/folder. - In
releasemode, the highest level of optimization options will be used to compile, and only.wasmandmetadata.jsonfiles will be generated.
- In the
- Provide
2. Performance optimization
2.1 Merging the functions of @storage into @contract, reducing the process of state variable definition.
In the implementation of v0.2 version, the @storage annotation was introduced, which is specifically used to mark that a certain class is used to save state variables, such as:
@storage
class StateVariable {
varA: i8;
varB: u8;
@ignore
varC: bool
// ...
}
@contract
class Contract {
sv: StateVariable;
// ...
@message
msgA(): void {
this.sv.varA = 8;
// ...
}
}
With this implementation method, the original purpose is to distinguish state variables and ordinary variables, so that when some parameters need to be passed across methods, ordinary variables can be used without additional storage burden, but this requirement is in v0.2 With the introduction of @ignore, there can be better implementations. At the same time, the use of @storage to distinguish variable types has obvious disadvantages:
- Introduced additional coding burden, each time you use it, you need to use the writing method of
this.sv.varA. - When the contract has an inheritance relationship, it is not convenient to arrange the storage location of the data in the subclass and the parent class.
Therefore, in v0.3, the functions of @storage and @contract will be merged. The contract in the above example can be written more directly as follows:
@contract
class Contract {
varA: i8;
varB: u8;
@ignore
varC: bool
// ...
@message
msgA(): void {
this.varA = 8;
// ...
}
}
2.2 Optimize the key generation logic used when storing state variables: Use continuous hash data instead of dynamic hash(string).
In the implementation of v0.2, the key used when storing state variables is obtained by calculating hash("_lang_ask.contract.varA"). This generation method is not convenient for more reasonable arrangement of storage locations, especially for collection types such as map and array.
In v0.3, for non-@ignore variables defined in the contract, storage locations will be generated in an orderly manner according to their declaration order (including variables of the parent class), as in the above example。The storage location of varA is 0x0000000000000000000000000000000000000000000000000000000000000001, the storage location of varB is 0x0000000000000000000000000000000000000000000000000000000000000002... and so on.
2.3 In the process of a message call, when the value of the state variable is changed multiple times, reduce the number of calls to seal_set_storage
In the implementation of v0.2, every time the value of the state variable is changed, the seal_set_storage method will be called in real time to save the result to the chain. The advantage of this implementation is that the value of the state variable will change in real time, which is very important when calling each other across contracts. But in most cases, it is not necessary to update state variables in real time, which will waste gas and consume IO operations.
In v0.3, the state variable will be updated in a lazy way, that is: in the process of a message call, the value of the state variable can be modified multiple times, but only after the message call is completed, will the final result be saved to the chain , So no matter how many times the state variable is modified, the seal_set_storage method will only be called once. At the same time, in order to meet the need to update state variables in real time when calling across contracts, a new annotation @immediately is introduced, which is annotated on state variables. If the state variable of @immediately is modified, its value will be real-time Update to the chain.
@contract
class Contract {
varA: i8;
@immediately
varB: u8;
// ...
@message
msgA(): void {
this.varA = 9; // won't update onchain value
// ...
this.varA = 18; // won't update onchain value
this.varB = 19; // update onchain value to 19 immediately
// ...
this.varB = 29; // update onchain value to 29 immediately
// ...
// update onchain value of this.varA to 18
}
}
2.4 Define the export format of Map and Array in metadata.json.
In v0.2, we provide the implementation of StorableMap and StorableArray, and in spread mode, they are saved as a doubly linked list, so that you can iteratively access all the data in StorableMap and StorableArry offline through the information provided in metadata.json. In order to achieve this goal, we will generate the necessary information for the StorableMap and StorableArray in the storage object of metadata.json. For StorableMap, its storage information is like:
{
"name": "someMap",
"layout": {
"struct": {
"fields": [
{// StorableMap info of entry node
"name": "entries",
"type": "spread", // storage mode, "spread" | "packed"
"layout": {
"key": "0x0000000000000000000000000000000000000000000000000000000000000002" // storage position
}
},
{
"name": "key",
"layout": {
"ty": 5 // data type of key
}
},
{
"name": "value",
"layout": {
"ty": 5 // data type of value
}
}
]
}
}
}
For StorableArray, like:
{
"name": "someArray",
"layout": {
"struct": {
"fields": [
{// StorableArray info of entry
"name": "entries",
"type": "spread", // storage mode, "spread" | "packed"
"layout": {
"key": "0x0000000000000000000000000000000000000000000000000000000000000002" // storage position
}
},
{
"name": "key",
"layout": {
"ty": 5 // data type of key
}
}
]
}
}
}
2.5 Use JSON instead of () annotations
In the implementation of v0.2, the parameter of the annotation is provided by (), such as@message(payable = true, selector = "0x1234"). In v0.3, it will be: @message({payable: true, selector: "0x1234"}) to improve the readability and maintainability of the code.
2.6 Enhance Event syntax, provide js library for parsing Event data
- Support @event inheritance
Event is essentially derived from the_lang.Eventclass, in terms of syntax they should support inheritance. But in v0.2 does not support inheritance operations, in v0.3, we will support the Event class can be inherited. - Optimize the constructor and implementation method
In v0.2, because of the functional limitation of Proprecess, when we generate the Event construction method, we call theemitmethod by default, and the code of the Event class after the Preprocessor is expanded:
class Transfer extends _lang.Event {
private from: AccountId;
private to: AccountId;
private value: u128;
constructor(from: AccountId, to : AccountId, value: u128) {
super();
this.from = from;
this.to = to;
this.value = value;
// code inserted by compiler
this.emit();
}
}
This implementation has the following problems:
- If the
returnmethod is called in the constructor method, thethis.emitmethod will not be called, resulting in the event not being sent. - The emit is defaultly used when constructing the Event, which is very unintuitive in coding.
For these reasons, we will optimize the implementation of Event to avoid the above problems by providing js library to parse Event data.
2.7 Enhanced annotation syntax and parameter checking
In the previous version, we have successively introduced multiple annotations, sub-annotations and annotation parameters, but before compilation, there was no good check during compilation, and no clear enough prompt information was provided when an error occurred. So in the v0.3, we will check all annotations and parameters in Preprocess, and provide friendly compilation information when errors occur.
2.8 Optimize the size of the generated wasm file
2.9 Upgrade the seal_xxx method in pallet-contract
Some seal_xxx methods in pallet-contract have been changed. In v0.3, the changed methods will be upgraded to the latest stable version.
3. Provide system parameter types in custom env
In the previous version, we used the FRAME provided in the Europa project by default, and defined the data types of the following system-level variables:
type Hash Array<u8>(32);
type AccountId Array<u8>(32);
type BlockNumber UInt32;
type Balance UInt128;
Although the default data type can meet most of the needs, in order to meet a small number of custom requirements, we will provide developers with the ability about custom Hash AccountId BlockNumber Balance data type in the v0.3 to adapt to different FRAME.
4. Unit Testing and Documentation
- Provide unit testing of Preprocess and framework.
- Provide tutorial documents for contract development.
- Provide framework API documentation.
Detailed timeline v0.3 (3 developers * 10 weeks)
- Week 1~2: ask-cli
- Complete the architecture design and implementation of
ask-cli. - Implement
init,compilefunctions.
- Week 3~6: Performance optimization work.
- Merge
@storageto@contract:- Expand the
@storagelogic in the implementation of contract to realize the read and write ability of state variables. - Optimize the key generation logic when storing state variables.
- A new method is added to the implementation of contract to generate storage logic for state variables, ensuring that
seal_set_storageis only called once. - Add
@immediatelyannotation, which acts on state variables, and the annotated variables will immediately callseal_set_storageto save.
- Expand the
- Enhance contract syntax.
- Standardize annotation usage, use JSON format instead of
()method - Enhance compile-time syntax checking, when encountering unsupported annotations and parameters, a compilation error will be thrown.
- Enhance
@eventclass, optimize implementation method and support event inheritance.
- Standardize annotation usage, use JSON format instead of
- Optimize the size of the generated wasm file.
- Define the export format of Map and Array in metadata.json, and provide js parsing library.
- Upgrade the
seal_xxxmethod to the latest stable version of pallet-contract.
- Week 7:
- Customize the
HashAccountIdBlockNumberBalancedata type in the env environment. - Update the usage of predefined environment variables in the framework.
- Week 8~10: Complete documentation and unit tests.
- Provide local test cases for Preprocess and framework.
- Provide ask contract development tutorial.
- Provide a tutorial on how to use ask-cli.
- Provide API documentation for each component in the framework.
Cost of v0.3 (30 developers * weeks)
- Operating activities: $6000 ( Rent and Devices: $200 per developer * week )
- Employee payments: $87000 ($2900 per developer * week)
- Total Cost: $93000 and monthly average: $203/KSM @ 28JUL
- Treasury Proposal: 458 KSM
How to verify v0.3 (github & docs & samples)
- Officially released npm library of ask and ask-cli.
- Reimplement the contract in examples with a new contract implementation method.
- Complete contract development tutorial.
- Complete API documentation.
Comments (7)
That sounds great to me. I would add a single comment about
ask-cli init, make sure you use proper scaffolding and ideally provide an easy access to patch the template source as this is likely to evolve over time and it would be great for everyone to have an easy maintenance.You may get inspiration from https://yeoman.io/ on that topic.
Thank you very much, this suggestion is very helpful