Skip to content

Commit

Permalink
Merge branch 'main' into testnet
Browse files Browse the repository at this point in the history
  • Loading branch information
damip committed Sep 16, 2022
2 parents 390d2fe + cea0ff5 commit c09e975
Show file tree
Hide file tree
Showing 26 changed files with 563 additions and 323 deletions.
123 changes: 33 additions & 90 deletions docs/smart-contracts/getting-started.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,72 +7,35 @@ In this section you will learn how to compile your first Massa smart contract.

Setting up a new project
^^^^^^^^^^^^^^^^^^^^^^^^
.. collapse:: Wait, I know npm. Just give me the commands!

Here you go:

.. code-block:: shell
npm init
npm install --global yarn npx
npm install --save-dev @as-pect/cli massa-sc-std
npx asinit .
npx asp --init
.. collapse:: OK, but I would like to use docker. Can you help me?

Sure, no problem:

.. code-block:: shell
docker run -it --user $(id -u):$(id -g) -v $PWD:/app -v $PWD/.npm:/.npm -v $PWD/.config:/.config -w /app node:17.7-alpine npm init
docker run --user $(id -u):$(id -g) -v $PWD:/app -v $PWD/.npm:/.npm -v $PWD/.config:/.config -w /app node:17.7-alpine npm install --save-dev @as-pect/cli
docker run -it --user $(id -u):$(id -g) -v $PWD:/app -v $PWD/.npm:/.npm -v $PWD/.config:/.config -w /app node:17.7-alpinenpx asinit .
docker run --user $(id -u):$(id -g) -v $PWD:/app -v $PWD/.npm:/.npm -v $PWD/.config:/.config -w /app node:17.7-alpine npx asp --init

Make sure you have a recent version of Node.js and npm. Update or `install <https://docs.npmjs.com/downloading-and-installing-node-js-and-npm>`_ them if needed.
Create or go to the directory where you want to set up your project and run:

.. code-block:: shell
npm init
npm install --global yarn npx
npx massa-sc-create my-sc
Don't bother with the different question, you can change all that by editing the `package.json` file.

.. note::
You can add the parameter `--yes` to automatically set the default values.

Now that the npm project is created, install the `as-pect` and `massa-sc-std` dependencies by executing the following command:
Now that the npm project is created, go inside your smart-contract directory and install the dependencies using the following commands:

.. code-block:: shell
npm install --save-dev [email protected] @massalabs/[email protected] [email protected] [email protected] [email protected]
cd my-sc
npm install --legacy-peer-deps
You have now installed AssemblyScript. The first one will be used to generate bytecode from AssemblyScript code.
You have now installed AssemblyScript among other dependencies. It will be used to generate bytecode from AssemblyScript code.

.. note::
* Massa smart contract module (massa-sc-std) contains the API you need to use to interact with the external world of the smart contract (the node, the ledger...).
* Massa smart contract module (@massalabs/massa-sc-std) contains the API you need to use to interact with the external world of the smart contract (the node, the ledger...).
* Installing directly as-pect will automatically install the compatible version of AssemblyScript.
* All dependencies should be installed as dev dependencies as no module will be exported on this project.

Now that AssemblyScript and as-pect dependencies are installed, you can finish setting up your project by running:

.. code-block:: shell
npx asinit .
npx asp --init

Congratulations! Now you have a fully set up project and you are ready to add some code.

.. note::
A few words on project folders:

* `assembly` is where the code goes;
* `assembly/__test__/` store the unit tests;
* `build` will contain the compiled smart contracts.
* `src` is where the code goes;
* `build` will be created during compilation and will contain the compiled smart contracts.

Create your first smart contract
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Expand All @@ -85,29 +48,29 @@ Your first smart contract will be no exception!

I'm told that it has nothing to do with the beginning of mankind but Brian Kernighan used it for the first time in *a tutorial introduction to the language B* published in 1972.

Create and open a new file called `helloworld.ts` in `assembly` directory at the root of your project. In this file, write or copy/paste the following code:
Open the `main.ts` file in the `src` directory at the root of your project. Replace the code in the file by the following code:

.. code-block:: typescript
import { print } from "@massalabs/massa-sc-std";
import { generateEvent } from "@massalabs/massa-sc-std";
export function main(_args: string): void {
print("Hello world!");
export function main(_args: string): void {
generateEvent("Hello world!");
}
Don't forget to save the file. Before starting compilation, just a few words to describe what you just wrote or pasted:
Dont forget to save the file. Before starting compilation, just a few words to describe what is used here:

* line 1: `print` function is imported from Massa API (massa-sc-std). This function will write to stdout the string given as argument.
* line 1: `generateEvent` function is imported from Massa API (@massalabs/massa-sc-std). This function will generate an event with the string given as argument. Events can be later recovered using a Massa client.
* line 3: `main` function is exported. This means that the main function will be callable from the outside of the WebAssembly module (more about that later).
* line 4: `print` function is called with "Hello world!". Brian, we are thinking of you!
* line 4: `generateEvent` function is called with "Hello world!". Brian, we are thinking of you!

Now that everything is in place, we can start the compilation step by running the following command:

.. code-block:: shell
npx massa-sc-scripts build-sc assembly/helloworld.ts
npm run build
Congratulations! You have generated your first smart contract: the `helloworld.wasm` file in `build` directory.
Congratulations! You have generated your first smart contract: the `main.wasm` file in `build` directory.

.. note::

Expand All @@ -124,46 +87,21 @@ Execute your smart contract on a node

To execute the smart contract you will need:

- A running node with a log level set to DEBUG.
- A client configured with an address having coins.
- A smart contract compiled in WebAssembly (see previous step).

Let's go!

Running a node in debug mode
""""""""""""""""""""""""""""

Make sure that you have the last version of the Massa node. If not, `install it <https://github.com/massalabs/massa/wiki/install>`_.

Once the node is installed and before running it, set your log level to DEBUG:

- open `massa-node/base_config/config.toml` file with your preferred editor;
- set the log level to `3`.

.. note::

Your file should look like the following:

.. code-block:: toml
[logging]
# Logging level. High log levels might impact performance. 0: ERROR, 1: WARN, 2: INFO, 3: DEBUG, 4: TRACE
level = 3
.. warning::
A node configured with a verbose log level will write a lot of logs. You should restore default value as soon as this tutorial is finished.


Now that the node is properly configured to log `print` function output you have to `run the node <https://github.com/massalabs/massa/wiki/run>`_.

Configure the client
""""""""""""""""""""

Make sure that you have the last version of the Massa node. If not, `install it <https://github.com/massalabs/massa/wiki/install>`_.

If you don't have any wallet configured yet, `create a new one <https://github.com/massalabs/massa/wiki/wallet>`_.

If you're using a brand new wallet, add some coins by sending your address to `testnet-faucet discord channel <https://discord.com/channels/828270821042159636/866190913030193172>`_.

If you are using an existing wallet, make sure that you have at least 1 coin on it.
If you are using an existing wallet, make sure that you have some coins on it.

In any case, keep the `address` of your wallet, you will use it later.

Expand All @@ -185,26 +123,31 @@ Everything is in place, we can now execute the `hello world` smart contract on y
- 100000: the maximum amount of gas that the execution of your smart-contract is allowed to use.
- Three 0 parameters that can be safely ignored by now. If you want more info on them, use the command `help send_smart_contract`.


If everything went fine, the following prompted message should be prompted:

.. code-block:: shell
Sent operation IDs:
<id with numbers and letters>
In that case, return to the node tab and have a look at the log, you should see a message like the following:
In that case, you should be able to retrieve the event with the `Hello world` emited. Use the following command inside the **client cli**:

.. code-block:: shell
<date and time> DEBUG massa_execution_worker::interface_impl: SC print: Hello world!
get_filtered_sc_output_event operation_id=<id with numbers and letters>
If everything went well you should see a message similar to this one:

.. code-block:: shell
Congratulations! You have just executed your first smart contract on a node !!
Context: Slot: (period: 627, thread: 22) at index: 0
On chain execution
Block id: VaY6zeec2am5i1eKKPzuyvhbzxVU8mts7ykSDj5usHyobJee8
Origin operation id: wHGoVbp8QSwWxEMzM5nK9CpKL3SpNmxzUF3E4pHgn8fVkJmR5
Call stack: A12Lkz8mEZ4uXPrzW9WDo5HKWRoYgeYjiQZMrwbjE6cPeRxuSfAG
Don't forget to change node's log level to INFO (value is 2).
Data: Hello world!
Store a smart contract in the blockchain
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Congratulations! You have just executed your first smart contract !

TODO
In the next tutorial you'll see a more involved example showing you how to create a Tictactoe smart-contract.
2 changes: 1 addition & 1 deletion docs/technical-doc/openrpc.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"openrpc": "1.2.4",
"info": {
"title": "Massa OpenRPC",
"version": "TEST.14.1",
"version": "TEST.14.2",
"description": "Massa OpenRPC spec",
"termsOfService": "https://open-rpc.org",
"contact": {
Expand Down
6 changes: 3 additions & 3 deletions docs/testnet/install.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ From binaries
If you just wish to run a Massa node without compiling it yourself, you
can simply download the latest binary below and go the the next step: :ref:`Running a node <testnet-running>`.

- `Windows executable <https://github.com/massalabs/massa/releases/download/TEST.14.1/massa_TEST.14.1_release_windows.zip>`_
- `Linux binary <https://github.com/massalabs/massa/releases/download/TEST.14.1/massa_TEST.14.1_release_linux.tar.gz>`_ - only works with libc2.28 at least (for example Ubuntu 20.04 and higher)
- `MacOS binary <https://github.com/massalabs/massa/releases/download/TEST.14.1/massa_TEST.14.1_release_macos.tar.gz>`_
- `Windows executable <https://github.com/massalabs/massa/releases/download/TEST.14.2/massa_TEST.14.2_release_windows.zip>`_
- `Linux binary <https://github.com/massalabs/massa/releases/download/TEST.14.2/massa_TEST.14.2_release_linux.tar.gz>`_ - only works with libc2.28 at least (for example Ubuntu 20.04 and higher)
- `MacOS binary <https://github.com/massalabs/massa/releases/download/TEST.14.2/massa_TEST.14.2_release_macos.tar.gz>`_

From source code
================
Expand Down
38 changes: 27 additions & 11 deletions massa-bootstrap/src/client.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use std::{net::SocketAddr, sync::Arc, time::Duration};

use massa_final_state::FinalState;
use massa_final_state::{ExecutedOpsStreamingStep, FinalState};
use massa_ledger_exports::get_address_from_key;
use massa_logging::massa_trace;
use massa_models::version::Version;
use massa_pos_exports::PoSCycleStreamingStep;
use massa_signature::PublicKey;
use massa_time::MassaTime;
use nom::AsBytes;
Expand Down Expand Up @@ -64,6 +65,7 @@ async fn stream_final_state(
async_pool_part,
pos_cycle_part,
pos_credits_part,
exec_ops_part,
slot,
final_state_changes,
} => {
Expand All @@ -72,12 +74,16 @@ async fn stream_final_state(
let last_last_async_id = write_final_state
.async_pool
.set_pool_part(async_pool_part.as_bytes())?;
let last_cycle = write_final_state
let last_cycle_step = write_final_state
.pos_state
.set_cycle_history_part(pos_cycle_part.as_bytes())?;
let last_credits_slot = write_final_state
.pos_state
.set_deferred_credits_part(pos_credits_part.as_bytes())?;
let last_exec_ops_step = write_final_state
.executed_ops
.set_executed_ops_part(exec_ops_part.as_bytes(), cfg.thread_count)
.unwrap();
for (changes_slot, changes) in final_state_changes.iter() {
write_final_state
.ledger
Expand All @@ -89,7 +95,10 @@ async fn stream_final_state(
changes.pos_changes.clone(),
*changes_slot,
false,
)?
)?;
write_final_state
.executed_ops
.extend(changes.executed_ops.clone());
}
write_final_state.slot = slot;
if let BootstrapClientMessage::AskFinalStatePart {
Expand All @@ -102,28 +111,35 @@ async fn stream_final_state(
}
// Set new message in case of disconnection
*next_bootstrap_message = BootstrapClientMessage::AskFinalStatePart {
last_slot: Some(slot),
last_key,
slot: Some(slot),
last_async_message_id: last_last_async_id,
last_cycle,
last_cycle_step,
last_credits_slot,
last_exec_ops_step,
};
}
BootstrapServerMessage::FinalStateFinished => {
info!("State bootstrap complete");
// Prune executed operations
let mut write_final_state = global_bootstrap_state.final_state.write();
let slot = write_final_state.slot;
write_final_state.executed_ops.prune(slot);
// Set next bootstrap message
*next_bootstrap_message = BootstrapClientMessage::AskBootstrapPeers;
return Ok(());
}
BootstrapServerMessage::SlotTooOld => {
info!("Slot is too old retry bootstrap from scratch");
*next_bootstrap_message = BootstrapClientMessage::AskFinalStatePart {
last_slot: None,
last_key: None,
slot: None,
last_async_message_id: None,
last_cycle: None,
last_cycle_step: PoSCycleStreamingStep::Started,
last_credits_slot: None,
last_exec_ops_step: ExecutedOpsStreamingStep::Started,
};
return Ok(());
panic!("Bootstrap failed, try to bootstrap again.");
}
_ => {
return Err(
Expand Down Expand Up @@ -422,14 +438,14 @@ pub async fn get_state(
}
let mut shuffled_list = bootstrap_config.bootstrap_list.clone();
shuffled_list.shuffle(&mut StdRng::from_entropy());
// Will be none when bootstrap is over
let mut next_bootstrap_message: BootstrapClientMessage =
BootstrapClientMessage::AskFinalStatePart {
last_slot: None,
last_key: None,
slot: None,
last_async_message_id: None,
last_cycle: None,
last_cycle_step: PoSCycleStreamingStep::Started,
last_credits_slot: None,
last_exec_ops_step: ExecutedOpsStreamingStep::Started,
};
let mut global_bootstrap_state = GlobalBootstrapState::new(final_state.clone());
loop {
Expand Down
Loading

0 comments on commit c09e975

Please sign in to comment.