diff --git a/doc/final-design.md b/doc/final-design.md
index 1407b88..4381d6c 100644
--- a/doc/final-design.md
+++ b/doc/final-design.md
@@ -14,7 +14,7 @@ This article discusses the pallet-move functionality.
MoveVM scripts and modules are not allowed to run forever - therefore, the `gas` value is used for that purpose. The provided `gas` gets converted to `Weight`, a mechanism that prevents extriniscs from running forever.
The script execution is an atomic operation - if the provided gas is insufficient, the MoveVM within the pallet will reject the script, and no changes shall occur - but the user will pay for the used weight anyway. So, using the gas estimation RPC method is well recommended.
-Scripts and modules have limited access to the balance transfer functionality via the `cheque_amount` parameter - the maximum amount of balance the account scripts can transfer from the signer of the extrinsic.
+Scripts and modules have limited access to the balance transfer functionality via the `cheque_limit` parameter - the maximum amount of balance the account scripts can transfer from the signer of the extrinsic.
## Extrinsics
@@ -69,6 +69,8 @@ Scripts and modules have limited access to the balance transfer functionality vi
## RPC
+To quickly access these RPC methods above, it is recommended to use `smove node rpc` set of subcommands.
+
### Method `mvm_estimateGasPublishModule`
Estimate gas and weight cost for publishing a module.
@@ -145,7 +147,7 @@ Get module binary using account address.
----------------------------------------------------------------
-# Design architecture
+# Design Architecture
The main parts are:
- A pallet hosting the MoveVM _(this repo)_.
@@ -172,14 +174,16 @@ Each following signer will execute the same script transaction with its individu
Pallet move will store the state of each signature and each cheque limit and keep track if all users have signed or not.
After each signer has signed by calling the exact same extrinsic call with the same script transaction, the Move pallet will execute the script.
-**Differences to single signer:**
+**Differences to single signer scripts:**
- The cheque limit (tokens) of each signer will be locked on their accounts until the request gets finally executed or deleted.
- Except for the final signer, the event `SignedMultisigScript` will be emitted instead of `ExecuteCalled`.
- When all signers have signed, the script will be executed, the tokens be unlocked, and balances applied according to the Move script.
- Every user needs to sign the script within a certain time limit; otherwise, the request will expire, which means it will be removed automatically after a certain amount of time (as defined by the blockchain developer).
- If a multi-signature request expires, then all previous signatures are dropped in vain. If some user then reinitiates the request, all signers need to provide their signature again.
- The point of time of the first signature defines the expiration timeout for that multi-signature script. New signatures for that multi-signer script cannot extend the time limit.
-- If all signatures are collected and then the script execution fails (e.g. because of insufficient cheque amount), no change will take place in the MoveVM storage / balance. The only way to re-execute the script is to restart the request and try to collect all signatures once again.
+- If all signatures are collected and then the script execution fails (e.g. because of insufficient cheque amount), no change will take place in the MoveVM storage / balance, nor the previous signatures will be dropped. The only way to re-execute the script successfully is to find a signer who provided insufficient `cheque_limit` and ask that user to re-sign the script. Only then the final signer can execute the script successfully.
- The signer order doesn't matter (it is independent of the order of the script function arguments).
- If the script function argument list has a signer in multiple places in the argument list, this signer (user) has to sign the script only once.
-- _TODO (Eiger): Add information about gas usage._
+- Only the last signer must provide the `gas_limit` value necessary for execution within the MoveVM. All previous signers can set the `gas_limit` value to zero since the script won't start\the execution until all signatures are collected.
+
+We recommend you review our quick multi-signer [tutorial](tutorial-multi-signer.md) for more practical info.
diff --git a/doc/gas-handling.md b/doc/gas-handling.md
index 792355e..d0901db 100644
--- a/doc/gas-handling.md
+++ b/doc/gas-handling.md
@@ -38,16 +38,10 @@ For that reason, it is recommended to use `smove node rpc` estimation RPC comman
- the minimum required `gas_limit` to execute/publish a given script/module,
- an estimated weight cost for the extrinsic call for the given `gas_limit`.
-Previously executed Substrate benchmarks define conversion between gas limit and weight and can be found in the auto-generated file here.
+Previously executed Substrate benchmarks define conversion between gas limit and weight and can be found in the auto-generated file [here](../pallet/src/weights.rs).
To better understand the costs, it's best to use the estimation RPC methods.
> [!NOTE]
> The same amount of `gas_limit` between different extrinsic doesn't necessarily add the equal weight cost.
Future pallet users should monitor and observe gas handling costs once the pallet gets integrated into the actual blockchain and then recalibrate it according to their needs, if necessary, according to the info above.
-
-[move-stdlib]: https://github.com/eigerco/substrate-move/tree/main/language/move-stdlib
-[substrate-move]: https://github.com/eigerco/substrate-move
-[substrate-stdlib]: https://github.com/eigerco/substrate-stdlib
-[native-fn]: https://move-language.github.io/move/functions.html?highlight=native#native-functions
-[smove]: https://github.com/eigerco/smove
diff --git a/doc/stdlib-doc.md b/doc/stdlib-doc.md
index 9cea2e1..7b9f43b 100644
--- a/doc/stdlib-doc.md
+++ b/doc/stdlib-doc.md
@@ -4,8 +4,8 @@ The standard library provides a set of common modules that should be available t
All modules within the standard library are published under the special account address `0x01` in the Move storage.
The standard library is contained in two repositories:
- - [`move-stdlib`](move-stdlib) - commonly known set of standard library modules that can be found across all Move compatible ecosystems.
- - [`substrate-stdlib`](substrate-stdlib) - an extended standard library which contains Substrate-specific modules or any module that might be required for specific pallet-move use cases.
+ - [`move-stdlib`][move-stdlib] - commonly known set of standard library modules that can be found across all Move compatible ecosystems.
+ - [`substrate-stdlib`][substrate-stdlib] - an extension library to the standard library which contains Substrate-specific modules or any module that might be required for specific pallet-move use cases.
If the pallet users want to extend the standard library, we recommend adding new modules to the `subtrate-stdlib` repository to keep the original `move-stdlib` small and simple.
@@ -14,33 +14,34 @@ Any new modules can be easily added once the end goal for the pallet user is cle
In the following chapters, one can find a set of instructions that can be used to update the standard library when there is a clear need to do so.
-Before we delve into the next two chapters, we should mention the special kind of functions called [native functions](native-fn).
+Before we delve into the next two chapters, we should mention the special kind of functions called [native functions][native-fn].
These functions don't have a regular function body specified in Move source files like normal functions have, but instead, their implementation is integrated within the MoveVM itself.
Native functions are only allowed in standard libraries, as updating them requires updating the MoveVM source code itself.
-## Updates adding new Move source code modules
+## Move Modules Updates
Adding new modules to the standard library is pretty simple.
Add a module to the wanted repository and then build it as a bundle with `smove bundle` and also generate doc files with `smove docgen`.
If the standard library needs to be updated in post-genesis block settings, the `update_stdlib_bundle` extrinsic can achieve this.
+Check usage instructions in the [tech guide](./tech_guide.md#update-standard-libraries).
Note: This extrinsic can be used only by the root user.
A simple example can be found in this [pull request](https://github.com/eigerco/move-stdlib/pull/5).
-## Updates that add native functions
+## Native Function Updates
Adding new native functions to the standard library requires the implementation of a function body in Rust within the MoveVM code.
You can use these PRs as an example of how that can be done:
- - in [`substrate-move`](substrate-move): [feat: add native functions for substrate_hash module](https://github.com/eigerco/substrate-move/pull/83)
- - in [`substrate-stdlib`](substrate-stdlib): [feat: add new hash module with native functions](https://github.com/eigerco/substrate-stdlib/pull/4)
+ - in [`substrate-move`][substrate-move]: [feat: add native functions for substrate_hash module](https://github.com/eigerco/substrate-move/pull/83)
+ - in [`substrate-stdlib`][substrate-stdlib]: [feat: add new hash module with native functions](https://github.com/eigerco/substrate-stdlib/pull/4)
-Whenever native functions are added, [smove](smove) needs to update dependencies so it fetches the latest MoveVM changes and then a new version of `smove` should be published.
+Whenever native functions are added, [smove][smove] needs to update dependencies so it fetches the latest MoveVM changes and then a new version of `smove` should be published.
Hopefully, pallet users won't need to add new native functions after the genesis block, otherwise the node's runtime will require an update containing the new version of the MoveVM instance with the latest code that includes added native functions.
-[move-stdlib]: https://github.com/eigerco/substrate-move/tree/main/language/move-stdlib
+[move-stdlib]: https://github.com/eigerco/move-stdlib
[substrate-move]: https://github.com/eigerco/substrate-move
[substrate-stdlib]: https://github.com/eigerco/substrate-stdlib
[native-fn]: https://move-language.github.io/move/functions.html?highlight=native#native-functions
diff --git a/doc/tech_guide.md b/doc/tech_guide.md
index 04e1db9..dd3a250 100644
--- a/doc/tech_guide.md
+++ b/doc/tech_guide.md
@@ -102,7 +102,7 @@ impl pallet_move::Config for Test {
The pallet provides three extrinsic calls. To find about those check the [design document](final-design.md).
-Have a look at the [mockup implementation](https://github.com/eigerco/pallet-move/blob/main/tests/mock.rs) for further coding details, or check the crate's Rust documentation:
+Have a look at the [mockup implementation](https://github.com/eigerco/pallet-move/blob/main/pallet/src/mock.rs) for further coding details, or check the crate's Rust documentation:
```bash
cargo doc --open
```
@@ -166,14 +166,14 @@ All available options are in the [node template](https://docs.substrate.io/refer
## Update Standard Libraries
Two standard libraries are provided for pallet-move at the genesis block creation:
-- [`move-stdlib`](move-stdlib) - the normal Move standard library inherited from the Move repo.
-- [`substrate-stdlib`](substrate-stdlib) - an extension of the standard library with additional modules - where some of those modules are also substrate-specific modules.
+- [`move-stdlib`][move-stdlib] - the normal Move standard library inherited from the Move repo.
+- [`substrate-stdlib`][substrate-stdlib] - an extension of the standard library with additional modules - where some of those modules are also substrate-specific modules.
On rare occasions, those libraries can be updated after the genesis block creation by the root account. **WARNING: THIS CAN BREAK THE MOVE-VM ON-CHAIN STORAGE IF IT INTRODUCES BACKWARD INCOMPATIBLE CHANGES - BE CAREFUL WITH THIS OPERATION**
After edits are prepared to the standard library Move packages, compile both bundles using `smove`:
```bash
-smove bundle -p substrate-move/language/move-stdlib
+smove bundle -p move-stdlib
smove bundle -p substrate-stdlib
```
The two generated bundles will be located in the subfolders:
@@ -183,7 +183,8 @@ The two generated bundles will be located in the subfolders:
Use the extrinsic call `update_stdlib_bundle` as the sudo user to update both of them.
![Update Stdlib](assets/polkadot.js_update_stdlib.png)
+For more info about the standard library, check the documentation [here](./stdlib-doc.md).
-[move-stdlib]: https://github.com/eigerco/substrate-move/tree/main/language/move-stdlib
+[move-stdlib]: https://github.com/eigerco/move-stdlib
[substrate-move]: https://github.com/eigerco/substrate-move
[substrate-stdlib]: https://github.com/eigerco/substrate-stdlib
diff --git a/doc/tutorial-multi-signer.md b/doc/tutorial-multi-signer.md
index acd2dd9..fefd783 100644
--- a/doc/tutorial-multi-signer.md
+++ b/doc/tutorial-multi-signer.md
@@ -7,23 +7,44 @@ You have already done the [tutorial](tutorial.md) and you are familiar with publ
### Differences to a Single User Script Execution
Again, the story starts with the developer, Bob, who publishes a module.
-This time, it is the `Dorm.mv` module from our example move project [`multi-signer`](../pallet/srv/tests/assets/move-projects/multi-signer), which allows to rent apartments for groups of three students each.
+This time, it is the `Dorm.mv` module from our example move project [`multi-signer`](../pallet/src/assets/move-projects/multiple-signers), which allows to rent apartments for groups of three students each.
We assumed that dorms with exactly three rooms are available and can only be rented with three students together.
+
| ![polkadot.js_multisign_bob_publishes_module.png](assets/polkadot.js_multisign_bob_publishes_module.png) |
|:--:|
| _Bob publishes a module using [polkadot.js][polkadotjs]_ |
Again, developer Bob initialises his module by executing the script transaction `init_module.mvt`.
+_To create script transactions feel free to use solutions hidden within the `multiple-signers/build.sh` script (or just run the script)._
+
| ![polkadot.js_multisign_bob_inits_module.png](assets/polkadot.js_multisign_bob_inits_module.png) |
|:--:|
| _Bob initialises his module using [polkadot.js][polkadotjs]_ |
-The student Alice is the first one and executes the script transaction `rent_apartment.mvt`, which is already prepared for the student group Alice, Dave and Eve and with two months of rental. Alice can set her gas limit to 0 because the script will only be executed after everyone has signed.
+Now, let's prepare a script transaction for the script shown below:
+```move
+fun rent_apartment(acc1: signer, acc2: signer, acc3: signer, months: u8) {
+ Dorm::rent_apartment(&acc1, &acc2, &acc3, months);
+}
+```
+
+The script transaction will group all three users (signers) of the apartment together, so every signer should execute the script
+(the order of arguments in the `create-transaction` within the `--args` list, must be the same as in the actual script above):
+```sh
+move create-transaction --compiled-script-path build/multiple-signers/bytecode_scripts/rent_apartment.mv --args signer:5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY signer:5DAAnrj7VHTznn2AWBemMuyBwZWs6FNFjdyVXUeYum3PTXFy signer:5HGjWAeFDfFCWPsjFQdVV2Msvz2XtMktvgocEZcCj68kUMaw u8:2
+```
+
+The student Alice is the first one and executes the created script transaction `rent_apartment.mvt`, which is already prepared for the student group Alice, Dave and Eve and with two months of rental. Alice can set her gas limit to 0 because the script will only be executed after everyone has signed.
+
+Within the `Dorm.move`, we can see that the monthly price is 90 UNITs, so the two-month cost is 180 UNITs.
+Every user of the apartment needs to provide a third of the whole cost, which is 60 UNITs (60000000000000 picoUNITs).
+
| ![polkadot.js_multisign_alice_initiates.png](assets/polkadot.js_multisign_alice_initiates.png) |
|:--:|
| _Alice initiates the multi signer execution request using [polkadot.js][polkadotjs]_ |
-Now same script transaction must be executed by Dave and Eve as well where Dave sets his gas limit also to 0. Eve has estimated the needed gas for the script execution to 1377 and now enters that value because he is the final signer and the script will be executed now.
+Now, Dave and Eve must execute the same script transaction, and Dave sets his gas limit to 0. Eve estimates the needed gas for the script execution to be 1377 and enters that value because he is the final signer, and the script will be executed now since all signers have provided their signatures.
+
| ![polkadot.js_multisign_eve_finalises.png](assets/polkadot.js_multisign_eve_finalises.png) |
|:--:|
| _Eve finalises the multi signer execution request using [polkadot.js][polkadotjs]_ |
@@ -31,7 +52,7 @@ Now same script transaction must be executed by Dave and Eve as well where Dave
After all three students have executed that script transaction you should see, that the amounts of tokens have be withdrawn from their accounts.
Because every student has to sign the extrinsic call and execute the script execution, the execution request will be stored in the pallet's storage until every student has signed.
-> Note: After the initiation of a multi signer execution requests, the specified cheque limits will be locked until it the request gets executed or deleted.
+> Note: After the initiation of a multi signer execution requests, the specified cheque limits will be locked until it the request gets executed, deleted or updated (signing again the same transction script allows user to change the cheque limits in a pending multisig script).
From the first signer to the one before the last one, they will see the event `SignedMultisigScript`.
After the final signer has signed and executed the same extrinsic call, the script transaction will be executed, tokens with amount of the cheque limit will be unlocked and withdrawn, and the event `ExecuteCalled` will be emitted.
@@ -40,4 +61,6 @@ Here, the second was Dave, and the last one was Eve, who signed the extrinsic ca
|:--:|
| _Events in a multi signer execution requests in [polkadot.js][polkadotjs]_ |
-We hope you liked this short introduction about multi-signer script executions. You can find a couple of details more on this more in the [tech guide](tech_guide.md).
+We hope you liked this short introduction about multi-signer script executions. You can find a couple of details more on this more in the [the design document](./final-design.md#multi-signer-script-execution).
+
+[polkadotjs]: https://polkadot.js.org/apps/
diff --git a/doc/tutorial.md b/doc/tutorial.md
index 815475c..d7c2fed 100644
--- a/doc/tutorial.md
+++ b/doc/tutorial.md
@@ -39,11 +39,11 @@ Prerequisites:
- [Install smove](https://github.com/eigerco/smove).
- Setup our template node with pallet-move integrated and run it in the background - the instructions can be found in our [tech guide](./tech_guide.md).
- Either use [polkadot.js][polkadotjs] or run a local frontend for the node running in the background.
-- Switch the current working directory to the code example directory in `pallet-move/tests/assets/move-projects/car-wash-example`.
+- Switch the current working directory to the code example directory in `pallet-move/pallet/src/assets/move-projects/car-wash-example`.
In our example, a simple car wash is modelized, where washing coins are used to control the usage of the car wash.
Users can register, buy washing coins and use them to start the car wash.
-For the sake of simplicity, we show here only the function headers of the Move module, the full module can be seen [here](https://github.com/eigerco/pallet-move/blob/main/tests/assets/move-projects/car-wash-example/sources/CarWash.move).
+For the sake of simplicity, we show here only the function headers of the Move module, the full module can be seen [here](https://github.com/eigerco/pallet-move/blob/main/pallet/src/assets/move-projects/car-wash-example/sources/CarWash.move).
```move
module DeveloperBob::CarWash {
@@ -98,7 +98,11 @@ smove node rpc estimate-gas-publish-module --account-id 5FHneW46xGXgs5mUiveU4sbT
The successful result will look like:
```sh
-Estimated gas: Estimate (gas_used: 732, vm_status_code: EXECUTED)
+Gas estimation:
+ used gas: 732
+ total extrinsic weight cost with the above gas:
+ Weight { ref_time: 20205232845, proof_size: 3576 }
+ vm_status_code: EXECUTED
```
### Publication
@@ -159,7 +163,11 @@ smove node rpc estimate-gas-execute-script -s build/car-wash-example/script_tran
```
with response:
```sh
-Estimated gas: Estimate (gas_used: 343, vm_status_code: EXECUTED)
+Gas estimation:
+ used gas: 343
+ total extrinsic weight cost with the above gas:
+ Weight { ref_time: 2829763107, proof_size: 17037 }
+ vm_status_code: EXECUTED
```
### Execution
@@ -214,7 +222,7 @@ Now, let's execute the following actions:
smove create-transaction --compiled-script-path build/car-wash-example/bytecode_scripts/buy_coin.mv --args signer:5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY u8:1
# Now let's estimate gas for this transaction-script.
- # `cheque_limit` also needs to be specified here, the RPC command will just if the use has enough funds, if not, it will report an error:
+ # `cheque_limit` isn't used in the RPC command for gas estimation, the RPC command assume the user has enough funds:
smove node rpc estimate-gas-execute-script -s build/car-wash-example/script_transactions/buy_coin.mvt
```
@@ -229,7 +237,7 @@ Now, let's execute the following actions:
Click here to unlock the hidden command for the above action.
```
- # The check_limit isn't required here (so it should be set to zero for safety reasons) since Alice will burn the MoveVM spend token in order to wash her car.
+ # The check_limit isn't required here (so it should be set to zero for safety reasons) since Alice will burn the car wash coin in order to wash her car.
smove create-transaction --compiled-script-path build/car-wash-example/bytecode_scripts/wash_car.mv --args signer:5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY
# Now let's estimate gas for this transaction-script:
diff --git a/pallet/src/assets/move-projects/smove-clean-all.sh b/pallet/src/assets/move-projects/smove-clean-all.sh
index 75ca9ad..e708571 100755
--- a/pallet/src/assets/move-projects/smove-clean-all.sh
+++ b/pallet/src/assets/move-projects/smove-clean-all.sh
@@ -4,7 +4,6 @@
cd $(dirname $0)
build_dir=(
- # Modules
"balance"
"base58_smove_build"
"car-wash-example"
@@ -13,7 +12,7 @@ build_dir=(
"move-basics"
"multiple-signers"
"signer-scripts"
- # Bundles
+ "basic_coin"
"prohibited-bundle"
"testing-move-stdlib"
"testing-substrate-stdlib"
diff --git a/pallet/src/mock_utils.rs b/pallet/src/mock_utils.rs
index 12ecd0e..b46eea3 100644
--- a/pallet/src/mock_utils.rs
+++ b/pallet/src/mock_utils.rs
@@ -79,7 +79,7 @@ mod tests_only {
/// Can panic if the file doesn't exist.
pub fn read_bytes(file_path: &str) -> Vec {
std::fs::read(file_path)
- .unwrap_or_else(|e| panic!("Can't read {file_path}: {e} - make sure you run pallet-move/tests/assets/move-projects/smove-build-all.sh"))
+ .unwrap_or_else(|e| panic!("Can't read {file_path}: {e} - make sure you run pallet-move/pallet/src/assets/move-projects/smove-build-all.sh"))
}
/// Reads a precompiled Move scripts from our assets directory.
diff --git a/pallet/src/signer.rs b/pallet/src/signer.rs
index 61b1c96..069c92c 100644
--- a/pallet/src/signer.rs
+++ b/pallet/src/signer.rs
@@ -234,7 +234,7 @@ impl ScriptSignatureHandler {
Ok(balances)
}
- /// Consumes [`ScriptSignatureHandler`] and returns innner `SigData`.
+ /// Consumes [`ScriptSignatureHandler`] and returns inner `SigData`.
pub(crate) fn into_inner(self) -> SigDataOf {
self.sig_info
}