From a2d909bebdc3a1c36bd67e8330e69a74f30b48c8 Mon Sep 17 00:00:00 2001 From: damip Date: Thu, 5 May 2022 19:02:54 +0200 Subject: [PATCH 1/3] merge main --- docs/Community-Ressources.md | 40 ++ docs/Dummy-network-generation.md | 26 ++ docs/FAQ.md | 261 +++++++++++ docs/Home.md | 35 ++ docs/Massa-Web.md | 31 ++ docs/hacking/api.md | 598 ++++++++++++++++++++++++++ docs/hacking/concurrency.md | 122 ++++++ docs/hacking/vm-block-feed.md | 96 +++++ docs/hacking/vm_ledger_interaction.md | 186 ++++++++ docs/install.md | 72 ++++ docs/routability.md | 66 +++ docs/run.md | 73 ++++ docs/staking.md | 100 +++++ docs/testnet_rules.md | 109 +++++ docs/transaction.md | 33 ++ docs/update.md | 39 ++ docs/wallet.md | 72 ++++ 17 files changed, 1959 insertions(+) create mode 100644 docs/Community-Ressources.md create mode 100644 docs/Dummy-network-generation.md create mode 100644 docs/FAQ.md create mode 100644 docs/Home.md create mode 100644 docs/Massa-Web.md create mode 100644 docs/hacking/api.md create mode 100644 docs/hacking/concurrency.md create mode 100644 docs/hacking/vm-block-feed.md create mode 100644 docs/hacking/vm_ledger_interaction.md create mode 100644 docs/install.md create mode 100644 docs/routability.md create mode 100644 docs/run.md create mode 100644 docs/staking.md create mode 100644 docs/testnet_rules.md create mode 100644 docs/transaction.md create mode 100644 docs/update.md create mode 100644 docs/wallet.md diff --git a/docs/Community-Ressources.md b/docs/Community-Ressources.md new file mode 100644 index 00000000000..839387f12f2 --- /dev/null +++ b/docs/Community-Ressources.md @@ -0,0 +1,40 @@ +# Tutorials and resources from the community + +The Massa community is growing and we want to thank everyone who is participating in the project. Some members created useful tutorials and resources and deserve to be credited for it. In this document, we are gathering links of the latest creations. + +**Please note, these are unofficial and not frequently checked by the core members. Some might be outdated or miss important information. For security reasons, we encourage you to go through the official installation process and tutorials or trusted parties. As always, use your best judgment when visiting third party links.** + +## Articles about Massa + +- [English - Presentation of Massa](https://medium.com/@unlimitedmolotnorilsk/massa-decentralization-is-unavoidable-6f903f7500da) +- [Spanish - Presentation of Massa technology](https://kimiko-cumulo.medium.com/introducci%C3%B3n-a-la-blockchain-massa-7e5fab213462) +- [Spanish - Summary of AMA episode 6](https://medium.com/@cumulo.pro/ama-con-los-cofundadores-de-massa-testnet-episodio-6-y-actualizaciones-18bc928122d7) + +## Setting up a node + +- [English - Tutorial to create a Massa node](https://medium.com/@altaycrypto/massa-creating-a-node-1065cab11d73) +- [English - Tutorial and resources to run Massa node & client on Docker](https://github.com/f-lopes/massa-docker) +- [English - Tutorial to launch a node using a VPS (outdated)](https://mycryptobit99.medium.com/massa-node-setup-guide-e238c45275ac) +- [English - How to migrate Massa node to Docker container](https://github.com/ParanormalBrothers/Massa-Node-Docker) +- [Script which sets up a node](https://github.com/WeVouT/massa) +---- +- [Russian - Article and tutorial to launch a node using a VPS](https://teletype.in/@letskynode/Massa) +---- +- [Spanish - Tutorial to launch a node](https://medium.com/@massaesp/gu%C3%ADa-automatica-de-como-crear-un-nodo-para-linux-c657a976ea36) +- [Spanish - Presentation and tutorial to launch a node](https://kimiko-cumulo.medium.com/lanza-tu-nodo-en-la-testnet-de-massa-78e9e025bc05) +---- +- [French - Article and tutorial to launch a node using a VPS](https://www.muchco.in/academy/tutoriel-creation-noeud-massa) +- [French - Tutorial to launch a node using a VPS](https://medium.com/@bouqsi/lancer-un-node-chez-massa-labs-8da7e01738c) +- [French - Security best practices article](https://medium.com/@bouqsi/security-best-practices-si-vous-lancez-un-node-validateur-99f44b520f84) + +## Tracking the activity of a node + +- [Telegram Bot to track node activity](https://t.me/massacheck_bot) +- [Telegram Bot to track node activity and network statistics](https://t.me/hekumatiarubot) +- [Website to monitor your node](https://paranormal-brothers.com/massa/) +- [Another website to monitor your node](https://grafana-massa.trend-deposits.com/d/MLcl7dt7k/massa-overview?orgId=2) +- [Script to monitor faulty blocks of your node](https://github.com/WeVouT/massa/tree/main/monitor) + +## Miscellaneous + +- [Telegram Bot answering FAQs](https://t.me/paramassa_bot) \ No newline at end of file diff --git a/docs/Dummy-network-generation.md b/docs/Dummy-network-generation.md new file mode 100644 index 00000000000..a5a8d22481e --- /dev/null +++ b/docs/Dummy-network-generation.md @@ -0,0 +1,26 @@ +# Dummy network generation + +How to launch a dummy network with custom settings and initial coins & rolls repartition + +* get a private key and associated public key and address (see wallet_generate_private_key command), these will be referenced as PRI PUB and ADR +* replace `massa-node/base_config/initial_rolls.json` content with +``` +{ + "ADR": 100 +} +``` +* replace `massa-node/base_config/initial_ledger.json` content with +``` +{ + "ADR": { + "balance": "250000000" + } +} +``` +* add or replace `massa-node/config/staking_keys.json` +``` +[ + "PRI" +] +``` +* Then do `cargo run --features test` in massa-node folder diff --git a/docs/FAQ.md b/docs/FAQ.md new file mode 100644 index 00000000000..260e23897ec --- /dev/null +++ b/docs/FAQ.md @@ -0,0 +1,261 @@ +# General questions + +## What are the hardware requirements? + +The philosophy of Massa is to be as decentralized as possible. To +fulfill this goal, we aim to have low hardware requirements so that many +people can run nodes. Right now 4 cores and 8 GB of RAM should be enough +to run a node. As the transaction rate increases, it might not be +sufficient anymore. Ultimately, we plan that the mainnet fits on a +desktop computer with 8 cores, 16 GB RAM, and 1TB disk. + +## Can it run on a VPS? + +You can use a VPS to run a node. The pros of VPS are that they have high +availability and are easy to configure. Cons are that nodes running on a +VPS can lead to centralization if a lot of nodes running on the same +provider (e.g. AWS). + +## How to keep the node running when I close the terminal? + +You can run the following command in the terminal: + + nohup cargo run --release & + +the output will go to the `nohup.out` file. You will be able to close +the terminal safely then. To kill the app you'll have to use +`pkill -f massa-node`. You can also use +[screen](https://help.ubuntu.com/community/Screen) or +[tmux](http://manpages.ubuntu.com/manpages/cosmic/man1/tmux.1.html) for +example. + +## Will Massa support smart contracts? + +We will try to support both the EVM for retro compatibility, and a +specific smart contract engine that fully leverages the Massa protocol and +allows to develop in more usual languages as well as introduces several +innovations. + +We are currently finishing the implementation of a first version of the smart contract +engine which should be released soon. + +We are planning some exciting features, such as self-wakeup, a bit like +what is introduced here: https://arxiv.org/pdf/2102.10784.pdf + +## What ports does Massa use? + +By default, Massa uses TCP port 31244 for protocol communication with +other nodes, and 31245 to bootstrap other nodes. Massa also uses TCP +port 33034 for the new private +API, and 33035 for the new public API (API v2). + +## How to restart the Node? + +- Ubuntu : ctrl + c for killing the process and + cargo run --release |& tee logs.txt` +- Windows : ctrl + c for killing the process and `cargo run --release` +- Mac Os : ctrl + c for killing the process and + cargo run --release > logs.txt 2>&1` + +## How secure are the private keys? + +Please note that the Testnet coins have NO VALUE. That being said, we are working on adding encryption on several levels before the Mainnet. + +The staking key file in the node folder and the wallet file in the client folder are currently not encrypted but it will come soon. Also, private API communication between the client and the node is not encrypted for now but it will be implemented before the Mainnet as well. + +Note that nodes don't know or trust each other, and they never exchange sensitive information, therefore cryptography is not required at that level. +A handshake is performed at the connection with another peer. We sign random bytes that the peer sent us with our private key, and same on the other side. And data that is sent after that is signed by its creator, not the node that is sending it to us. +During the bootstrap, the handshake is asymmetric. We know the public key of the bootstrap node and we expect signed messages from it, but we do not communicate our public key, nor we sign the only message we send (just random bytes). + +# Balance and wallet + +## How to migrate from one server to another without losing staked amounts and tokens? + +You need to back up the file wallet.dat and migrate it to the +massa-client folder on your new server. You also need to backup and +migrate the node_privkey.key file in massa-node/config to keep your +connectivity stats. + +If you have rolls, you also need to register the key used to buy rolls +to start staking again (see [Staking](staking.md)). + +## Why are the balances in the client and the explorer different ? + +It may mean that your node is desynchronized. +Check that your node is running, that the computer meets hardware requirements, and try restarting your node. + +## Does the command `cargo run -- --wallet wallet.dat` override my existing wallet? + +No, it loads the wallet if it exists, otherwise, it creates it. + +## Where is the wallet.dat located? + +By default, in the massa-client directory. + +# Rolls and staking + +## My rolls disappeared/were sold automatically. + +The most likely reason is that you did not produce some blocks when +selected to do so. Most frequent reasons: + +- Node not running 100% of the time during which you had + active_rolls \> 0 +- Node not being properly connected to the network 100% of the time + during which you had active_rolls \> 0 +- Node being desynchronized (which can be caused by temporary overload + if the specs are insufficient or if other programs are using + resources on the computer or because of internet connection + problems) at some point while you had active_rolls \> 0 +- The node does not having the right registered staking keys (type + staking_addresses in the client to verify that they match the + addresses in your wallet_info that have active rolls) 100% of the + time during which you had active_rolls \> 0 +- Some hosting providers have Half-duplex connection setting. + Contact hosting support and ask to switch you to full-duplex. + +Diagnostic process: + +- make sure the node is running on a computer that matches hardware requirements and that no other software is hogging ressources +- type `wallet_info` and make sure that at least one address has active rolls > 0 + - if there are no addresses listed, create a new one by calling `wallet_generate_private_key` and try the diagnostic process again + - if none of the listed addresses has non-zero active rolls, perform a new roll buy (see tutorials) and try the diagnostic process again +- type `node_get_staking_addresses` in the client: + - if the list is empty or if none of the addresses listed matches addresses that have active rolls in `wallet_info`: + - call `node_add_staking_private_keys` with the private key matching an address that has non-zero active rolls in `wallet_info` +- check your address with the online explorer: if there is a mismatch between the number of active rolls displayed in the online interface and what is returned by `wallet_info`, it might be that your node is desynchronized. Try restarting it. + +## Why are rolls automatically sold? Is it some kind of penalty/slashing? + +It is not slashing because the funds are reimbursed fully. It's more +like an implicit roll sell. + +The point is the following: for the network to be healthy, everyone with +active rolls needs to produce blocks whenever they are selected to do +so. If an address misses more than 70% of its block creation +opportunities during cycle C, all its rolls are implicitly sold at the +beginning of cycle C+3. + +## Do I need to register the keys after subsequent purchases of ROLLs, or do they get staked automatically? + +For now, they don't stake automatically. In the future, we will add a +feature allowing auto compounding. That being said, some people appear +to have done that very early in the project. Feel free to ask on the +[Discord](https://discord.com/invite/massa) server :). + +## I can buy, send, sell ROLLs and coins without fees. When should I increase the fee \>0? + +For the moment, there are only a few transactions at the same time and +so most created blocks are empty. This means that your operation will be +added to a block even if the fee is zero. We will communicate if you +need to increase the fee. + +## I am staking ROLLs but my wallet info doesn't change. When do I get my first staking rewards? + +You need to wait for your rolls to become active (around 1h45), then +depending on the number of rolls you have, you might want to wait for +more to be selected for block/endorsement production. + +# Testnet and rewards + +## How can I migrate my node from one computer/provider to another and keep my score in the Testnet Staking Reward Program? + +If you migrate your node from one computer/provider to another you +should save the private key associated with the staking address that is +registered. This private key is located in the `wallet.dat` file located +in `massa-client` folder. You can also save your node private key +`node_privkey.key` located in the `massa-node/config` folder, if you +don't then don't forget to register your new node private key to the +Discord bot. + +If your new node has a new IP address then you should not forget to +register the new IP address to the Discord bot. + +If you lost `wallet.dat` and/or `node_privkey.key`, don't panic, just +redo the whole node setup and rewards registration process and the newly +generated keys will be associated with your discord account. Past scores +won't be lost. + +## I want to stake more! Can I abuse the faucet bot to get more coins? + +You can claim testnet tokens every 24h. The tokens are worthless, you +won't have any advantage over the others by doing that. + +## Will the amount of staked Rolls affect Testnet rewards? + +No, as long as you have at least 1 roll, further roll purchases won't +change your score. + +## I can't register with the Discord bot because the node ID is already used + +If you changed your staking key, you need to register again with the bot using the `node_testnet_rewards_program_ownership_proof` command. +If you are using the same install, the bot will return the following error message: +"This node ID is already used or has already been used, please use another one!". +To solve this, you need to generate a new node ID. Stop your node and delete the `node_privkey.key` file in `massa-node/config`. You can then start your node again and you will have a new node ID. + +# Common issues + +## Ping too high issue + +Check the quality of your internet connection. Try increasing the +"max_ping" setting in your config file: + +- edit file `massa-node/config/config.toml` (create if it is absent) with the following + content: + +```toml +[bootstrap] +max_ping = 10000 # try 10000 for example +``` + +## API can't start + +- If your API can't start, e.g. with + `could not start API controller: ServerError(hyper::Error(Listen, Os { code: 98, kind: AddrInUse, message: "Address already in use" }))`, + it's probably because the default API ports 33034/33035 are already in use + on your computer. You should change the port in the config files, + both in the API and Client: + +* create/edit file `massa-node/config/config.toml` to change the port used by the API: + +```toml +[api] +bind_private = "127.0.0.1:33034" # change port here from 33034 to something else +bind_public = "0.0.0.0:33035" # change port here from 33035 to something else +``` + +- create/edit file `massa-client/config/config.toml` and put the same + port: + +```toml +[default_node] +ip = "127.0.0.1" +private_port = 33034 # change port here from 33034 to the port chosen in node's bind_private +public_port = 33035 # change port here from 33035 to the port chosen in node's bind_public +``` + +## Raspberry Pi problem "Thread 'main' panicked" + +If you encountered an error message such as: + +"Thread 'main' panicked at 'called Option::unwrap() on aNone value', models/src/hhasher.rs:35:46", this is a known problem on older Raspberry Pi, +especially with Raspbian. Try installing Debian. + +Please note, running a Massa node on a Raspberry Pi is ambitious and will probably not work that well. We don't +expect raspberry to be enough powerful to run on the mainnet. + + + +## Disable IPV6 support + +If your OS, virtual machine or provider does not support IPV6, try disabling IPV6 support on your Massa node. + +To do this, edit (or create if absent) the file `massa-node/config/config.toml` with the following contents: +```toml +[network] + bind = "0.0.0.0:31244" + +[bootstrap] + bind = "0.0.0.0:31245" +``` +then restart your node. diff --git a/docs/Home.md b/docs/Home.md new file mode 100644 index 00000000000..d85cff76db3 --- /dev/null +++ b/docs/Home.md @@ -0,0 +1,35 @@ +# Welcome to the Massa wiki! + +For project announcements, we mainly use +[Telegram](https://t.me/massanetwork), [Discord](https://discord.com/invite/massa) and we also have a [Twitter](https://twitter.com/MassaLabs) account. + +## Tutorials to join the testnet + +- [Installing a node](install) +- [Running a node](run) +- [Creating a wallet](wallet) +- [Staking](staking) +- [Routability tutorial](routability) (Optional) +- [Testnet rewards program](testnet_rules) (Optional) + +## More tutorials + +- [Updating the node](update) +- [Sending transactions](transaction) +- [Tutorials and resources from the community](Community-Ressources) + +## [FAQ](faq) and Troubleshooting + +You'll find answers to common issues and questions regarding the Massa +protocol in the [FAQ](faq). + +Don't hesitate to ask questions in the +[Discord](https://discord.com/invite/massa) testnet channel. + +## Technical documentation + +- [API](api) +- [Concurrency](concurrency) +- [Smart contract VM block feed process](vm-block-feed) +- [Resources for community builders](Dummy-network-generation) + diff --git a/docs/Massa-Web.md b/docs/Massa-Web.md new file mode 100644 index 00000000000..ab839a98be1 --- /dev/null +++ b/docs/Massa-Web.md @@ -0,0 +1,31 @@ +# Rationale + +The "code is law" rule is a cornerstone of DeFi. It states among other things that once successfully audited, a program can remain trusted. +This implies that the program of a successfully audited smart contract may never be unexpectedly changed by an outsider (note that contracts that modify their own code during runtime cannot be trusted this way in the first place, but this is visible in the code audit). Popular ETH smart contracts essentially follow that rule. + +However, most DeFi web3 apps such as https://app.uniswap.org/ are typically used through an otherwise normal website that talks to a browser plugin (typically Metamask) allowing the webpage to interact with the user's wallet and the blockchain. The website that serves as an entry point to the dapp is neither decentralized nor immutable-once-audited, thus breaking the very foundations of DeFi security. And that's how you get into situations like this one: https://www.theverge.com/2021/12/2/22814849/badgerdao-defi-120-million-hack-bitcoin-ethereum + +The goal here is to allow addresses on Massa to store not only a balance, bytecode and a datastore, but also named files. +Those files must remain small, or storing them will cost a lot to their owner. +Any address, through bytecode execution, can initialize, read and write the "files" part just like it would with the datastore. +The reason why we don't reuse the datastore for this, outside of the risk of key collisions, is for easier auditing: if the code never writes into its own bytecode nor its filestore after deployment, it is safe to assume that the stored website can't change anymore. +That's it from the point of view of the node. + +The Massa browser plugin will function like Metamask (wallet, interaction with the blockchain) but also provide extra functions: +* when an URL of the form `xxxxxxxxxxxx.massa` is typed in the address bar, the plugin will check if `xxxxxxxxxxxx` is an address +* if it's an address, the plugin will try to load the `website.zip` file from the filestore of that address, unzip it, and display its index.html (or whatever other page is requested). +* if it's not and address but something like a domain name, the plugin will interrogate a "Massa Name Service" smart contract through a readonly call to try to match the domain name to an address. This is inspired by how the Ethereum Name Service works. Then it will load the address's website as defined above. +* the website will typically contain html, css and javascript to remain lightweight. The javascript can dynamically talk to the Massa plugin to interact with the blockchain and wallet (just like Metamask) +* if the website needs heavy assets (videos, large images...) that cannot be stored on the blockchain, the plugin allows looking up optional external data on IPFS or on the normal web, but plugin settings allow users to disable the fetching of off-chain assets for maximum security. + +That way, Massa allows deploying fully decentralized code-is-law apps, as it was meant to be ! + +To close the loop, we can imagine dumping a copy of the source code of Massa and surrounding tools in the filestore of an on-chain smart contract. + +# Filestore + +From the point of the node, this functions just like another extra binary datastore in the SCE ledger, but indexed by a max-255-char string (instead of hash) and we call it the "filestore". + +# Browser plugin + +TODO diff --git a/docs/hacking/api.md b/docs/hacking/api.md new file mode 100644 index 00000000000..7623aeb0b9b --- /dev/null +++ b/docs/hacking/api.md @@ -0,0 +1,598 @@ +# Massa JSON-RPC API + +This crate exposes Rust methods (through the `Endpoints` trait) as +JSON-RPC API endpoints (thanks to the [ParityJSON-RPC](https://github.com/paritytech/jsonrpc) crate). + +**E.g.** this curl command will call endpoint `stop_node` (and stop the +locally running `massa-node`): + +```bash +curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc": "2.0", "method": "stop_node", "id": 123 }' 127.0.0.1:33034 +``` + +Endpoints are organized in 2 authorizations levels: + +## **Public** API +_a.k.a. **"user mode"** endpoints (running by default on `[::]:33035`)_ + +### `get_status` + +Summary of the current state: time, last final blocks (hash, thread, +slot, timestamp), clique count, connected nodes count. + +- No parameters. + +- Return: + +```javascript + { + "config": { + "block_reward": String, // represent an Amount in coins + "delta_f0": Number, // Used to compute finality threshold + "end_timestamp": null or Number, // millis since 1970-01-01 (only in tesnets) + "genesis_timestamp": Number, // millis since 1970-01-01 + "operation_validity_periods": Number, + "periods_per_cycle": Number, + "pos_lock_cycles": Number, + "pos_lookback_cycles": Number, + "roll_price": String, // represent an Amount in coins + "t0": Number, // millis between to slots in the same thread + "thread_count": Number + }, + "connected_nodes": { + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx": String // Node id -> ip address + }, + "consensus_stats": { + "clique_count": Number, + "end_timespan": Number,// stats time interval, millis since 1970-01-01 + "final_block_count": Number, + "final_operation_count": Number, + "staker_count": Number, + "stale_block_count": Number, + "start_timespan": // stats time interval, millis since 1970-01-01 + }, + "current_cycle": Number, + "current_time": Number, // millis since 1970-01-01 + "last_slot": { + "period": Number, + "thread": Number + }, + "network_stats": { + "active_node_count": Number, + "banned_peer_count": Number, + "in_connection_count": Number, + "known_peer_count": Number, + "out_connection_count": Number + }, + "next_slot": { + "period": Number, + "thread": Number + }, + "node_id": String, + "node_ip": null or String, // ip address if provided + "pool_stats": { + "endorsement_count": Number, + "operation_count": Number + }, +} +``` + +### `get_cliques` + +Get cliques. + +- No parameters. + +- Return: + +```javascript +[ + { + block_ids: [String], + fitness: Number, + is_blockclique: Boolean, + }, +]; +``` + +### `get_stakers` + +Returns the active stakers and their roll counts for the current cycle. + +- No parameters. + +- Return: + +```javascript +{ + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx": Number +} // Dictionnary associating staker addresses to their active roll counts +``` + +### `get_operations` + +Returns operations information associated to a given list of operations' IDs. + +- Parameters: + +```javascript +[String]. // String must be an operation Id +``` + +- Return: + +```javascript +[ + { + "id": String, // Operation id + "in_blocks": [String], // Block ids + "in_pool": Boolean, + "is_final": Boolean, + "operation": { + "content": { + "expire_period": Number,// after that period, the operation become invalid forever + "fee": String, // represent an Amount in coins + "op": { + "Transaction": { + "amount": String, // represent an Amount in coins + "recipient_address": String + } + OR + "RollBuy": { + "roll_count": Number + } + OR + "RollSell": { + "roll_count": Number + } + OR + "ExecuteSC" { + "data": [Number], // vec of bytes to execute + "max_gas": Number, // maximum amount of gas that the execution of the contract is allowed to cost. + "coins": String, // represent an Amount in coins that are spent by consensus and are available in the execution context of the contract. + "gas_price": String, // represent an Amount in coins, price per unit of gas that the caller is willing to pay for the execution. + } + }, + "sender_public_key": String + }, + "signature": String + } + } +] +``` + +### `get_endorsements` + +Get endorsements + +- Parameters: + +```javascript +[String]; // string must be an endorsement id +``` + +- Return: + +```javascript +[{ + "id": String, // EndorsementId, + "in_pool": Boolean, + "in_blocks": [String], // BlockId, + "is_final": Boolean, + "endorsement": { + "content":{ + "sender_public_key": String, + "slot": { + "period": Number, + "thread": Number + }, + "index": Number, + "endorsed_block": String // BlockId, + } + "signature": String + } + }] +``` + +### `get_block` + +Get information on a block given its hash. + +- Parameters: + +```javascript +[String]; // Block IDs +``` + +- Return: + +```javascript +{ + "id": String // BlockId, + "content": Null or { + "is_final": bool, + "is_stale": bool, + "is_in_blockclique": bool, + "block": { + "header": { + "content": { + "endorsed_block": String, // Block id + "index": Number, + "sender_public_key": String, + "slot": { // endorsed block slot: deifferent from block's slot + "period": Number, + "thread": Number + } + }, + "signature": String + } + ], + "operation_merkle_root": String, // Hash of all operations + "parents": [String], // Block ids, as many as thread count + "slot": { + "period": Number, + "thread": Number + } + }, + "signature": String + }, + "operations": [ + { + "content": { + "expire_period": Number, + "fee": String, // represent an Amount in coins + "op": { + "Transaction": { + "amount": String, // represent an Amount in coins + "recipient_address": String + } + OR + "RollBuy": { + "roll_count": Number + } + OR + "RollSell": { + "roll_count": Number + } + }, + "sender_public_key": String + }, + "signature": String + } + ] + }, + "is_final": Boolean, + "is_in_blockclique": Boolean, + "is_stale": Boolean + }, +} +``` + +### `get_graph_interval` + +Get the block graph within the specified time interval. + +- Parameters: + +```javascript +{ + "start": null or Number, // in millis since 1970-01-01, field may be omitted + "end": null or Number,// in millis since 1970-01-01, field may be omitted +} +``` + +- Return: + +```javascript +[ + { + creator: String, // public key + id: String, // Block Id + is_final: Boolean, + is_in_blockclique: Boolean, + is_stale: Boolean, + parents: [String], // as many block Ids as there are threads + slot: { + period: Number, + thread: Number, + }, + }, +]; +``` + +### `get_addresses` + +Get addresses. + +- Parameters: + +```javascript +[ + [String], // Addresses +]; +``` + +- Return: + +```javascript +[ + { + address: String, + balance: { + candidate_balance: String, // represent an Amount in coins + final_balance: String, // represent an Amount in coins + locked_balance: String, // represent an Amount in coins + }, + block_draws: [ + { + period: Number, + thread: Number, + }, + ], + blocks_created: [String], // Block ids + endorsement_draws: [ + { + slot: { + period: Number, + thread: Number, + }, + index: Number, + }, + ], + involved_in_endorsements: [String], // Endorsement Id + involved_in_operations: [String], // Operation id + production_stats: [ + // as many items as cached cycles + { + cycle: Number, + is_final: Boolean, + nok_count: Number, + ok_count: Number, + }, + ], + rolls: { + active_rolls: Number, + candidate_rolls: Number, + final_rolls: Number, + }, + thread: Number, + sce_ledger_info : { + balance: String // reprensents an amount + module: null OR [Number] // stored bytecode + datastore: [ + xxxxxxxxxxxxxxxxxxxxxx: [Number] // bytes + ] + } + }, +]; +``` + +### `send_operations` + +Adds operations to pool. Returns operations that were ok and sent to +pool. + +- Parameters: + +```javascript +[[ + { + "content": { + "expire_period": Number, + "fee": String, // represent an Amount in coins + "op": { + "Transaction": { + "amount": String, // represent an Amount in coins + "recipient_address": String + } + OR + "RollBuy": { + "roll_count": Number + } + OR + "RollSell": { + "roll_count": Number + } + }, + "sender_public_key": String + }, + "signature": String + } +]] +``` + +- Return: + +```javascript +[String], // Operation ids +``` +### `get_sc_output_event_by_slot_range` + +Returns output events by slot range. (not yet implemented) + +- Parameters: + +```javascript +{ + "start": { + "period": Number, + "thread": Number + }, + "end": { + "period": Number, + "thread": Number + } +} +``` + +- Return: + +```javascript +[ + { + "data": String, // Arbitrary json string generated by the smart contract + "context":{ + "slot": { + "period": Number, + "thread": Number + }, + "block": null OR String // block id, + "call_stack": [String], //Addresses + } + } +] +``` + +### `get_sc_output_event_by_sc_address` + +Returns output events by smart contract address. (not yet implemented) + +- Parameters: + +```javascript +String // Address +``` + +- Return: + +```javascript +[ + { + "data": String, // Arbitrary json string generated by the smart contract + "context":{ + "slot": { + "period": Number, + "thread": Number + }, + "block": null OR String // block id, + "call_stack": [String], //Addresses + } + } +] +``` +### `get_sc_output_event_by_caller_address` + +Returns output events by caller address. (not yet implemented) + +- Parameters: + +```javascript +String //Address +``` + +- Return: + +```javascript +[ + { + "data": String, // Arbitrary json string generated by the smart contract + "context":{ + "slot": { + "period": Number, + "thread": Number + }, + "block": null OR String // block id, + "call_stack": [String], //Addresses + } + } +] +``` +## **Private** API +_a.k.a. **"manager mode"** endpoints (running by default on `127.0.0.1:33034`)_ + +### `stop_node` + +Gracefully stop the node. + +- No parameters. + +- No return. + +### `node_sign_message` + +Sign message with node's key. + +- Parameter: + +```javascript +[u8]; +``` + +- Return: + +```javascript +{"public_key": String, "signature": String} +``` + +Where public_key is the public key used to sign the input and signature, +the resulting signature. + +### `add_staking_private_keys` + +Add a vec of new private keys for the node to use to stake. + +- Parameter: + +```javascript +[String]; +``` + +The strings must be private keys. + +- No return. + +### `remove_staking_addresses` + +Remove a vec of addresses used to stake. + +- Parameter: + +```javascript +[String]; +``` + +The strings must be addresses. + +- No return. + +### `get_staking_addresses` + +Return hashset of staking addresses. + +- No parameters. + +- Return: + +```javascript +[String]; +``` + +The strings are addresses. + +### `ban` + +Bans given IP addresses. + +- Parameter: + +```javascript +[String]; +``` + +The strings must be ip addresses. + +- No return. + +### `unban` + +Unbans given IP addresses. + +- Parameter: + +```javascript +[String]; +``` + +The strings must be ip addresses. + +- No return. diff --git a/docs/hacking/concurrency.md b/docs/hacking/concurrency.md new file mode 100644 index 00000000000..115397dc5c7 --- /dev/null +++ b/docs/hacking/concurrency.md @@ -0,0 +1,122 @@ +# Concurrency + +The Massa system is built mostly around message-passing. This involves +bi-directional communication between components on bounded channels, +which comes with a risk of deadlock. To manage this risk, a distinction +is made between two types of messages: + +- Events + - Examples are: `NetworkEvent`, and `ProtocolEvent`. These are + messages that can be dropped if they haven't been received, or + added to the channel buffer, before a timeout. Care should be + taken to ensure that dropping one of these does not result in + livelock. +- Commands + - Examples are: `ProtocolCommand` and `NetworkCommand`. Those + cannot be dropped. + +## How is deadlock prevented? + +When two components communicate with each other, one of these channels +should be using `_Command` type of messages, and the other `_Event`. +This ensures that if both channels are full, `_Event` messages will +start being dropped, ensuring that the `_Command` messages are handled +and the system does not deadlock. + +## What risks are left? + +First, dropping `_Event` messages could inadvertently result in the +system not being able to make progress, a so-called livelock. Secondly, +care should be taken not to introduce dependencies on `_Command` type of +messages between components, even indirectly. For example, two +components should not send each other `_Command`, not even indirectly +via another, or multiple other, component(s). + +## Current state of communication links + +- Massa-node: + - Receives events from: + - Api + - Consensus +- Consensus: + - Sends events to: + - Massa-node + - Receives events from: + - Protocol + - Sends commands to: + - Protocol + - Pool + - Receives commands from: + - Bootstrap + - Api +- Pool: + - Receives events from: + - Protocol + - Sends commands to: + - Protocol + - Receives commands from: + - Consensus + - Api +- Protocol: + - Sends events to: + - Consensus + - Pool + - Receives events from: + - Network + - Sends commands to: + - Network + - Receives commands from: + - Consensus + - Pool +- Network: + - Sends events to: + - Protocol + - Node + - Receives events from: + - Node + - Receives commands from: + - Protocol + - Bootstrap + - Api +- API: + - Sends commands to: + - Consensus + - Pool + - Network + +```mermaid +graph LR + MN[Massa-node] + C[Consensus] -->|events| MN + C -->|commands| Pr[Protocol] + C -->|commands| Po[Pool] + Po -->|commands| Pr + Pr -->|events| C + Pr -->|events| Po + Pr -->|commands| N[Network] + N -->|events| Pr + N -->|events| No[Node] + No -->|events| N + A[Api] --> |commands| C + A[Api] --> |commands| Po + A[Api] --> |commands| N + B[Bootstrap] --> |commands| C + B[Bootstrap] --> |commands| N +``` + +## Blocking relationships + +If a component has a relationship with another by sending `_Command` +type of messages than the receiving component cannot block on the +sender, which means that it cannot send `_Command` type of messages to +it, even indirectly via another, or several other, component(s). + +- Network cannot block on Protocol, Bootstrap, and Massa-node, blocks + on Node(s). +- Protocol cannot block on Consensus and Pool, blocks on Network. +- Pool cannot block on Consensus and Massa-node, blocks on Protocol. +- Consensus cannot block on Bootstrap and Massa-node, blocks on + Protocol, Pool. +- API blocks on Massa-node. +- Massa-node cannot block on API, blocks on Consensus, Pool, and + Network. diff --git a/docs/hacking/vm-block-feed.md b/docs/hacking/vm-block-feed.md new file mode 100644 index 00000000000..ffc9f2631bb --- /dev/null +++ b/docs/hacking/vm-block-feed.md @@ -0,0 +1,96 @@ +# Rationale + +This page describes how blocks and byte-code in the block graph are brought to the smart contract VM for execution. + +## Summary + +The general idea is that the Smart Contract Engine (SCE) takes an initial SCE ledger loaded from file and iteratively updates it by executing all Slots in order from (0,0) up to the current latest slot. +At each one of those slots, there might be a block (either final or in the active Blockclique) containing a certain number of ExecuteSC operations, or a miss (lack of block in the slot). ExecuteSC operations within a block are tentatively executed in the order they appear in the block. + +Each one of those ExecuteSC operations has already spent `max_gas * gas_price + coins` from the CSS ledger so that the block creator is certain to get the gas fees (they cannot be spent in-between). +When an ExecuteSC operation is executed on the SCE side, it immediately credits the block producer with `max_gas * gas_price` in the SCE ledger, then it credits the target address with `coins` in the SCE ledger, then it executes the byte-code inside the ExecuteSC operation. +If byte-code execution fails (invalid byte-code or execution error), everything is reverted except the `max_gas * gas_price` credit to the block producer and `coins` are sent back to the sender on the SCE side. + +This scheme works in theory but requires heavy optimizations in practice because not everything can be recomputed from genesis at every slot or Blockclique change, especially since old blocks are forgotten. Such optimizations include keeping only a final ledger on the SCE side and a list of changes caused by active blocks that can be applied to the final ledger on-the-fly. + +# Block sequencing + +## SCE vs CSS finality + +Block finality on the CSS side (CSS-finality) can happen in any order (see scientific paper). To ensure that final slots (blocks or misses) are taken into account in a fully sequential way on the SCE side, we introduce a stronger definition of finality on the SCE side (SCE-finality). + + +``` +A slot S is SCE-final if-and-only-if all the following criteria are met: +* all slots before B are SCE-final` +* S either contains a CSS-final block or there is a CSS-final block in the same thread at a later period +``` + +That way, we ensure that once a slot becomes SCE-final, the final SCE ledger won't ever have to be rolled back because no new blocks can appear at that slot or before it. + +The SCE-finality of a block implies its CSS-finality but the opposite may not always be true. + +## CSS: notifying SCE about Blockclique changes + +The Blockclique can change whenever a new block is added to the graph: +* another maximal clique can become the new Blockclique if its fitness becomes higher than the current Blockclique's +* a new active non-CSS-final block can be added to the Blockclique +* blocks are removed from the Blockclique when they become CSS-final + +Every time the Blockclique changes, Consensus calls `ExecutionCommandSender::blockclique_changed(..)` with the list of blocks that became CSS-final, and the full list of blocks that belong to the updated Blockclique. + +## SCE setup + +The SCE (ExecutionWorker) carries: +* a VM (that also includes a CSS-final ledger and a active slot history) +* a `last_final_slot` cursor pointing to the latest executed SCE-final slot +* a `last_active_slot` cursor pointing to the latest executed slot +* a `pending_css_final_blocks` list of CSS-final blocks that are not yet SCE-final + +## SCE: processing Blockclique change notifications + +When the SCE receives a Blockclique change notification from the CSS with parameters `new_css_final_blocks` and `blockclique_blocks`: + +### 1 - reset the SCE state back to its latest final state + +Note that this is sub-optimal as only invalidated slots should be reverted. + +* revert the VM to its latest SCE-final state by clearing its active slot history. +* set `last_active_slot = last_final_slot` + +### 2 - process CSS-final blocks + +* extend `pending_css_final_blocks` with `new_css_final_blocks` +* iterate over every slot S starting from `last_final_slot.get_next_slot()` up to the latest slot in `pending_css_final_blocks` (included) + * if there is a block B at slot S in `pending_css_final_blocks`: + * remove B from `pending_css_final_blocks` + * call the VM to execute the SCE-final block B at slot S + * set `last_active_slot = last_final_slot = S` + * otherwise, if there is a block in `pending_css_final_blocks` at a later period of the same thread as S: + * call the VM to execute an SCE-final miss at slot S + * set `last_active_slot = last_final_slot = S` + * otherwise it means that we have reached a non-SCE-final slot: + * break + +At this point, the VM has updated its final SCE ledger, and blocks that remain to be processed are in `blockclique_blocks UNION pending_css_final_blocks`. + +### 3 - process CSS-active blocks + +* define `sce_active_blocks = blockclique_blocks UNION pending_css_final_blocks` +* iterate over every slot S starting from `last_active_slot.get_next_slot()` up to the latest slot in `sce_active_blocks` (included) + * if there is a block B at slot S in `sce_active_blocks`: + * call the VM to execute the SCE-active block B at slot S + * set `last_active_slot = S` + * otherwise: + * call the VM to execute an SCE-active miss at slot S + * set `last_active_slot = S` + +At this point, the SCE has executed all SCE-active blocks. It only needs to fill up the remaining slots until now with misses. + +### 4 - fill the remaining slots with misses + +* iterate over every slot S starting from `last_active_slot.get_next_slot()` up to the latest slot at the current timestamp (included): + * call the VM to execute an SCE-active miss at slot S + * set `last_active_slot = S` + +Note that this miss-filling algorithm needs to be called again at every slot tick, even in the absence of Blockclique change notifications. diff --git a/docs/hacking/vm_ledger_interaction.md b/docs/hacking/vm_ledger_interaction.md new file mode 100644 index 00000000000..2cb96fd6e82 --- /dev/null +++ b/docs/hacking/vm_ledger_interaction.md @@ -0,0 +1,186 @@ +# Rationale + +This page descibes how the VM interacts with the SCE ledger. + +## Summary + +VM execution happens in steps: there is one execution step at every slot. +During the execution of a slot S, background async tasks at S are executed first, then the block at slot S (if any) is executed. + +The SCE ledger is a hashmap mapping an Address to a balance, optional bytecode, and a datastore hashmap mapping hashes to arbitrary bytes. + +The VM maintains a single full copy of the SCE ledger at the output of the latest SCE-final slot, +as well as an active execution step history containing the changes caused to the ledger by every active slot. +The step history can be sequentially applied on top of the SCE-final ledger to get an SCE ledger entry at the output of any active slot. + +During execution, the executed code can access the SCE ledger with read and limited write rights. + +# Design + +## SCE Ledger + +### Structure + +The SCE Ledger can become large (up to 1TB). For now, it is in RAM but this needs to be fixed. + +The SCE Ledger is represented by the `SCELedger` structure which acts as a hashmap associating an `Address` to a `SCELedgerEntry`. + +The `SCELedgerEntry` structure represents an entry in the ledger andhas the following properties: +* `balance`: the SCE balance of the address +* `opt_module`: an optional executable module +* `data: HHashMap>`: a generic datastore associating a hash to bytes + +### Ledger changes + +The `SCELedgerChanges` struct is a hashmap associating an `Address` to a `SCELedgerChange` and represents the entries of the SCE ledger that have changed. The exact change to each entry is described by the `SCELedgerChange` enum that can be: +* `Delete`: the entry was deleted +* `Set(SCELedgerEntry)`: a new entry was inserted or an existing entry was reset to a completely new value +* `Update(SCELedgerEntryUpdate)`: an existing entry was modified. The modifications are described by `SCELedgerEntryUpdate` + +The `SCELedgerEntryUpdate` struct describes modifications to an SCE ledger entry and has the following fields: +* `update_balance: Option`: optionally updates the balance of the entry to a new value +* `update_opt_module: Option>`: optionally updates the module of the entry to a new one (or to None) +* `update_data: HHashMap>>`: a list of datastore entries that have been updated to a new value (or deleted if the hashmap value is None) + + +## VM structure + +### Overview + +The VM is represented by the `VM` structure with the following properties: +* `step_history`: a history of active execution steps +* `execution_interface`: an interface for the interpreter +* `execution_context`: an execution context + +Those fields are described in the next subsections. + +### Step history + +The VM contains a `step_history` property which is a list of `StepHistoryItem` active steps that have been executed on top of the current final SCE ledger. Each `StepHistoryItem` represents the summarized consequences of a given active step and has the following properties: +* `slot`: the slot to which the step is associated +* `opt_block_id`: an optional block ID if a block is present at that slot, or None if there is a miss +* `ledger_changes`: a `SCELedgerChanges` object listing the SCE ledger changes caused by that step + +The state of an entry of the SCE ledger at the output of a given active execution step can be retrieved by taking the corresponding entry in the final SCE ledger (available in the execution context, see below) and applying ledger changes from the `step_history` one after the other until to the desired active step (included). + +### Execution interface + +TODO + +### Execution context + +The `execution_context` field of the `VM` sturct represents the context in which the current execution runs. +`ExecutionContext` has the following fields: + +* `ledger_step` is a `SCELedgerStep` that represents the state of the SCE ledger up to the latest point of the execution of the latest active step +* `max_gas` is the max amount of gas for the execution +* `coins` is the amount of coins that have been transferred to the called SC in the context of the call +* `gas_price` is the price (in coins) per unit of gas for the execution +* `slot` is the slot of the execution step +* `opt_block_id` block id being executed (None if absent) +* `opt_block_creator_addr` address of the block producer (None if block absent) +* `call_stack`: call stack listing calling addresses. The latest one is rightmost and should be the address of the called SC when applicable + +The `SCELedgerStep` struct allows accumulating changes caused by the step execution and reading the latest SCE ledger state during execution. Fields: +* `final_ledger_slot` a `FinalLedger` structure containing the current final `SCELedger` as well as the slot at the output of which the final ledger is attached +* `cumulative_history_changes` is a `SCELedgerChanges` obtained by accumulating the `ledger_changes` of all the previous elements of the VM's `step_history` +* `caused_changes` is a `SCELedgerChanges` representing all the changes that happened so far in the current execution + +In order to transparently obtain a ledger entry at the current point of the execution, `SCELedgerStep` provides convenience methods that gather entries from the final ledger, apply the `cumulative_history_changes` and then the `caused_changes`. It also provides convenience methods for applying changes to `caused_changes`. + +## SCE interaction with the VM + +### Active execution requests + +Whenever the SCE tells the VM to execute an active block or active miss at slot S (see the [VM block feed specification](vm-block-feed)), the corresponding execution step is executed by the VM and the state changes caused by the execution are compiled into a `StepHistoryItem` and added to the `step_history`. + +The detailed algorithm is the following: +* get the execution context ready by resetting `ledger_step.caused_changes` and computing `ledger_step.cumulative_history_changes` based on the `step_history` +* TODO run async background tasks +* if there is a block B at slot S: + * Note that the block would have been rejected before if the sum of the `max_gas` of its operations exceeded `config.max_block_gas` + * for every `ExecuteSC` operation Op of the block B : + * Note that Consensus has already debited `Op.max_gas*Op.gas_price+Op.coins` from Op's sender's CSS balance or rejected the block B if there wasn't enough balance to do so + * prepare the context for execution: + * make `context.ledger_step` credit Op's sender with `Op.coins` in the SCE ledger + * make `context.ledger_step` credit the producer of the block B with `Op.max_gas * Op.gas_price` in the SCE ledger + * save a snapshot (named `ledger_changes_backup`) of the `context.ledger_step.caused_changes` that will be used to rollback the step's effects on the SCE ledger backt to this point in case bytecode execution fails. This is done because on bytecode execution failure (whether it fails completely or midway) we want to credit the block producer with fees (it's not their fault !) and Op's sender with `Op.coins` (otherwise those coins will be lost !) but revert all the effects of a bytecode execution that failed midway + * parse and run (call `main()`) the bytecode of operation Op + * in case of failure (e.g. invalid bytecode), revert `context.ledger_step.caused_changes = ledger_changes_backup` +* push back the SCE ledger changes caused by the slot `StepHistoryItem { step, block_id (optional), ledger_changes: context.ledger_step.caused_changes }` into `step_history` + + +### Final execution requests + +Whenever the SCE tells the VM to execute a final block or final miss at slot S (see the [VM block feed specification](vm-block-feed)), the VM first checks if that step was already executed (it should match the first/oldest step in `step_history`). +If it matches (it should almost always), the step result is popped out of `step_history` and its `ledger_changes` are applied to the SCE final ledger. + +In the case where the step is not found at the front of `step_history`, it might mean that there was a deep blockclique change, or that there was nothing in `step_history` due to a recent bootstrap for example. In that case, `step_history` is cleared, the `Active execution requests` process described above is executed again, and its resulting history item is then applied to the final SCE ledger. + +After this process, the SCE final ledger now represents the SCE ledger state at the output of slot S. + + + +# ABIs for interacting with the SCE ledger from inside running bytecode + +TODO detail how each one works + + +``` +// gets the current execution context +get_context() -> { + // call stack + call_stack: Vec
+ // last item (stack top) is the current SC context, first item (stack bottom) is the initial caller + + // number of coins transferred to the called address during the call + transferred_coins: int + + // max gas + max_gas: int + + // gas price + gas_price: int + + // block ID in which the execution happens (only for ExecuteSC) + block_id: Option + + // are we in a read-only execution context ? + is_readonly: bool + + // remaining gas + remaining_gas +} + +// transfer coins from the current address (if any) towards another +transfer_coins(recipient_address, amount) -> Result<()> + +// get the balance of an address +get_balance(address) -> Result + +// read the bytecode of an address +get_bytecode(address) -> Result> + +// runs arbitrary bytecode in the current context by calling a function in it +run_bytecode(bytecode, function_name, parameters, max_gas, gas_price, coins) + +// create a new ledger entry and initialize it with a balance and bytecode +// returns the address of the entry +create_sc(balance: int, bytecode) -> Result
+ +// delete the current address from the ledger, sending freed coins to a recipient +self_destruct(recipient_addr) + +// calls a public method of a target SC in the context of the target SC +call(target_addr, function_name, params, max_gas, gas_price, coins) -> Result< ... Return type ? ... > + +// gets data from an addresses' storage +data_get(addr: Address, key: Hash) -> Result> + +// sets data in the current addresses' storage (insert if absent) +data_set(key: Hash, value: Vec) -> Result<()> + +// delete data in the current addresses's storage +data_remove(key: Hash) -> Result + +``` diff --git a/docs/install.md b/docs/install.md new file mode 100644 index 00000000000..e480be47377 --- /dev/null +++ b/docs/install.md @@ -0,0 +1,72 @@ +# Installing a node + +Right now 4 cores and 8 GB of RAM should be enough to run a node, but it might increase in the future. More info in the [FAQ](faq). + +## From binaries + +If you just wish to run a Massa node without compiling it yourself, you +can simply get the latest binary (download below and go the the next step: [Running a node](run)) + +- [Windows + executable](https://github.com/massalabs/massa/releases/latest/download/release_windows.zip) +- [Linux + binary](https://github.com/massalabs/massa/releases/latest/download/release_linux.zip) - only work with libc2.28 + at least (for example Ubuntu 20.04 and higher) +- [MacOS + binary](https://github.com/massalabs/massa/releases/latest/download/release_macos.zip) + +## From source code + +Otherwise, if you wish to run a Massa node from source code, here are the steps to follow: + +### On Ubuntu / MacOS + +- on Ubuntu, these libs must be installed: + `sudo apt install pkg-config curl git build-essential libssl-dev` +- install [rustup](https://www.rust-lang.org/tools/install): + `curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh` +- configure path: `source $HOME/.cargo/env` +- check rust version: `rustc --version` +- install + [nigthly](https://doc.rust-lang.org/edition-guide/rust-2018/rustup-for-managing-rust-versions.html): + `rustup toolchain install nightly` +- set it as default: `rustup default nightly` +- check rust version: `rustc --version` +- clone this repo: + `git clone --branch testnet https://github.com/massalabs/massa.git` + +### On Windows + +#### Set up your Rust environment + +- On Windows, you should first follow the indications from Microsoft + to be able to run on a Rust environment + [here](https://docs.microsoft.com/en-gb/windows/dev-environment/rust/setup). + - Install Visual Studio (recommended) or the Microsoft C++ Build + Tools + - Once Visual Studio is installed, click on C++ Build Tool. Select + on the right column called "installation details" the following + packages: + - MSCV v142 -- VS 2019 + - Windows 10 SDK + - C++ CMake tools for Windows + - Testing Tools Core Feature + - Click install on the bottom right to download & install those + packages +- Install Rust, to be downloaded + [here](https://www.rust-lang.org/tools/install) +- Install Git for windows, to be downloaded + [here](https://git-scm.com/download/win) + +#### Clone the Massa Git Repository + +- Open Windows Power Shell + + - To clone the latest distributed version, type: `git clone --branch testnet https://github.com/massalabs/massa.git` + +- Change default Rust to nightly + - Type: `rustup default nightly` + +### Next step + +- [Running a node](https://github.com/massalabs/massa/wiki/run) diff --git a/docs/routability.md b/docs/routability.md new file mode 100644 index 00000000000..47ea541185a --- /dev/null +++ b/docs/routability.md @@ -0,0 +1,66 @@ +# Routability + +## Principle + +Nodes in the Massa network need to establish connections between them to +communicate, propagate blocks and operations, and maintain consensus and +synchrony all together. + +For node A to establish a connection towards node B, node B must be +routable. This means that node B has a public IP address that can be +reached from node A and that ports TCP 31244 and TCP 31245 are open on +node B and that inbound connection on those ports are allowed by +firewalls on node B. Once such a connection is established, +communication through this connection is bidirectional, and it does not +matter anymore which one of the two nodes initiated the connection +establishment. + +If only a small number of nodes are routable, all other nodes will be +able to connect only to those routable nodes, which can overload them +and generally hurt the decentralization and security of the network, as +those few routable nodes become de-facto central communication hubs, +choke points, and single points of failure. It is therefore important to +have as many routable nodes as possible. + +In Massa, nodes are non-routable by default and require a manual +operation to be made routable. + +## How to make your node routable + +- make sure the computer on which the node is running has a static + public IP address (IPv4 or IPv6). You can retrieve the public IP + address of your computer by opening +- if the computer running the node is behind a router/NAT, you will + need to configure your router: + - if the router uses DHCP, the MAC address of the computer running the + node must be set to have a permanent DHCP lease (a local IP address + that never changes, usually of form 192.168.X.XX) + - incoming connections on TCP ports 31244 and 31245 must be directed + towards the local IP address of the computer running the node +- setup the firewall on your computer to allow incoming TCP + connections on ports 31244 and 31245 (example: + `ufw allow 31244 && ufw allow 31245` on Ubuntu, or set up the + Windows Firewall on Windows) +- edit file `massa-node/config/config.toml` (create it if absent) with the following + contents: + ```toml + [network] + routable_ip = "AAA.BBB.CCC.DDD" + ``` + where AAA.BBB.CCC.DDD should be replaced with your public IP address (not + the local one !). IPV6 is also supported. +- run the massa node +- you can then test if your ports are open by typing your public IP + address and port 31244 in + (then again with + port 31245) +- Once your node is routable, you need to send the public IP address of your node to the Discord bot. + You first need to register to the staking reward program (see the last step below). + +## Last step + +- To validate your participation in the testnet staking reward program, + you have to register with your Discord account. Write something in the + `testnet-rewards-registration` channel of our + [Discord](https://discord.com/invite/massa) and our bot will DM you + instructions. More info here: [Testnet rewards program](https://github.com/massalabs/massa/wiki/testnet_rules) diff --git a/docs/run.md b/docs/run.md new file mode 100644 index 00000000000..c0f6aa8d4f0 --- /dev/null +++ b/docs/run.md @@ -0,0 +1,73 @@ +# Running a node + +## From binaries + +Simply run the binaries you downloaded in the previous step: +Open the `massa-node` folder and run the `massa-node` excutable +Open the `massa-client` folder and run the `massa-client` excutable + +## From source code + +### On Ubuntu / MacOS + +#### Start the node + +On a first window: + +```bash +cd massa/massa-node/ +``` + +Launch the node, on Ubuntu: + +```bash +RUST_BACKTRACE=full cargo run --release |& tee logs.txt +``` + +**Or,** on macOS: + +```bash +RUST_BACKTRACE=full cargo run --release > logs.txt 2>&1 +``` + +You should leave the window opened. + +#### Start the client + +On a second window: + +```bash +cd massa/massa-client/ +``` + +Then: + +```bash +cargo run --release +``` + +Please wait until the directories are built before moving to the next step. + +### On Windows + +#### Start the Node + +- Open Windows Power Shell or Command Prompt on a first window + - Type: `cd massa` + - Type: `cd massa-node` + - Type: `cargo run --release` + +You should leave the window opened. + +#### Start the Client + +- Open Windows Power Shell or Command Prompt on a second window + - Type: `cd massa` + - Type: `cd massa-client` + - Type: `cargo run --release` + +Please wait until the directories are built before moving to the next step. + +## Next step + +- [Creating a wallet](https://github.com/massalabs/massa/wiki/wallet) diff --git a/docs/staking.md b/docs/staking.md new file mode 100644 index 00000000000..23055fa5b75 --- /dev/null +++ b/docs/staking.md @@ -0,0 +1,100 @@ +# Staking + +In Massa, the minimal number of coins required to be able to stake is +100 MAS (which is called one "roll"). The total initial supply is 500m +MAS, so in theory, there could be 5 million people staking. + +Addresses are randomly selected to stake (create blocks) in all threads, +based on the number of rolls they possess. The list of stakers and their +rolls can be seen [there](https://test.massa.net/#staking). + +Rolls can be bought with Massa coins or sold to get the coins back. If +you already have more than 100 Massa, you can continue this tutorial, +otherwise, send your address to the faucet bot in the +"testnet-faucet" channel of our [Discord](https://discord.com/invite/massa). + +## Buying rolls + +Get the address that has coins in your wallet. In the Massa client: + +```plain +wallet_info +``` + +Buy rolls with it: put your address, the number of rolls you want to +buy, and the operation fee (you can put 0): + +```plain +buy_rolls
+``` + +As an example, the command for buying 1 roll with 0 fee for the address `VkUQ5MA4niNBhAEP7uVf89tvPfUHcbgy6BrdLM9SAuFSyy9DE` +is: `buy_rolls VkUQ5MA4niNBhAEP7uVf89tvPfUHcbgy6BrdLM9SAuFSyy9DE 1 0` + + +It should take less than one minute for your roll to become final, check +with: + +```plain +wallet_info +``` + +## Telling your node to start staking with your rolls + +Get the private key that has rolls in your wallet: + +```plain +wallet_info +``` + +Register your private key so that your node start to stake with it: + +```plain +node_add_staking_private_keys +``` + +Now you should wait some time so that your rolls become active: 3 cycles +of 128 periods (one period is 32 blocks - 16 sec), so about 1h40 +minutes. + +You can check if your rolls are active with the same command: + +```plain +wallet_info +``` + +When your rolls become active, that's it! You're staking! Please note, having one +roll is enough. On the testnet, we don't value how many rolls you have, but how reliable is your node. + +You should be selected to create blocks in the different threads. + +To check when your address is selected to stake, run this command: + +```plain +get_addresses +``` + +and look at the "next draws" section. + +Also check that your balance increases, for each block or endorsement that you +create you should get a small reward. + +## Selling rolls + +If you want to get back some or all of your coins, sell rolls the same +way you bought them: + +```plain +sell_rolls
+``` + +It should take some time again for your coins to be credited, and they +will be frozen for 1 cycle before you can spend them, again check with: + +```plain +wallet_info +``` + +## Next step + +- [Routability tutorial](https://github.com/massalabs/massa/wiki/routability) (Optionnal) diff --git a/docs/testnet_rules.md b/docs/testnet_rules.md new file mode 100644 index 00000000000..1f9836e46c7 --- /dev/null +++ b/docs/testnet_rules.md @@ -0,0 +1,109 @@ +# Testnet Staking Rewards Program + +To help achieve our goal of a fully decentralized and scaled blockchain, +we designed a staking rewards program during the testnet phase. + +People that consistently run a node and produce blocks will be rewarded +mainnet Massa tokens when mainnet launches. + +Staking is what improves the security of the network. By buying rolls +(freezing your coins) and producing your share of the blocks, you help +honest nodes collectively protect against potential attackers, who must +not reach 51% of the block production. On mainnet, staking is +incentivized through block rewards: for each block produced, you get +some Massa. On testnet however, you get testnet Massa which has no +value, this is why we will reward you with mainnet Massa for learning to +set up your node and stake right now, which also helps us improve the +staking user experience. + +On July 16th we launched the first public version of Massa, the first +testnet. More than 350 nodes were connected at the same time after one +week, which overloaded our bootstrap nodes which were the only nodes +accepting connections. By setting your node up to be routable (with a +public IP), you become a real peer in the peer-to-peer network: you not +only connect to existing routable nodes, but you offer other people the +possibility to access the network through your connection. We will +therefore also reward how often your node is publicly accessible. + +## Episodes + +We have release cycles of 1 month each, called "episodes", the +first one started in August 2021. At the beginning of an episode, +participants have a few days to set up their nodes with the newest +version before scoring starts, but it's also possible to join anytime +during the episode. + +Throughout the episode, you can ask for coins in the Discord faucet (on +channel `testnet-faucet`). No need to abuse the faucet, we don't +reward you based on the number of rolls. + +At the end of an episode, all nodes stop by themselves and become +useless/unusable. Participants have to download and launch the new +version for the next episode. Make sure you keep the same node private +key and wallet! + +## Scoring Formula + +The score of a node for a given episode is the following: + + Score = 50 * (active_cycles / nb_cycles) * (produced_blocks / selected_slots) + 50 * (routable_cycles / nb_cycles) + 20 * total_maxim_factor / nb_cycles + +- 50 points of the score are based on staking: + - (`active_cycles` / `nb_cycles` ) \* (`produced_blocks` / + `selected_slots`) + - `active_cycles` is the number of cycles in the episode + during which the address had active rolls. + - `nb_cycles` is the total number of cycles in the episode. + - `produced_blocks` is the number of final blocks produced by + the staker during the episode. + - `selected_slots` is the number of final slots for which the + staker was selected to create blocks during the episode. If + `selected_slots` = 0, the staking score is set to 0. + - The maximum score is supposed to be reached if, during the + whole episode, the node has rolls and produces all blocks + when it is selected to. +- 50 points of the score are based on the routability of the node: how + often the node can be reached by other nodes. + - `routable_cycles` / `nb_cycles` + - `routable_cycles` is the number of connection trials that + resulted in a successful connection. + - Maximum score is achieved if the node can always be reached + by other nodes. +- 20 points of the score incentivize node diversity: the network is + more decentralized if nodes are spread across countries and + providers than if they are all hosted at the same location/provider. + - `total_maxim_factor` / `nb_cycles` + - `total_maxim_factor` is the total amount of `maxim_factor` + accumulated at each cycle. The `maxim_factor` is a value + between 0 and 1 representing the distance between this + node's IP address and the IP addresses of other nodes in a + given cycle. + - Maximum score is reached when running the node at home or + with a provider that is not used to run other Massa nodes. + +We encourage every person to run only one node. Running multiple nodes +with the same staking keys will result in roll slashing in the future. +Running multiple nodes with the same node_privkey.key also reduces +network health and will be a point of attention for rewards. + +## Registration + +To validate your participation in the testnet staking reward program, +you have to register with your Discord account. Write something in the +`testnet-rewards-registration` channel of our +[Discord](https://discord.com/invite/massa) and our bot will DM you +instructions. + +## From scores to rewards + +The launch of mainnet is planned for mid-2022. + +By this time, people will be able to claim their rewards through a KYC +process (most likely including video/liveness) to ensure that the same +people don't do multiple claims, and comply with KYC/AML laws. + +The testnet score of a person will be the sum of all their episode +scores. + +The mainnet reward will depend on the testnet score. More info on +mainnet rewards will come later. diff --git a/docs/transaction.md b/docs/transaction.md new file mode 100644 index 00000000000..32e81adc1e3 --- /dev/null +++ b/docs/transaction.md @@ -0,0 +1,33 @@ +# Transactions + +Once you have coins in your wallet, here is how to transfer them. + +First, check the balance of your addresses with this command in the +client: + +```plain +wallet_info +``` + +You can send a transaction from an address in your wallet that has a +positive balance to any address with this command: + +```plain +send_transaction +``` + +Change with the origin and destination addresses, and set the amount and +fee, for instance: + +```plain +send_transaction 5y1JC9eEgCkXJXWcrCxzegZaUHZ1CcKEpAYMdAHPzyDLqUvvE 2NZ25sfyN7R4UWGUFU1H6N7UqYJh8NRMMoRBev4fU27BkxhBHy 23.1 0 +``` + +As long as the blocks are not full, you can put a 0 fee. + +Now check your balance. Your candidate balance should be lower, and +after \~40 sec the transaction will be final. + +```plain +wallet_info +``` diff --git a/docs/update.md b/docs/update.md new file mode 100644 index 00000000000..a9cddedc618 --- /dev/null +++ b/docs/update.md @@ -0,0 +1,39 @@ +# Update + +If you use the binaries, simply download the latest binaries, and make sure you use the latest nightly version of rust. + +Set the latest nightly as default: +```bash +rustup default nightly +``` + +Update Rust: +```bash +rustup update +``` + + +Otherwise: + +Make sure you you have the right git repository (especially since the change from GitLab to GitHub): + +```bash +cd massa/ +git stash +git remote set-url origin https://github.com/massalabs/massa.git +``` + +Update Massa: + +```bash +git checkout testnet +git pull +``` + +After updating, enter the command `node_get_staking_addresses` in your client and make sure that it returns an address that has rolls according to `wallet_info`. + +- If `wallet_info` does not return any address, it means that you haven't backed up your wallet.dat correctly. Close the client, overwrite wallet.dat with your backup, launch the client again and try again. You can also create a new address by calling `wallet_generate_private_key`. + +- If you can't find an address in `wallet_info` that has non-zero candidate, non-zero final and non-zero active rolls, please refer to the [staking tutorial](https://github.com/massalabs/massa/wiki/staking) on getting rolls. + +- If `node_get_staking_addresses` does not return any address or does not return an address that has active_rolls according to `wallet_info`, it means you haven't backed up staking_keys.json properly. Try stopping the node, overwriting staking_keys.json with your backup, and starting the node again to try again. You can also manually add a staking private key by calling `add_staking_private_keys` with the PRIVATE KEY matching the address that has active rolls in `wallet_info` (warning: do not type the address or public key, only the PRIVATE KEY). diff --git a/docs/wallet.md b/docs/wallet.md new file mode 100644 index 00000000000..929fcee2695 --- /dev/null +++ b/docs/wallet.md @@ -0,0 +1,72 @@ +# Creating a Massa wallet + +A Massa wallet is a file that contains a list of your private keys. + +Like other blockchains, Massa uses elliptic curve cryptography for the +security of your coins (with `secp256k1`). + +It means your private key is your password allowing you to spend coins +that were sent to your address (your address is the hash of your public +key). + +Here is how to create a Massa wallet. + +## From the command line interface + +### If your client is not running + +Go to the client folder: + +```bash +cd massa/massa-client/ +``` + +Start the interactive client and load a wallet file: + +```bash +cargo run +``` + +It loads the wallet file `wallet.dat`. If it does not exist, it is +created. + +### If your client is running + +Now you can either generate a new private key (and associated public key/address): + +```plain +wallet_generate_private_key +``` + +**Or, if you already have one from a previous wallet**, you can add manually an existing private key: + +```plain +wallet_add_private_keys +``` + +The list of addresses and keys of your wallet can be accessed with: + +```plain +wallet_info +``` + +## From the graphical interface + +If you don't plan to stake or use the command-line client, you can also +create a wallet on the web interface: head to the +[explorer](https://test.massa.net), in the wallet tab. + +Click `Generate private key` then `Add`. + +This generates a new random private key from your computer randomness +which stays on your side, it is never transferred on the network. + +Now you can add more addresses or see the list of your addresses with +their associated thread and balance. + +Also, if you want to save this wallet and be able to restore it later, +click `Save wallet`, and next time directly do `Load wallet`. + +## Next step + +- [Staking](https://github.com/massalabs/massa/wiki/staking) your coins to receive rewards. From 946ddf644588230a2612337a8c4b8b499335304d Mon Sep 17 00:00:00 2001 From: Damir Vodenicarevic Date: Sat, 17 Sep 2022 13:30:16 +0200 Subject: [PATCH 2/3] add execution logs --- massa-execution-worker/src/controller.rs | 20 +++++++++++++ massa-execution-worker/src/request_queue.rs | 2 ++ massa-execution-worker/src/worker.rs | 32 +++++++++++++++++++-- 3 files changed, 52 insertions(+), 2 deletions(-) diff --git a/massa-execution-worker/src/controller.rs b/massa-execution-worker/src/controller.rs index e8ef4a78271..c6a2c469ccf 100644 --- a/massa-execution-worker/src/controller.rs +++ b/massa-execution-worker/src/controller.rs @@ -18,6 +18,7 @@ use massa_models::{block::BlockId, slot::Slot}; use massa_storage::Storage; use parking_lot::{Condvar, Mutex, RwLock}; use std::collections::{BTreeMap, HashMap}; +use std::fmt::Display; use std::sync::Arc; use tracing::info; @@ -33,6 +34,25 @@ pub(crate) struct ExecutionInputData { pub readonly_requests: RequestQueue, } +impl Display for ExecutionInputData { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!( + f, + "stop={:?}, finalized={:?}, blockclique={:?}, readonly={:?}", + self.stop, + self.finalized_blocks + .iter() + .map(|(slot, (id, _))| (*slot, *id)) + .collect::>(), + self.new_blockclique.as_ref().map(|bq| bq + .iter() + .map(|(slot, (id, _))| (*slot, *id)) + .collect::>()), + self.readonly_requests + ) + } +} + impl ExecutionInputData { /// Creates a new empty `ExecutionInputData` pub fn new(config: ExecutionConfig) -> Self { diff --git a/massa-execution-worker/src/request_queue.rs b/massa-execution-worker/src/request_queue.rs index 72cdf1a82df..53fdc236066 100644 --- a/massa-execution-worker/src/request_queue.rs +++ b/massa-execution-worker/src/request_queue.rs @@ -7,6 +7,7 @@ use std::collections::VecDeque; use std::sync::mpsc::Sender; /// Represents an execution request T coupled with an MPSC sender for a result of type R +#[derive(Debug)] pub(crate) struct RequestWithResponseSender { /// The underlying execution request request: T, @@ -47,6 +48,7 @@ impl RequestWithResponseSender { /// Structure representing an execution request queue with maximal length. /// Each request is a `RequestWithResponseSender` that comes with an MPSC sender /// to return the execution result when the execution is over (or an error). +#[derive(Debug)] pub(crate) struct RequestQueue { /// Max number of item in the queue. /// When the queue is full, extra new items are cancelled and dropped. diff --git a/massa-execution-worker/src/worker.rs b/massa-execution-worker/src/worker.rs index 10f43b92032..f8ae69d5cdb 100644 --- a/massa-execution-worker/src/worker.rs +++ b/massa-execution-worker/src/worker.rs @@ -23,7 +23,7 @@ use massa_storage::Storage; use massa_time::MassaTime; use parking_lot::{Condvar, Mutex, RwLock}; use std::{collections::HashMap, sync::Arc}; -use tracing::{info, warn}; +use tracing::{debug, info, warn}; /// Structure gathering all elements needed by the execution thread pub(crate) struct ExecutionThread { @@ -252,9 +252,13 @@ impl ExecutionThread { return false; } + debug!("entered execute_one_final_slot"); + // w-lock execution state let mut exec_state = self.execution_state.write(); + debug!("locked execution state in execute_one_final_slot"); + // get the slot just after the last executed final slot let slot = exec_state .final_cursor @@ -269,12 +273,19 @@ impl ExecutionThread { let target_id = exec_target.as_ref().map(|(b_id, _)| *b_id); // check if the final slot is cached at the front of the speculative execution history + debug!( + "execute_one_final_slot: checking cache for slot {} target {:?}", + slot, + exec_target.as_ref().map(|(s, _)| *s) + ); if let Some(exec_out) = exec_state.pop_first_execution_result() { if exec_out.slot == slot && exec_out.block_id == target_id { // speculative execution front result matches what we want to compute // apply the cached output and return exec_state.apply_final_execution_output(exec_out); + + debug!("execute_one_final_slot: found in cache, applied cache"); return true; } else { // speculative cache mismatch @@ -295,10 +306,13 @@ impl ExecutionThread { exec_state.clear_history(); // execute slot + debug!("execute_one_final_slot: execution started"); let exec_out = exec_state.execute_slot(slot, exec_target, &self.selector); + debug!("execute_one_final_slot: execution finished"); // apply execution output to final state exec_state.apply_final_execution_output(exec_out); + debug!("execute_one_final_slot: execution result applied"); true } @@ -322,7 +336,9 @@ impl ExecutionThread { /// returns true if something was executed fn execute_one_active_slot(&mut self) -> bool { // write-lock the execution state + debug!("execute_one_active_slot: execution started"); let mut exec_state = self.execution_state.write(); + debug!("execute_one_active_slot: execution state locked"); // get the next active slot let slot = exec_state @@ -333,14 +349,24 @@ impl ExecutionThread { // choose the execution target let exec_target = match self.active_slots.get(&slot) { Some(b_store) => b_store.as_ref().map(|(b_id, bs)| (*b_id, bs.clone())), - _ => return false, + _ => { + debug!("execute_one_active_slot: no target for slot {}", slot); + return false; + } }; // execute the slot + debug!( + "execute_one_active_slot: executing slot {} target = {:?}", + slot, + exec_target.as_ref().map(|(s, _)| *s) + ); let exec_out = exec_state.execute_slot(slot, exec_target, &self.selector); + debug!("execute_one_active_slot: execution sfinished"); // apply execution output to active state exec_state.apply_active_execution_output(exec_out); + debug!("execute_one_active_slot: execution state applied"); true } @@ -539,6 +565,8 @@ impl ExecutionThread { // 2 - speculative executions // 3 - read-only executions while let Some(input_data) = self.wait_loop_event() { + debug!("Execution loop triggered, input_data = {}", input_data); + // update the sequence of final slots given the newly finalized blocks self.update_final_slots(input_data.finalized_blocks); From b4fe19ca99da7f4aae744a34ca1179322bbfe1aa Mon Sep 17 00:00:00 2001 From: Damir Vodenicarevic Date: Sat, 17 Sep 2022 13:33:30 +0200 Subject: [PATCH 3/3] correct docs --- docs/Community-Ressources.md | 40 -- docs/Dummy-network-generation.md | 26 -- docs/FAQ.md | 261 ----------- docs/Home.md | 35 -- docs/Massa-Web.md | 31 -- docs/hacking/api.md | 598 -------------------------- docs/hacking/concurrency.md | 122 ------ docs/hacking/vm-block-feed.md | 96 ----- docs/hacking/vm_ledger_interaction.md | 186 -------- docs/install.md | 72 ---- docs/routability.md | 66 --- docs/run.md | 73 ---- docs/staking.md | 100 ----- docs/testnet_rules.md | 109 ----- docs/transaction.md | 33 -- docs/update.md | 39 -- docs/wallet.md | 72 ---- 17 files changed, 1959 deletions(-) delete mode 100644 docs/Community-Ressources.md delete mode 100644 docs/Dummy-network-generation.md delete mode 100644 docs/FAQ.md delete mode 100644 docs/Home.md delete mode 100644 docs/Massa-Web.md delete mode 100644 docs/hacking/api.md delete mode 100644 docs/hacking/concurrency.md delete mode 100644 docs/hacking/vm-block-feed.md delete mode 100644 docs/hacking/vm_ledger_interaction.md delete mode 100644 docs/install.md delete mode 100644 docs/routability.md delete mode 100644 docs/run.md delete mode 100644 docs/staking.md delete mode 100644 docs/testnet_rules.md delete mode 100644 docs/transaction.md delete mode 100644 docs/update.md delete mode 100644 docs/wallet.md diff --git a/docs/Community-Ressources.md b/docs/Community-Ressources.md deleted file mode 100644 index 839387f12f2..00000000000 --- a/docs/Community-Ressources.md +++ /dev/null @@ -1,40 +0,0 @@ -# Tutorials and resources from the community - -The Massa community is growing and we want to thank everyone who is participating in the project. Some members created useful tutorials and resources and deserve to be credited for it. In this document, we are gathering links of the latest creations. - -**Please note, these are unofficial and not frequently checked by the core members. Some might be outdated or miss important information. For security reasons, we encourage you to go through the official installation process and tutorials or trusted parties. As always, use your best judgment when visiting third party links.** - -## Articles about Massa - -- [English - Presentation of Massa](https://medium.com/@unlimitedmolotnorilsk/massa-decentralization-is-unavoidable-6f903f7500da) -- [Spanish - Presentation of Massa technology](https://kimiko-cumulo.medium.com/introducci%C3%B3n-a-la-blockchain-massa-7e5fab213462) -- [Spanish - Summary of AMA episode 6](https://medium.com/@cumulo.pro/ama-con-los-cofundadores-de-massa-testnet-episodio-6-y-actualizaciones-18bc928122d7) - -## Setting up a node - -- [English - Tutorial to create a Massa node](https://medium.com/@altaycrypto/massa-creating-a-node-1065cab11d73) -- [English - Tutorial and resources to run Massa node & client on Docker](https://github.com/f-lopes/massa-docker) -- [English - Tutorial to launch a node using a VPS (outdated)](https://mycryptobit99.medium.com/massa-node-setup-guide-e238c45275ac) -- [English - How to migrate Massa node to Docker container](https://github.com/ParanormalBrothers/Massa-Node-Docker) -- [Script which sets up a node](https://github.com/WeVouT/massa) ----- -- [Russian - Article and tutorial to launch a node using a VPS](https://teletype.in/@letskynode/Massa) ----- -- [Spanish - Tutorial to launch a node](https://medium.com/@massaesp/gu%C3%ADa-automatica-de-como-crear-un-nodo-para-linux-c657a976ea36) -- [Spanish - Presentation and tutorial to launch a node](https://kimiko-cumulo.medium.com/lanza-tu-nodo-en-la-testnet-de-massa-78e9e025bc05) ----- -- [French - Article and tutorial to launch a node using a VPS](https://www.muchco.in/academy/tutoriel-creation-noeud-massa) -- [French - Tutorial to launch a node using a VPS](https://medium.com/@bouqsi/lancer-un-node-chez-massa-labs-8da7e01738c) -- [French - Security best practices article](https://medium.com/@bouqsi/security-best-practices-si-vous-lancez-un-node-validateur-99f44b520f84) - -## Tracking the activity of a node - -- [Telegram Bot to track node activity](https://t.me/massacheck_bot) -- [Telegram Bot to track node activity and network statistics](https://t.me/hekumatiarubot) -- [Website to monitor your node](https://paranormal-brothers.com/massa/) -- [Another website to monitor your node](https://grafana-massa.trend-deposits.com/d/MLcl7dt7k/massa-overview?orgId=2) -- [Script to monitor faulty blocks of your node](https://github.com/WeVouT/massa/tree/main/monitor) - -## Miscellaneous - -- [Telegram Bot answering FAQs](https://t.me/paramassa_bot) \ No newline at end of file diff --git a/docs/Dummy-network-generation.md b/docs/Dummy-network-generation.md deleted file mode 100644 index a5a8d22481e..00000000000 --- a/docs/Dummy-network-generation.md +++ /dev/null @@ -1,26 +0,0 @@ -# Dummy network generation - -How to launch a dummy network with custom settings and initial coins & rolls repartition - -* get a private key and associated public key and address (see wallet_generate_private_key command), these will be referenced as PRI PUB and ADR -* replace `massa-node/base_config/initial_rolls.json` content with -``` -{ - "ADR": 100 -} -``` -* replace `massa-node/base_config/initial_ledger.json` content with -``` -{ - "ADR": { - "balance": "250000000" - } -} -``` -* add or replace `massa-node/config/staking_keys.json` -``` -[ - "PRI" -] -``` -* Then do `cargo run --features test` in massa-node folder diff --git a/docs/FAQ.md b/docs/FAQ.md deleted file mode 100644 index 260e23897ec..00000000000 --- a/docs/FAQ.md +++ /dev/null @@ -1,261 +0,0 @@ -# General questions - -## What are the hardware requirements? - -The philosophy of Massa is to be as decentralized as possible. To -fulfill this goal, we aim to have low hardware requirements so that many -people can run nodes. Right now 4 cores and 8 GB of RAM should be enough -to run a node. As the transaction rate increases, it might not be -sufficient anymore. Ultimately, we plan that the mainnet fits on a -desktop computer with 8 cores, 16 GB RAM, and 1TB disk. - -## Can it run on a VPS? - -You can use a VPS to run a node. The pros of VPS are that they have high -availability and are easy to configure. Cons are that nodes running on a -VPS can lead to centralization if a lot of nodes running on the same -provider (e.g. AWS). - -## How to keep the node running when I close the terminal? - -You can run the following command in the terminal: - - nohup cargo run --release & - -the output will go to the `nohup.out` file. You will be able to close -the terminal safely then. To kill the app you'll have to use -`pkill -f massa-node`. You can also use -[screen](https://help.ubuntu.com/community/Screen) or -[tmux](http://manpages.ubuntu.com/manpages/cosmic/man1/tmux.1.html) for -example. - -## Will Massa support smart contracts? - -We will try to support both the EVM for retro compatibility, and a -specific smart contract engine that fully leverages the Massa protocol and -allows to develop in more usual languages as well as introduces several -innovations. - -We are currently finishing the implementation of a first version of the smart contract -engine which should be released soon. - -We are planning some exciting features, such as self-wakeup, a bit like -what is introduced here: https://arxiv.org/pdf/2102.10784.pdf - -## What ports does Massa use? - -By default, Massa uses TCP port 31244 for protocol communication with -other nodes, and 31245 to bootstrap other nodes. Massa also uses TCP -port 33034 for the new private -API, and 33035 for the new public API (API v2). - -## How to restart the Node? - -- Ubuntu : ctrl + c for killing the process and - cargo run --release |& tee logs.txt` -- Windows : ctrl + c for killing the process and `cargo run --release` -- Mac Os : ctrl + c for killing the process and - cargo run --release > logs.txt 2>&1` - -## How secure are the private keys? - -Please note that the Testnet coins have NO VALUE. That being said, we are working on adding encryption on several levels before the Mainnet. - -The staking key file in the node folder and the wallet file in the client folder are currently not encrypted but it will come soon. Also, private API communication between the client and the node is not encrypted for now but it will be implemented before the Mainnet as well. - -Note that nodes don't know or trust each other, and they never exchange sensitive information, therefore cryptography is not required at that level. -A handshake is performed at the connection with another peer. We sign random bytes that the peer sent us with our private key, and same on the other side. And data that is sent after that is signed by its creator, not the node that is sending it to us. -During the bootstrap, the handshake is asymmetric. We know the public key of the bootstrap node and we expect signed messages from it, but we do not communicate our public key, nor we sign the only message we send (just random bytes). - -# Balance and wallet - -## How to migrate from one server to another without losing staked amounts and tokens? - -You need to back up the file wallet.dat and migrate it to the -massa-client folder on your new server. You also need to backup and -migrate the node_privkey.key file in massa-node/config to keep your -connectivity stats. - -If you have rolls, you also need to register the key used to buy rolls -to start staking again (see [Staking](staking.md)). - -## Why are the balances in the client and the explorer different ? - -It may mean that your node is desynchronized. -Check that your node is running, that the computer meets hardware requirements, and try restarting your node. - -## Does the command `cargo run -- --wallet wallet.dat` override my existing wallet? - -No, it loads the wallet if it exists, otherwise, it creates it. - -## Where is the wallet.dat located? - -By default, in the massa-client directory. - -# Rolls and staking - -## My rolls disappeared/were sold automatically. - -The most likely reason is that you did not produce some blocks when -selected to do so. Most frequent reasons: - -- Node not running 100% of the time during which you had - active_rolls \> 0 -- Node not being properly connected to the network 100% of the time - during which you had active_rolls \> 0 -- Node being desynchronized (which can be caused by temporary overload - if the specs are insufficient or if other programs are using - resources on the computer or because of internet connection - problems) at some point while you had active_rolls \> 0 -- The node does not having the right registered staking keys (type - staking_addresses in the client to verify that they match the - addresses in your wallet_info that have active rolls) 100% of the - time during which you had active_rolls \> 0 -- Some hosting providers have Half-duplex connection setting. - Contact hosting support and ask to switch you to full-duplex. - -Diagnostic process: - -- make sure the node is running on a computer that matches hardware requirements and that no other software is hogging ressources -- type `wallet_info` and make sure that at least one address has active rolls > 0 - - if there are no addresses listed, create a new one by calling `wallet_generate_private_key` and try the diagnostic process again - - if none of the listed addresses has non-zero active rolls, perform a new roll buy (see tutorials) and try the diagnostic process again -- type `node_get_staking_addresses` in the client: - - if the list is empty or if none of the addresses listed matches addresses that have active rolls in `wallet_info`: - - call `node_add_staking_private_keys` with the private key matching an address that has non-zero active rolls in `wallet_info` -- check your address with the online explorer: if there is a mismatch between the number of active rolls displayed in the online interface and what is returned by `wallet_info`, it might be that your node is desynchronized. Try restarting it. - -## Why are rolls automatically sold? Is it some kind of penalty/slashing? - -It is not slashing because the funds are reimbursed fully. It's more -like an implicit roll sell. - -The point is the following: for the network to be healthy, everyone with -active rolls needs to produce blocks whenever they are selected to do -so. If an address misses more than 70% of its block creation -opportunities during cycle C, all its rolls are implicitly sold at the -beginning of cycle C+3. - -## Do I need to register the keys after subsequent purchases of ROLLs, or do they get staked automatically? - -For now, they don't stake automatically. In the future, we will add a -feature allowing auto compounding. That being said, some people appear -to have done that very early in the project. Feel free to ask on the -[Discord](https://discord.com/invite/massa) server :). - -## I can buy, send, sell ROLLs and coins without fees. When should I increase the fee \>0? - -For the moment, there are only a few transactions at the same time and -so most created blocks are empty. This means that your operation will be -added to a block even if the fee is zero. We will communicate if you -need to increase the fee. - -## I am staking ROLLs but my wallet info doesn't change. When do I get my first staking rewards? - -You need to wait for your rolls to become active (around 1h45), then -depending on the number of rolls you have, you might want to wait for -more to be selected for block/endorsement production. - -# Testnet and rewards - -## How can I migrate my node from one computer/provider to another and keep my score in the Testnet Staking Reward Program? - -If you migrate your node from one computer/provider to another you -should save the private key associated with the staking address that is -registered. This private key is located in the `wallet.dat` file located -in `massa-client` folder. You can also save your node private key -`node_privkey.key` located in the `massa-node/config` folder, if you -don't then don't forget to register your new node private key to the -Discord bot. - -If your new node has a new IP address then you should not forget to -register the new IP address to the Discord bot. - -If you lost `wallet.dat` and/or `node_privkey.key`, don't panic, just -redo the whole node setup and rewards registration process and the newly -generated keys will be associated with your discord account. Past scores -won't be lost. - -## I want to stake more! Can I abuse the faucet bot to get more coins? - -You can claim testnet tokens every 24h. The tokens are worthless, you -won't have any advantage over the others by doing that. - -## Will the amount of staked Rolls affect Testnet rewards? - -No, as long as you have at least 1 roll, further roll purchases won't -change your score. - -## I can't register with the Discord bot because the node ID is already used - -If you changed your staking key, you need to register again with the bot using the `node_testnet_rewards_program_ownership_proof` command. -If you are using the same install, the bot will return the following error message: -"This node ID is already used or has already been used, please use another one!". -To solve this, you need to generate a new node ID. Stop your node and delete the `node_privkey.key` file in `massa-node/config`. You can then start your node again and you will have a new node ID. - -# Common issues - -## Ping too high issue - -Check the quality of your internet connection. Try increasing the -"max_ping" setting in your config file: - -- edit file `massa-node/config/config.toml` (create if it is absent) with the following - content: - -```toml -[bootstrap] -max_ping = 10000 # try 10000 for example -``` - -## API can't start - -- If your API can't start, e.g. with - `could not start API controller: ServerError(hyper::Error(Listen, Os { code: 98, kind: AddrInUse, message: "Address already in use" }))`, - it's probably because the default API ports 33034/33035 are already in use - on your computer. You should change the port in the config files, - both in the API and Client: - -* create/edit file `massa-node/config/config.toml` to change the port used by the API: - -```toml -[api] -bind_private = "127.0.0.1:33034" # change port here from 33034 to something else -bind_public = "0.0.0.0:33035" # change port here from 33035 to something else -``` - -- create/edit file `massa-client/config/config.toml` and put the same - port: - -```toml -[default_node] -ip = "127.0.0.1" -private_port = 33034 # change port here from 33034 to the port chosen in node's bind_private -public_port = 33035 # change port here from 33035 to the port chosen in node's bind_public -``` - -## Raspberry Pi problem "Thread 'main' panicked" - -If you encountered an error message such as: - -"Thread 'main' panicked at 'called Option::unwrap() on aNone value', models/src/hhasher.rs:35:46", this is a known problem on older Raspberry Pi, -especially with Raspbian. Try installing Debian. - -Please note, running a Massa node on a Raspberry Pi is ambitious and will probably not work that well. We don't -expect raspberry to be enough powerful to run on the mainnet. - - - -## Disable IPV6 support - -If your OS, virtual machine or provider does not support IPV6, try disabling IPV6 support on your Massa node. - -To do this, edit (or create if absent) the file `massa-node/config/config.toml` with the following contents: -```toml -[network] - bind = "0.0.0.0:31244" - -[bootstrap] - bind = "0.0.0.0:31245" -``` -then restart your node. diff --git a/docs/Home.md b/docs/Home.md deleted file mode 100644 index d85cff76db3..00000000000 --- a/docs/Home.md +++ /dev/null @@ -1,35 +0,0 @@ -# Welcome to the Massa wiki! - -For project announcements, we mainly use -[Telegram](https://t.me/massanetwork), [Discord](https://discord.com/invite/massa) and we also have a [Twitter](https://twitter.com/MassaLabs) account. - -## Tutorials to join the testnet - -- [Installing a node](install) -- [Running a node](run) -- [Creating a wallet](wallet) -- [Staking](staking) -- [Routability tutorial](routability) (Optional) -- [Testnet rewards program](testnet_rules) (Optional) - -## More tutorials - -- [Updating the node](update) -- [Sending transactions](transaction) -- [Tutorials and resources from the community](Community-Ressources) - -## [FAQ](faq) and Troubleshooting - -You'll find answers to common issues and questions regarding the Massa -protocol in the [FAQ](faq). - -Don't hesitate to ask questions in the -[Discord](https://discord.com/invite/massa) testnet channel. - -## Technical documentation - -- [API](api) -- [Concurrency](concurrency) -- [Smart contract VM block feed process](vm-block-feed) -- [Resources for community builders](Dummy-network-generation) - diff --git a/docs/Massa-Web.md b/docs/Massa-Web.md deleted file mode 100644 index ab839a98be1..00000000000 --- a/docs/Massa-Web.md +++ /dev/null @@ -1,31 +0,0 @@ -# Rationale - -The "code is law" rule is a cornerstone of DeFi. It states among other things that once successfully audited, a program can remain trusted. -This implies that the program of a successfully audited smart contract may never be unexpectedly changed by an outsider (note that contracts that modify their own code during runtime cannot be trusted this way in the first place, but this is visible in the code audit). Popular ETH smart contracts essentially follow that rule. - -However, most DeFi web3 apps such as https://app.uniswap.org/ are typically used through an otherwise normal website that talks to a browser plugin (typically Metamask) allowing the webpage to interact with the user's wallet and the blockchain. The website that serves as an entry point to the dapp is neither decentralized nor immutable-once-audited, thus breaking the very foundations of DeFi security. And that's how you get into situations like this one: https://www.theverge.com/2021/12/2/22814849/badgerdao-defi-120-million-hack-bitcoin-ethereum - -The goal here is to allow addresses on Massa to store not only a balance, bytecode and a datastore, but also named files. -Those files must remain small, or storing them will cost a lot to their owner. -Any address, through bytecode execution, can initialize, read and write the "files" part just like it would with the datastore. -The reason why we don't reuse the datastore for this, outside of the risk of key collisions, is for easier auditing: if the code never writes into its own bytecode nor its filestore after deployment, it is safe to assume that the stored website can't change anymore. -That's it from the point of view of the node. - -The Massa browser plugin will function like Metamask (wallet, interaction with the blockchain) but also provide extra functions: -* when an URL of the form `xxxxxxxxxxxx.massa` is typed in the address bar, the plugin will check if `xxxxxxxxxxxx` is an address -* if it's an address, the plugin will try to load the `website.zip` file from the filestore of that address, unzip it, and display its index.html (or whatever other page is requested). -* if it's not and address but something like a domain name, the plugin will interrogate a "Massa Name Service" smart contract through a readonly call to try to match the domain name to an address. This is inspired by how the Ethereum Name Service works. Then it will load the address's website as defined above. -* the website will typically contain html, css and javascript to remain lightweight. The javascript can dynamically talk to the Massa plugin to interact with the blockchain and wallet (just like Metamask) -* if the website needs heavy assets (videos, large images...) that cannot be stored on the blockchain, the plugin allows looking up optional external data on IPFS or on the normal web, but plugin settings allow users to disable the fetching of off-chain assets for maximum security. - -That way, Massa allows deploying fully decentralized code-is-law apps, as it was meant to be ! - -To close the loop, we can imagine dumping a copy of the source code of Massa and surrounding tools in the filestore of an on-chain smart contract. - -# Filestore - -From the point of the node, this functions just like another extra binary datastore in the SCE ledger, but indexed by a max-255-char string (instead of hash) and we call it the "filestore". - -# Browser plugin - -TODO diff --git a/docs/hacking/api.md b/docs/hacking/api.md deleted file mode 100644 index 7623aeb0b9b..00000000000 --- a/docs/hacking/api.md +++ /dev/null @@ -1,598 +0,0 @@ -# Massa JSON-RPC API - -This crate exposes Rust methods (through the `Endpoints` trait) as -JSON-RPC API endpoints (thanks to the [ParityJSON-RPC](https://github.com/paritytech/jsonrpc) crate). - -**E.g.** this curl command will call endpoint `stop_node` (and stop the -locally running `massa-node`): - -```bash -curl -X POST -H "Content-Type: application/json" -d '{"jsonrpc": "2.0", "method": "stop_node", "id": 123 }' 127.0.0.1:33034 -``` - -Endpoints are organized in 2 authorizations levels: - -## **Public** API -_a.k.a. **"user mode"** endpoints (running by default on `[::]:33035`)_ - -### `get_status` - -Summary of the current state: time, last final blocks (hash, thread, -slot, timestamp), clique count, connected nodes count. - -- No parameters. - -- Return: - -```javascript - { - "config": { - "block_reward": String, // represent an Amount in coins - "delta_f0": Number, // Used to compute finality threshold - "end_timestamp": null or Number, // millis since 1970-01-01 (only in tesnets) - "genesis_timestamp": Number, // millis since 1970-01-01 - "operation_validity_periods": Number, - "periods_per_cycle": Number, - "pos_lock_cycles": Number, - "pos_lookback_cycles": Number, - "roll_price": String, // represent an Amount in coins - "t0": Number, // millis between to slots in the same thread - "thread_count": Number - }, - "connected_nodes": { - "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx": String // Node id -> ip address - }, - "consensus_stats": { - "clique_count": Number, - "end_timespan": Number,// stats time interval, millis since 1970-01-01 - "final_block_count": Number, - "final_operation_count": Number, - "staker_count": Number, - "stale_block_count": Number, - "start_timespan": // stats time interval, millis since 1970-01-01 - }, - "current_cycle": Number, - "current_time": Number, // millis since 1970-01-01 - "last_slot": { - "period": Number, - "thread": Number - }, - "network_stats": { - "active_node_count": Number, - "banned_peer_count": Number, - "in_connection_count": Number, - "known_peer_count": Number, - "out_connection_count": Number - }, - "next_slot": { - "period": Number, - "thread": Number - }, - "node_id": String, - "node_ip": null or String, // ip address if provided - "pool_stats": { - "endorsement_count": Number, - "operation_count": Number - }, -} -``` - -### `get_cliques` - -Get cliques. - -- No parameters. - -- Return: - -```javascript -[ - { - block_ids: [String], - fitness: Number, - is_blockclique: Boolean, - }, -]; -``` - -### `get_stakers` - -Returns the active stakers and their roll counts for the current cycle. - -- No parameters. - -- Return: - -```javascript -{ - "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx": Number -} // Dictionnary associating staker addresses to their active roll counts -``` - -### `get_operations` - -Returns operations information associated to a given list of operations' IDs. - -- Parameters: - -```javascript -[String]. // String must be an operation Id -``` - -- Return: - -```javascript -[ - { - "id": String, // Operation id - "in_blocks": [String], // Block ids - "in_pool": Boolean, - "is_final": Boolean, - "operation": { - "content": { - "expire_period": Number,// after that period, the operation become invalid forever - "fee": String, // represent an Amount in coins - "op": { - "Transaction": { - "amount": String, // represent an Amount in coins - "recipient_address": String - } - OR - "RollBuy": { - "roll_count": Number - } - OR - "RollSell": { - "roll_count": Number - } - OR - "ExecuteSC" { - "data": [Number], // vec of bytes to execute - "max_gas": Number, // maximum amount of gas that the execution of the contract is allowed to cost. - "coins": String, // represent an Amount in coins that are spent by consensus and are available in the execution context of the contract. - "gas_price": String, // represent an Amount in coins, price per unit of gas that the caller is willing to pay for the execution. - } - }, - "sender_public_key": String - }, - "signature": String - } - } -] -``` - -### `get_endorsements` - -Get endorsements - -- Parameters: - -```javascript -[String]; // string must be an endorsement id -``` - -- Return: - -```javascript -[{ - "id": String, // EndorsementId, - "in_pool": Boolean, - "in_blocks": [String], // BlockId, - "is_final": Boolean, - "endorsement": { - "content":{ - "sender_public_key": String, - "slot": { - "period": Number, - "thread": Number - }, - "index": Number, - "endorsed_block": String // BlockId, - } - "signature": String - } - }] -``` - -### `get_block` - -Get information on a block given its hash. - -- Parameters: - -```javascript -[String]; // Block IDs -``` - -- Return: - -```javascript -{ - "id": String // BlockId, - "content": Null or { - "is_final": bool, - "is_stale": bool, - "is_in_blockclique": bool, - "block": { - "header": { - "content": { - "endorsed_block": String, // Block id - "index": Number, - "sender_public_key": String, - "slot": { // endorsed block slot: deifferent from block's slot - "period": Number, - "thread": Number - } - }, - "signature": String - } - ], - "operation_merkle_root": String, // Hash of all operations - "parents": [String], // Block ids, as many as thread count - "slot": { - "period": Number, - "thread": Number - } - }, - "signature": String - }, - "operations": [ - { - "content": { - "expire_period": Number, - "fee": String, // represent an Amount in coins - "op": { - "Transaction": { - "amount": String, // represent an Amount in coins - "recipient_address": String - } - OR - "RollBuy": { - "roll_count": Number - } - OR - "RollSell": { - "roll_count": Number - } - }, - "sender_public_key": String - }, - "signature": String - } - ] - }, - "is_final": Boolean, - "is_in_blockclique": Boolean, - "is_stale": Boolean - }, -} -``` - -### `get_graph_interval` - -Get the block graph within the specified time interval. - -- Parameters: - -```javascript -{ - "start": null or Number, // in millis since 1970-01-01, field may be omitted - "end": null or Number,// in millis since 1970-01-01, field may be omitted -} -``` - -- Return: - -```javascript -[ - { - creator: String, // public key - id: String, // Block Id - is_final: Boolean, - is_in_blockclique: Boolean, - is_stale: Boolean, - parents: [String], // as many block Ids as there are threads - slot: { - period: Number, - thread: Number, - }, - }, -]; -``` - -### `get_addresses` - -Get addresses. - -- Parameters: - -```javascript -[ - [String], // Addresses -]; -``` - -- Return: - -```javascript -[ - { - address: String, - balance: { - candidate_balance: String, // represent an Amount in coins - final_balance: String, // represent an Amount in coins - locked_balance: String, // represent an Amount in coins - }, - block_draws: [ - { - period: Number, - thread: Number, - }, - ], - blocks_created: [String], // Block ids - endorsement_draws: [ - { - slot: { - period: Number, - thread: Number, - }, - index: Number, - }, - ], - involved_in_endorsements: [String], // Endorsement Id - involved_in_operations: [String], // Operation id - production_stats: [ - // as many items as cached cycles - { - cycle: Number, - is_final: Boolean, - nok_count: Number, - ok_count: Number, - }, - ], - rolls: { - active_rolls: Number, - candidate_rolls: Number, - final_rolls: Number, - }, - thread: Number, - sce_ledger_info : { - balance: String // reprensents an amount - module: null OR [Number] // stored bytecode - datastore: [ - xxxxxxxxxxxxxxxxxxxxxx: [Number] // bytes - ] - } - }, -]; -``` - -### `send_operations` - -Adds operations to pool. Returns operations that were ok and sent to -pool. - -- Parameters: - -```javascript -[[ - { - "content": { - "expire_period": Number, - "fee": String, // represent an Amount in coins - "op": { - "Transaction": { - "amount": String, // represent an Amount in coins - "recipient_address": String - } - OR - "RollBuy": { - "roll_count": Number - } - OR - "RollSell": { - "roll_count": Number - } - }, - "sender_public_key": String - }, - "signature": String - } -]] -``` - -- Return: - -```javascript -[String], // Operation ids -``` -### `get_sc_output_event_by_slot_range` - -Returns output events by slot range. (not yet implemented) - -- Parameters: - -```javascript -{ - "start": { - "period": Number, - "thread": Number - }, - "end": { - "period": Number, - "thread": Number - } -} -``` - -- Return: - -```javascript -[ - { - "data": String, // Arbitrary json string generated by the smart contract - "context":{ - "slot": { - "period": Number, - "thread": Number - }, - "block": null OR String // block id, - "call_stack": [String], //Addresses - } - } -] -``` - -### `get_sc_output_event_by_sc_address` - -Returns output events by smart contract address. (not yet implemented) - -- Parameters: - -```javascript -String // Address -``` - -- Return: - -```javascript -[ - { - "data": String, // Arbitrary json string generated by the smart contract - "context":{ - "slot": { - "period": Number, - "thread": Number - }, - "block": null OR String // block id, - "call_stack": [String], //Addresses - } - } -] -``` -### `get_sc_output_event_by_caller_address` - -Returns output events by caller address. (not yet implemented) - -- Parameters: - -```javascript -String //Address -``` - -- Return: - -```javascript -[ - { - "data": String, // Arbitrary json string generated by the smart contract - "context":{ - "slot": { - "period": Number, - "thread": Number - }, - "block": null OR String // block id, - "call_stack": [String], //Addresses - } - } -] -``` -## **Private** API -_a.k.a. **"manager mode"** endpoints (running by default on `127.0.0.1:33034`)_ - -### `stop_node` - -Gracefully stop the node. - -- No parameters. - -- No return. - -### `node_sign_message` - -Sign message with node's key. - -- Parameter: - -```javascript -[u8]; -``` - -- Return: - -```javascript -{"public_key": String, "signature": String} -``` - -Where public_key is the public key used to sign the input and signature, -the resulting signature. - -### `add_staking_private_keys` - -Add a vec of new private keys for the node to use to stake. - -- Parameter: - -```javascript -[String]; -``` - -The strings must be private keys. - -- No return. - -### `remove_staking_addresses` - -Remove a vec of addresses used to stake. - -- Parameter: - -```javascript -[String]; -``` - -The strings must be addresses. - -- No return. - -### `get_staking_addresses` - -Return hashset of staking addresses. - -- No parameters. - -- Return: - -```javascript -[String]; -``` - -The strings are addresses. - -### `ban` - -Bans given IP addresses. - -- Parameter: - -```javascript -[String]; -``` - -The strings must be ip addresses. - -- No return. - -### `unban` - -Unbans given IP addresses. - -- Parameter: - -```javascript -[String]; -``` - -The strings must be ip addresses. - -- No return. diff --git a/docs/hacking/concurrency.md b/docs/hacking/concurrency.md deleted file mode 100644 index 115397dc5c7..00000000000 --- a/docs/hacking/concurrency.md +++ /dev/null @@ -1,122 +0,0 @@ -# Concurrency - -The Massa system is built mostly around message-passing. This involves -bi-directional communication between components on bounded channels, -which comes with a risk of deadlock. To manage this risk, a distinction -is made between two types of messages: - -- Events - - Examples are: `NetworkEvent`, and `ProtocolEvent`. These are - messages that can be dropped if they haven't been received, or - added to the channel buffer, before a timeout. Care should be - taken to ensure that dropping one of these does not result in - livelock. -- Commands - - Examples are: `ProtocolCommand` and `NetworkCommand`. Those - cannot be dropped. - -## How is deadlock prevented? - -When two components communicate with each other, one of these channels -should be using `_Command` type of messages, and the other `_Event`. -This ensures that if both channels are full, `_Event` messages will -start being dropped, ensuring that the `_Command` messages are handled -and the system does not deadlock. - -## What risks are left? - -First, dropping `_Event` messages could inadvertently result in the -system not being able to make progress, a so-called livelock. Secondly, -care should be taken not to introduce dependencies on `_Command` type of -messages between components, even indirectly. For example, two -components should not send each other `_Command`, not even indirectly -via another, or multiple other, component(s). - -## Current state of communication links - -- Massa-node: - - Receives events from: - - Api - - Consensus -- Consensus: - - Sends events to: - - Massa-node - - Receives events from: - - Protocol - - Sends commands to: - - Protocol - - Pool - - Receives commands from: - - Bootstrap - - Api -- Pool: - - Receives events from: - - Protocol - - Sends commands to: - - Protocol - - Receives commands from: - - Consensus - - Api -- Protocol: - - Sends events to: - - Consensus - - Pool - - Receives events from: - - Network - - Sends commands to: - - Network - - Receives commands from: - - Consensus - - Pool -- Network: - - Sends events to: - - Protocol - - Node - - Receives events from: - - Node - - Receives commands from: - - Protocol - - Bootstrap - - Api -- API: - - Sends commands to: - - Consensus - - Pool - - Network - -```mermaid -graph LR - MN[Massa-node] - C[Consensus] -->|events| MN - C -->|commands| Pr[Protocol] - C -->|commands| Po[Pool] - Po -->|commands| Pr - Pr -->|events| C - Pr -->|events| Po - Pr -->|commands| N[Network] - N -->|events| Pr - N -->|events| No[Node] - No -->|events| N - A[Api] --> |commands| C - A[Api] --> |commands| Po - A[Api] --> |commands| N - B[Bootstrap] --> |commands| C - B[Bootstrap] --> |commands| N -``` - -## Blocking relationships - -If a component has a relationship with another by sending `_Command` -type of messages than the receiving component cannot block on the -sender, which means that it cannot send `_Command` type of messages to -it, even indirectly via another, or several other, component(s). - -- Network cannot block on Protocol, Bootstrap, and Massa-node, blocks - on Node(s). -- Protocol cannot block on Consensus and Pool, blocks on Network. -- Pool cannot block on Consensus and Massa-node, blocks on Protocol. -- Consensus cannot block on Bootstrap and Massa-node, blocks on - Protocol, Pool. -- API blocks on Massa-node. -- Massa-node cannot block on API, blocks on Consensus, Pool, and - Network. diff --git a/docs/hacking/vm-block-feed.md b/docs/hacking/vm-block-feed.md deleted file mode 100644 index ffc9f2631bb..00000000000 --- a/docs/hacking/vm-block-feed.md +++ /dev/null @@ -1,96 +0,0 @@ -# Rationale - -This page describes how blocks and byte-code in the block graph are brought to the smart contract VM for execution. - -## Summary - -The general idea is that the Smart Contract Engine (SCE) takes an initial SCE ledger loaded from file and iteratively updates it by executing all Slots in order from (0,0) up to the current latest slot. -At each one of those slots, there might be a block (either final or in the active Blockclique) containing a certain number of ExecuteSC operations, or a miss (lack of block in the slot). ExecuteSC operations within a block are tentatively executed in the order they appear in the block. - -Each one of those ExecuteSC operations has already spent `max_gas * gas_price + coins` from the CSS ledger so that the block creator is certain to get the gas fees (they cannot be spent in-between). -When an ExecuteSC operation is executed on the SCE side, it immediately credits the block producer with `max_gas * gas_price` in the SCE ledger, then it credits the target address with `coins` in the SCE ledger, then it executes the byte-code inside the ExecuteSC operation. -If byte-code execution fails (invalid byte-code or execution error), everything is reverted except the `max_gas * gas_price` credit to the block producer and `coins` are sent back to the sender on the SCE side. - -This scheme works in theory but requires heavy optimizations in practice because not everything can be recomputed from genesis at every slot or Blockclique change, especially since old blocks are forgotten. Such optimizations include keeping only a final ledger on the SCE side and a list of changes caused by active blocks that can be applied to the final ledger on-the-fly. - -# Block sequencing - -## SCE vs CSS finality - -Block finality on the CSS side (CSS-finality) can happen in any order (see scientific paper). To ensure that final slots (blocks or misses) are taken into account in a fully sequential way on the SCE side, we introduce a stronger definition of finality on the SCE side (SCE-finality). - - -``` -A slot S is SCE-final if-and-only-if all the following criteria are met: -* all slots before B are SCE-final` -* S either contains a CSS-final block or there is a CSS-final block in the same thread at a later period -``` - -That way, we ensure that once a slot becomes SCE-final, the final SCE ledger won't ever have to be rolled back because no new blocks can appear at that slot or before it. - -The SCE-finality of a block implies its CSS-finality but the opposite may not always be true. - -## CSS: notifying SCE about Blockclique changes - -The Blockclique can change whenever a new block is added to the graph: -* another maximal clique can become the new Blockclique if its fitness becomes higher than the current Blockclique's -* a new active non-CSS-final block can be added to the Blockclique -* blocks are removed from the Blockclique when they become CSS-final - -Every time the Blockclique changes, Consensus calls `ExecutionCommandSender::blockclique_changed(..)` with the list of blocks that became CSS-final, and the full list of blocks that belong to the updated Blockclique. - -## SCE setup - -The SCE (ExecutionWorker) carries: -* a VM (that also includes a CSS-final ledger and a active slot history) -* a `last_final_slot` cursor pointing to the latest executed SCE-final slot -* a `last_active_slot` cursor pointing to the latest executed slot -* a `pending_css_final_blocks` list of CSS-final blocks that are not yet SCE-final - -## SCE: processing Blockclique change notifications - -When the SCE receives a Blockclique change notification from the CSS with parameters `new_css_final_blocks` and `blockclique_blocks`: - -### 1 - reset the SCE state back to its latest final state - -Note that this is sub-optimal as only invalidated slots should be reverted. - -* revert the VM to its latest SCE-final state by clearing its active slot history. -* set `last_active_slot = last_final_slot` - -### 2 - process CSS-final blocks - -* extend `pending_css_final_blocks` with `new_css_final_blocks` -* iterate over every slot S starting from `last_final_slot.get_next_slot()` up to the latest slot in `pending_css_final_blocks` (included) - * if there is a block B at slot S in `pending_css_final_blocks`: - * remove B from `pending_css_final_blocks` - * call the VM to execute the SCE-final block B at slot S - * set `last_active_slot = last_final_slot = S` - * otherwise, if there is a block in `pending_css_final_blocks` at a later period of the same thread as S: - * call the VM to execute an SCE-final miss at slot S - * set `last_active_slot = last_final_slot = S` - * otherwise it means that we have reached a non-SCE-final slot: - * break - -At this point, the VM has updated its final SCE ledger, and blocks that remain to be processed are in `blockclique_blocks UNION pending_css_final_blocks`. - -### 3 - process CSS-active blocks - -* define `sce_active_blocks = blockclique_blocks UNION pending_css_final_blocks` -* iterate over every slot S starting from `last_active_slot.get_next_slot()` up to the latest slot in `sce_active_blocks` (included) - * if there is a block B at slot S in `sce_active_blocks`: - * call the VM to execute the SCE-active block B at slot S - * set `last_active_slot = S` - * otherwise: - * call the VM to execute an SCE-active miss at slot S - * set `last_active_slot = S` - -At this point, the SCE has executed all SCE-active blocks. It only needs to fill up the remaining slots until now with misses. - -### 4 - fill the remaining slots with misses - -* iterate over every slot S starting from `last_active_slot.get_next_slot()` up to the latest slot at the current timestamp (included): - * call the VM to execute an SCE-active miss at slot S - * set `last_active_slot = S` - -Note that this miss-filling algorithm needs to be called again at every slot tick, even in the absence of Blockclique change notifications. diff --git a/docs/hacking/vm_ledger_interaction.md b/docs/hacking/vm_ledger_interaction.md deleted file mode 100644 index 2cb96fd6e82..00000000000 --- a/docs/hacking/vm_ledger_interaction.md +++ /dev/null @@ -1,186 +0,0 @@ -# Rationale - -This page descibes how the VM interacts with the SCE ledger. - -## Summary - -VM execution happens in steps: there is one execution step at every slot. -During the execution of a slot S, background async tasks at S are executed first, then the block at slot S (if any) is executed. - -The SCE ledger is a hashmap mapping an Address to a balance, optional bytecode, and a datastore hashmap mapping hashes to arbitrary bytes. - -The VM maintains a single full copy of the SCE ledger at the output of the latest SCE-final slot, -as well as an active execution step history containing the changes caused to the ledger by every active slot. -The step history can be sequentially applied on top of the SCE-final ledger to get an SCE ledger entry at the output of any active slot. - -During execution, the executed code can access the SCE ledger with read and limited write rights. - -# Design - -## SCE Ledger - -### Structure - -The SCE Ledger can become large (up to 1TB). For now, it is in RAM but this needs to be fixed. - -The SCE Ledger is represented by the `SCELedger` structure which acts as a hashmap associating an `Address` to a `SCELedgerEntry`. - -The `SCELedgerEntry` structure represents an entry in the ledger andhas the following properties: -* `balance`: the SCE balance of the address -* `opt_module`: an optional executable module -* `data: HHashMap>`: a generic datastore associating a hash to bytes - -### Ledger changes - -The `SCELedgerChanges` struct is a hashmap associating an `Address` to a `SCELedgerChange` and represents the entries of the SCE ledger that have changed. The exact change to each entry is described by the `SCELedgerChange` enum that can be: -* `Delete`: the entry was deleted -* `Set(SCELedgerEntry)`: a new entry was inserted or an existing entry was reset to a completely new value -* `Update(SCELedgerEntryUpdate)`: an existing entry was modified. The modifications are described by `SCELedgerEntryUpdate` - -The `SCELedgerEntryUpdate` struct describes modifications to an SCE ledger entry and has the following fields: -* `update_balance: Option`: optionally updates the balance of the entry to a new value -* `update_opt_module: Option>`: optionally updates the module of the entry to a new one (or to None) -* `update_data: HHashMap>>`: a list of datastore entries that have been updated to a new value (or deleted if the hashmap value is None) - - -## VM structure - -### Overview - -The VM is represented by the `VM` structure with the following properties: -* `step_history`: a history of active execution steps -* `execution_interface`: an interface for the interpreter -* `execution_context`: an execution context - -Those fields are described in the next subsections. - -### Step history - -The VM contains a `step_history` property which is a list of `StepHistoryItem` active steps that have been executed on top of the current final SCE ledger. Each `StepHistoryItem` represents the summarized consequences of a given active step and has the following properties: -* `slot`: the slot to which the step is associated -* `opt_block_id`: an optional block ID if a block is present at that slot, or None if there is a miss -* `ledger_changes`: a `SCELedgerChanges` object listing the SCE ledger changes caused by that step - -The state of an entry of the SCE ledger at the output of a given active execution step can be retrieved by taking the corresponding entry in the final SCE ledger (available in the execution context, see below) and applying ledger changes from the `step_history` one after the other until to the desired active step (included). - -### Execution interface - -TODO - -### Execution context - -The `execution_context` field of the `VM` sturct represents the context in which the current execution runs. -`ExecutionContext` has the following fields: - -* `ledger_step` is a `SCELedgerStep` that represents the state of the SCE ledger up to the latest point of the execution of the latest active step -* `max_gas` is the max amount of gas for the execution -* `coins` is the amount of coins that have been transferred to the called SC in the context of the call -* `gas_price` is the price (in coins) per unit of gas for the execution -* `slot` is the slot of the execution step -* `opt_block_id` block id being executed (None if absent) -* `opt_block_creator_addr` address of the block producer (None if block absent) -* `call_stack`: call stack listing calling addresses. The latest one is rightmost and should be the address of the called SC when applicable - -The `SCELedgerStep` struct allows accumulating changes caused by the step execution and reading the latest SCE ledger state during execution. Fields: -* `final_ledger_slot` a `FinalLedger` structure containing the current final `SCELedger` as well as the slot at the output of which the final ledger is attached -* `cumulative_history_changes` is a `SCELedgerChanges` obtained by accumulating the `ledger_changes` of all the previous elements of the VM's `step_history` -* `caused_changes` is a `SCELedgerChanges` representing all the changes that happened so far in the current execution - -In order to transparently obtain a ledger entry at the current point of the execution, `SCELedgerStep` provides convenience methods that gather entries from the final ledger, apply the `cumulative_history_changes` and then the `caused_changes`. It also provides convenience methods for applying changes to `caused_changes`. - -## SCE interaction with the VM - -### Active execution requests - -Whenever the SCE tells the VM to execute an active block or active miss at slot S (see the [VM block feed specification](vm-block-feed)), the corresponding execution step is executed by the VM and the state changes caused by the execution are compiled into a `StepHistoryItem` and added to the `step_history`. - -The detailed algorithm is the following: -* get the execution context ready by resetting `ledger_step.caused_changes` and computing `ledger_step.cumulative_history_changes` based on the `step_history` -* TODO run async background tasks -* if there is a block B at slot S: - * Note that the block would have been rejected before if the sum of the `max_gas` of its operations exceeded `config.max_block_gas` - * for every `ExecuteSC` operation Op of the block B : - * Note that Consensus has already debited `Op.max_gas*Op.gas_price+Op.coins` from Op's sender's CSS balance or rejected the block B if there wasn't enough balance to do so - * prepare the context for execution: - * make `context.ledger_step` credit Op's sender with `Op.coins` in the SCE ledger - * make `context.ledger_step` credit the producer of the block B with `Op.max_gas * Op.gas_price` in the SCE ledger - * save a snapshot (named `ledger_changes_backup`) of the `context.ledger_step.caused_changes` that will be used to rollback the step's effects on the SCE ledger backt to this point in case bytecode execution fails. This is done because on bytecode execution failure (whether it fails completely or midway) we want to credit the block producer with fees (it's not their fault !) and Op's sender with `Op.coins` (otherwise those coins will be lost !) but revert all the effects of a bytecode execution that failed midway - * parse and run (call `main()`) the bytecode of operation Op - * in case of failure (e.g. invalid bytecode), revert `context.ledger_step.caused_changes = ledger_changes_backup` -* push back the SCE ledger changes caused by the slot `StepHistoryItem { step, block_id (optional), ledger_changes: context.ledger_step.caused_changes }` into `step_history` - - -### Final execution requests - -Whenever the SCE tells the VM to execute a final block or final miss at slot S (see the [VM block feed specification](vm-block-feed)), the VM first checks if that step was already executed (it should match the first/oldest step in `step_history`). -If it matches (it should almost always), the step result is popped out of `step_history` and its `ledger_changes` are applied to the SCE final ledger. - -In the case where the step is not found at the front of `step_history`, it might mean that there was a deep blockclique change, or that there was nothing in `step_history` due to a recent bootstrap for example. In that case, `step_history` is cleared, the `Active execution requests` process described above is executed again, and its resulting history item is then applied to the final SCE ledger. - -After this process, the SCE final ledger now represents the SCE ledger state at the output of slot S. - - - -# ABIs for interacting with the SCE ledger from inside running bytecode - -TODO detail how each one works - - -``` -// gets the current execution context -get_context() -> { - // call stack - call_stack: Vec
- // last item (stack top) is the current SC context, first item (stack bottom) is the initial caller - - // number of coins transferred to the called address during the call - transferred_coins: int - - // max gas - max_gas: int - - // gas price - gas_price: int - - // block ID in which the execution happens (only for ExecuteSC) - block_id: Option - - // are we in a read-only execution context ? - is_readonly: bool - - // remaining gas - remaining_gas -} - -// transfer coins from the current address (if any) towards another -transfer_coins(recipient_address, amount) -> Result<()> - -// get the balance of an address -get_balance(address) -> Result - -// read the bytecode of an address -get_bytecode(address) -> Result> - -// runs arbitrary bytecode in the current context by calling a function in it -run_bytecode(bytecode, function_name, parameters, max_gas, gas_price, coins) - -// create a new ledger entry and initialize it with a balance and bytecode -// returns the address of the entry -create_sc(balance: int, bytecode) -> Result
- -// delete the current address from the ledger, sending freed coins to a recipient -self_destruct(recipient_addr) - -// calls a public method of a target SC in the context of the target SC -call(target_addr, function_name, params, max_gas, gas_price, coins) -> Result< ... Return type ? ... > - -// gets data from an addresses' storage -data_get(addr: Address, key: Hash) -> Result> - -// sets data in the current addresses' storage (insert if absent) -data_set(key: Hash, value: Vec) -> Result<()> - -// delete data in the current addresses's storage -data_remove(key: Hash) -> Result - -``` diff --git a/docs/install.md b/docs/install.md deleted file mode 100644 index e480be47377..00000000000 --- a/docs/install.md +++ /dev/null @@ -1,72 +0,0 @@ -# Installing a node - -Right now 4 cores and 8 GB of RAM should be enough to run a node, but it might increase in the future. More info in the [FAQ](faq). - -## From binaries - -If you just wish to run a Massa node without compiling it yourself, you -can simply get the latest binary (download below and go the the next step: [Running a node](run)) - -- [Windows - executable](https://github.com/massalabs/massa/releases/latest/download/release_windows.zip) -- [Linux - binary](https://github.com/massalabs/massa/releases/latest/download/release_linux.zip) - only work with libc2.28 - at least (for example Ubuntu 20.04 and higher) -- [MacOS - binary](https://github.com/massalabs/massa/releases/latest/download/release_macos.zip) - -## From source code - -Otherwise, if you wish to run a Massa node from source code, here are the steps to follow: - -### On Ubuntu / MacOS - -- on Ubuntu, these libs must be installed: - `sudo apt install pkg-config curl git build-essential libssl-dev` -- install [rustup](https://www.rust-lang.org/tools/install): - `curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh` -- configure path: `source $HOME/.cargo/env` -- check rust version: `rustc --version` -- install - [nigthly](https://doc.rust-lang.org/edition-guide/rust-2018/rustup-for-managing-rust-versions.html): - `rustup toolchain install nightly` -- set it as default: `rustup default nightly` -- check rust version: `rustc --version` -- clone this repo: - `git clone --branch testnet https://github.com/massalabs/massa.git` - -### On Windows - -#### Set up your Rust environment - -- On Windows, you should first follow the indications from Microsoft - to be able to run on a Rust environment - [here](https://docs.microsoft.com/en-gb/windows/dev-environment/rust/setup). - - Install Visual Studio (recommended) or the Microsoft C++ Build - Tools - - Once Visual Studio is installed, click on C++ Build Tool. Select - on the right column called "installation details" the following - packages: - - MSCV v142 -- VS 2019 - - Windows 10 SDK - - C++ CMake tools for Windows - - Testing Tools Core Feature - - Click install on the bottom right to download & install those - packages -- Install Rust, to be downloaded - [here](https://www.rust-lang.org/tools/install) -- Install Git for windows, to be downloaded - [here](https://git-scm.com/download/win) - -#### Clone the Massa Git Repository - -- Open Windows Power Shell - - - To clone the latest distributed version, type: `git clone --branch testnet https://github.com/massalabs/massa.git` - -- Change default Rust to nightly - - Type: `rustup default nightly` - -### Next step - -- [Running a node](https://github.com/massalabs/massa/wiki/run) diff --git a/docs/routability.md b/docs/routability.md deleted file mode 100644 index 47ea541185a..00000000000 --- a/docs/routability.md +++ /dev/null @@ -1,66 +0,0 @@ -# Routability - -## Principle - -Nodes in the Massa network need to establish connections between them to -communicate, propagate blocks and operations, and maintain consensus and -synchrony all together. - -For node A to establish a connection towards node B, node B must be -routable. This means that node B has a public IP address that can be -reached from node A and that ports TCP 31244 and TCP 31245 are open on -node B and that inbound connection on those ports are allowed by -firewalls on node B. Once such a connection is established, -communication through this connection is bidirectional, and it does not -matter anymore which one of the two nodes initiated the connection -establishment. - -If only a small number of nodes are routable, all other nodes will be -able to connect only to those routable nodes, which can overload them -and generally hurt the decentralization and security of the network, as -those few routable nodes become de-facto central communication hubs, -choke points, and single points of failure. It is therefore important to -have as many routable nodes as possible. - -In Massa, nodes are non-routable by default and require a manual -operation to be made routable. - -## How to make your node routable - -- make sure the computer on which the node is running has a static - public IP address (IPv4 or IPv6). You can retrieve the public IP - address of your computer by opening -- if the computer running the node is behind a router/NAT, you will - need to configure your router: - - if the router uses DHCP, the MAC address of the computer running the - node must be set to have a permanent DHCP lease (a local IP address - that never changes, usually of form 192.168.X.XX) - - incoming connections on TCP ports 31244 and 31245 must be directed - towards the local IP address of the computer running the node -- setup the firewall on your computer to allow incoming TCP - connections on ports 31244 and 31245 (example: - `ufw allow 31244 && ufw allow 31245` on Ubuntu, or set up the - Windows Firewall on Windows) -- edit file `massa-node/config/config.toml` (create it if absent) with the following - contents: - ```toml - [network] - routable_ip = "AAA.BBB.CCC.DDD" - ``` - where AAA.BBB.CCC.DDD should be replaced with your public IP address (not - the local one !). IPV6 is also supported. -- run the massa node -- you can then test if your ports are open by typing your public IP - address and port 31244 in - (then again with - port 31245) -- Once your node is routable, you need to send the public IP address of your node to the Discord bot. - You first need to register to the staking reward program (see the last step below). - -## Last step - -- To validate your participation in the testnet staking reward program, - you have to register with your Discord account. Write something in the - `testnet-rewards-registration` channel of our - [Discord](https://discord.com/invite/massa) and our bot will DM you - instructions. More info here: [Testnet rewards program](https://github.com/massalabs/massa/wiki/testnet_rules) diff --git a/docs/run.md b/docs/run.md deleted file mode 100644 index c0f6aa8d4f0..00000000000 --- a/docs/run.md +++ /dev/null @@ -1,73 +0,0 @@ -# Running a node - -## From binaries - -Simply run the binaries you downloaded in the previous step: -Open the `massa-node` folder and run the `massa-node` excutable -Open the `massa-client` folder and run the `massa-client` excutable - -## From source code - -### On Ubuntu / MacOS - -#### Start the node - -On a first window: - -```bash -cd massa/massa-node/ -``` - -Launch the node, on Ubuntu: - -```bash -RUST_BACKTRACE=full cargo run --release |& tee logs.txt -``` - -**Or,** on macOS: - -```bash -RUST_BACKTRACE=full cargo run --release > logs.txt 2>&1 -``` - -You should leave the window opened. - -#### Start the client - -On a second window: - -```bash -cd massa/massa-client/ -``` - -Then: - -```bash -cargo run --release -``` - -Please wait until the directories are built before moving to the next step. - -### On Windows - -#### Start the Node - -- Open Windows Power Shell or Command Prompt on a first window - - Type: `cd massa` - - Type: `cd massa-node` - - Type: `cargo run --release` - -You should leave the window opened. - -#### Start the Client - -- Open Windows Power Shell or Command Prompt on a second window - - Type: `cd massa` - - Type: `cd massa-client` - - Type: `cargo run --release` - -Please wait until the directories are built before moving to the next step. - -## Next step - -- [Creating a wallet](https://github.com/massalabs/massa/wiki/wallet) diff --git a/docs/staking.md b/docs/staking.md deleted file mode 100644 index 23055fa5b75..00000000000 --- a/docs/staking.md +++ /dev/null @@ -1,100 +0,0 @@ -# Staking - -In Massa, the minimal number of coins required to be able to stake is -100 MAS (which is called one "roll"). The total initial supply is 500m -MAS, so in theory, there could be 5 million people staking. - -Addresses are randomly selected to stake (create blocks) in all threads, -based on the number of rolls they possess. The list of stakers and their -rolls can be seen [there](https://test.massa.net/#staking). - -Rolls can be bought with Massa coins or sold to get the coins back. If -you already have more than 100 Massa, you can continue this tutorial, -otherwise, send your address to the faucet bot in the -"testnet-faucet" channel of our [Discord](https://discord.com/invite/massa). - -## Buying rolls - -Get the address that has coins in your wallet. In the Massa client: - -```plain -wallet_info -``` - -Buy rolls with it: put your address, the number of rolls you want to -buy, and the operation fee (you can put 0): - -```plain -buy_rolls
-``` - -As an example, the command for buying 1 roll with 0 fee for the address `VkUQ5MA4niNBhAEP7uVf89tvPfUHcbgy6BrdLM9SAuFSyy9DE` -is: `buy_rolls VkUQ5MA4niNBhAEP7uVf89tvPfUHcbgy6BrdLM9SAuFSyy9DE 1 0` - - -It should take less than one minute for your roll to become final, check -with: - -```plain -wallet_info -``` - -## Telling your node to start staking with your rolls - -Get the private key that has rolls in your wallet: - -```plain -wallet_info -``` - -Register your private key so that your node start to stake with it: - -```plain -node_add_staking_private_keys -``` - -Now you should wait some time so that your rolls become active: 3 cycles -of 128 periods (one period is 32 blocks - 16 sec), so about 1h40 -minutes. - -You can check if your rolls are active with the same command: - -```plain -wallet_info -``` - -When your rolls become active, that's it! You're staking! Please note, having one -roll is enough. On the testnet, we don't value how many rolls you have, but how reliable is your node. - -You should be selected to create blocks in the different threads. - -To check when your address is selected to stake, run this command: - -```plain -get_addresses -``` - -and look at the "next draws" section. - -Also check that your balance increases, for each block or endorsement that you -create you should get a small reward. - -## Selling rolls - -If you want to get back some or all of your coins, sell rolls the same -way you bought them: - -```plain -sell_rolls
-``` - -It should take some time again for your coins to be credited, and they -will be frozen for 1 cycle before you can spend them, again check with: - -```plain -wallet_info -``` - -## Next step - -- [Routability tutorial](https://github.com/massalabs/massa/wiki/routability) (Optionnal) diff --git a/docs/testnet_rules.md b/docs/testnet_rules.md deleted file mode 100644 index 1f9836e46c7..00000000000 --- a/docs/testnet_rules.md +++ /dev/null @@ -1,109 +0,0 @@ -# Testnet Staking Rewards Program - -To help achieve our goal of a fully decentralized and scaled blockchain, -we designed a staking rewards program during the testnet phase. - -People that consistently run a node and produce blocks will be rewarded -mainnet Massa tokens when mainnet launches. - -Staking is what improves the security of the network. By buying rolls -(freezing your coins) and producing your share of the blocks, you help -honest nodes collectively protect against potential attackers, who must -not reach 51% of the block production. On mainnet, staking is -incentivized through block rewards: for each block produced, you get -some Massa. On testnet however, you get testnet Massa which has no -value, this is why we will reward you with mainnet Massa for learning to -set up your node and stake right now, which also helps us improve the -staking user experience. - -On July 16th we launched the first public version of Massa, the first -testnet. More than 350 nodes were connected at the same time after one -week, which overloaded our bootstrap nodes which were the only nodes -accepting connections. By setting your node up to be routable (with a -public IP), you become a real peer in the peer-to-peer network: you not -only connect to existing routable nodes, but you offer other people the -possibility to access the network through your connection. We will -therefore also reward how often your node is publicly accessible. - -## Episodes - -We have release cycles of 1 month each, called "episodes", the -first one started in August 2021. At the beginning of an episode, -participants have a few days to set up their nodes with the newest -version before scoring starts, but it's also possible to join anytime -during the episode. - -Throughout the episode, you can ask for coins in the Discord faucet (on -channel `testnet-faucet`). No need to abuse the faucet, we don't -reward you based on the number of rolls. - -At the end of an episode, all nodes stop by themselves and become -useless/unusable. Participants have to download and launch the new -version for the next episode. Make sure you keep the same node private -key and wallet! - -## Scoring Formula - -The score of a node for a given episode is the following: - - Score = 50 * (active_cycles / nb_cycles) * (produced_blocks / selected_slots) + 50 * (routable_cycles / nb_cycles) + 20 * total_maxim_factor / nb_cycles - -- 50 points of the score are based on staking: - - (`active_cycles` / `nb_cycles` ) \* (`produced_blocks` / - `selected_slots`) - - `active_cycles` is the number of cycles in the episode - during which the address had active rolls. - - `nb_cycles` is the total number of cycles in the episode. - - `produced_blocks` is the number of final blocks produced by - the staker during the episode. - - `selected_slots` is the number of final slots for which the - staker was selected to create blocks during the episode. If - `selected_slots` = 0, the staking score is set to 0. - - The maximum score is supposed to be reached if, during the - whole episode, the node has rolls and produces all blocks - when it is selected to. -- 50 points of the score are based on the routability of the node: how - often the node can be reached by other nodes. - - `routable_cycles` / `nb_cycles` - - `routable_cycles` is the number of connection trials that - resulted in a successful connection. - - Maximum score is achieved if the node can always be reached - by other nodes. -- 20 points of the score incentivize node diversity: the network is - more decentralized if nodes are spread across countries and - providers than if they are all hosted at the same location/provider. - - `total_maxim_factor` / `nb_cycles` - - `total_maxim_factor` is the total amount of `maxim_factor` - accumulated at each cycle. The `maxim_factor` is a value - between 0 and 1 representing the distance between this - node's IP address and the IP addresses of other nodes in a - given cycle. - - Maximum score is reached when running the node at home or - with a provider that is not used to run other Massa nodes. - -We encourage every person to run only one node. Running multiple nodes -with the same staking keys will result in roll slashing in the future. -Running multiple nodes with the same node_privkey.key also reduces -network health and will be a point of attention for rewards. - -## Registration - -To validate your participation in the testnet staking reward program, -you have to register with your Discord account. Write something in the -`testnet-rewards-registration` channel of our -[Discord](https://discord.com/invite/massa) and our bot will DM you -instructions. - -## From scores to rewards - -The launch of mainnet is planned for mid-2022. - -By this time, people will be able to claim their rewards through a KYC -process (most likely including video/liveness) to ensure that the same -people don't do multiple claims, and comply with KYC/AML laws. - -The testnet score of a person will be the sum of all their episode -scores. - -The mainnet reward will depend on the testnet score. More info on -mainnet rewards will come later. diff --git a/docs/transaction.md b/docs/transaction.md deleted file mode 100644 index 32e81adc1e3..00000000000 --- a/docs/transaction.md +++ /dev/null @@ -1,33 +0,0 @@ -# Transactions - -Once you have coins in your wallet, here is how to transfer them. - -First, check the balance of your addresses with this command in the -client: - -```plain -wallet_info -``` - -You can send a transaction from an address in your wallet that has a -positive balance to any address with this command: - -```plain -send_transaction -``` - -Change with the origin and destination addresses, and set the amount and -fee, for instance: - -```plain -send_transaction 5y1JC9eEgCkXJXWcrCxzegZaUHZ1CcKEpAYMdAHPzyDLqUvvE 2NZ25sfyN7R4UWGUFU1H6N7UqYJh8NRMMoRBev4fU27BkxhBHy 23.1 0 -``` - -As long as the blocks are not full, you can put a 0 fee. - -Now check your balance. Your candidate balance should be lower, and -after \~40 sec the transaction will be final. - -```plain -wallet_info -``` diff --git a/docs/update.md b/docs/update.md deleted file mode 100644 index a9cddedc618..00000000000 --- a/docs/update.md +++ /dev/null @@ -1,39 +0,0 @@ -# Update - -If you use the binaries, simply download the latest binaries, and make sure you use the latest nightly version of rust. - -Set the latest nightly as default: -```bash -rustup default nightly -``` - -Update Rust: -```bash -rustup update -``` - - -Otherwise: - -Make sure you you have the right git repository (especially since the change from GitLab to GitHub): - -```bash -cd massa/ -git stash -git remote set-url origin https://github.com/massalabs/massa.git -``` - -Update Massa: - -```bash -git checkout testnet -git pull -``` - -After updating, enter the command `node_get_staking_addresses` in your client and make sure that it returns an address that has rolls according to `wallet_info`. - -- If `wallet_info` does not return any address, it means that you haven't backed up your wallet.dat correctly. Close the client, overwrite wallet.dat with your backup, launch the client again and try again. You can also create a new address by calling `wallet_generate_private_key`. - -- If you can't find an address in `wallet_info` that has non-zero candidate, non-zero final and non-zero active rolls, please refer to the [staking tutorial](https://github.com/massalabs/massa/wiki/staking) on getting rolls. - -- If `node_get_staking_addresses` does not return any address or does not return an address that has active_rolls according to `wallet_info`, it means you haven't backed up staking_keys.json properly. Try stopping the node, overwriting staking_keys.json with your backup, and starting the node again to try again. You can also manually add a staking private key by calling `add_staking_private_keys` with the PRIVATE KEY matching the address that has active rolls in `wallet_info` (warning: do not type the address or public key, only the PRIVATE KEY). diff --git a/docs/wallet.md b/docs/wallet.md deleted file mode 100644 index 929fcee2695..00000000000 --- a/docs/wallet.md +++ /dev/null @@ -1,72 +0,0 @@ -# Creating a Massa wallet - -A Massa wallet is a file that contains a list of your private keys. - -Like other blockchains, Massa uses elliptic curve cryptography for the -security of your coins (with `secp256k1`). - -It means your private key is your password allowing you to spend coins -that were sent to your address (your address is the hash of your public -key). - -Here is how to create a Massa wallet. - -## From the command line interface - -### If your client is not running - -Go to the client folder: - -```bash -cd massa/massa-client/ -``` - -Start the interactive client and load a wallet file: - -```bash -cargo run -``` - -It loads the wallet file `wallet.dat`. If it does not exist, it is -created. - -### If your client is running - -Now you can either generate a new private key (and associated public key/address): - -```plain -wallet_generate_private_key -``` - -**Or, if you already have one from a previous wallet**, you can add manually an existing private key: - -```plain -wallet_add_private_keys -``` - -The list of addresses and keys of your wallet can be accessed with: - -```plain -wallet_info -``` - -## From the graphical interface - -If you don't plan to stake or use the command-line client, you can also -create a wallet on the web interface: head to the -[explorer](https://test.massa.net), in the wallet tab. - -Click `Generate private key` then `Add`. - -This generates a new random private key from your computer randomness -which stays on your side, it is never transferred on the network. - -Now you can add more addresses or see the list of your addresses with -their associated thread and balance. - -Also, if you want to save this wallet and be able to restore it later, -click `Save wallet`, and next time directly do `Load wallet`. - -## Next step - -- [Staking](https://github.com/massalabs/massa/wiki/staking) your coins to receive rewards.