Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Documentation of System Contracts #3514

Open
wants to merge 25 commits into
base: docs
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
233e63b
make directory smart-contract and make spaces for future updating.
eanzhao Nov 27, 2023
6a5ca38
Initial commit of genesis contract doc.
eanzhao Nov 28, 2023
9291ff7
Fix smart-contract/index.rst
eanzhao Nov 28, 2023
a910016
Add titles to each system contract doc.
eanzhao Nov 28, 2023
49e6aea
Tune subtitles of genesis contract.
eanzhao Nov 28, 2023
474e12f
Optimize genesis contract doc.
eanzhao Nov 28, 2023
cbe6546
Improve genesis contract doc with acs0 explained.
eanzhao Nov 29, 2023
192456a
Commit 2 more diagrams for deploying and updating contracts.
eanzhao Nov 30, 2023
bded01b
Explained 5 main methods of aedpos contract.
eanzhao Nov 30, 2023
860bd32
Commit lib definition, generation and calculation doc
eanzhao Dec 1, 2023
c3a6617
fix a ref.
eanzhao Dec 1, 2023
f8ef99f
move puml files and images to separated dirs.
eanzhao Dec 4, 2023
fce2544
Initial commit of crosschain contract.
eanzhao Dec 4, 2023
6a28eb6
Initial commit of MultiToken Contract.
eanzhao Dec 5, 2023
38d2adc
Complete Transfer
eanzhao Dec 5, 2023
0cf919d
Commit token creation doc.
eanzhao Dec 5, 2023
6ab65d4
Fix literal_block
eanzhao Dec 5, 2023
b4b399a
Explained erc20 equivalent methods.
eanzhao Dec 6, 2023
54a537e
Explained external_info usage.
eanzhao Dec 6, 2023
807acbb
Initial commit of Vote Contract.
eanzhao Dec 7, 2023
bcacc75
Complete Vote Contract doc.
eanzhao Dec 7, 2023
cb3d962
Initial commit of Profit Contract doc.
eanzhao Dec 8, 2023
8e87c51
Add beneficiary management doc
eanzhao Dec 12, 2023
022e15d
Remove unfinished docs.
eanzhao Jan 22, 2024
09be4e9
Remove unfinished doc files.
eanzhao Jan 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs-sphinx/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ Welcome to AElf's official documentation!
Smart Contract API <reference/smart-contract-api/index>
Acs Introduction <reference/acs/index>
Command-line Interface <reference/cli/index>
Smart Contract <reference/smart-contract/index>


.. toctree::
Expand Down
535 changes: 535 additions & 0 deletions docs-sphinx/reference/smart-contract/consensus-contract.md

Large diffs are not rendered by default.

113 changes: 113 additions & 0 deletions docs-sphinx/reference/smart-contract/cross-chain-contract.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
# CrossChain Contract

## Overview

Unlike other blockchain ecosystem, aelf blockchain has a built-in cross chain mechanism.

We have designed a structure of **MainChain**-**SideChains**, where a MainChain can have multiple SideChains.
The MainChain can act as a data center, regularly indexing the cross chain information generated by its SideChains,
and then submitting the cross chain information of any SideChain to all other SideChains.

This way, not only can cross chain interaction occur between the MainChain and its SideChains, but also between its SideChains with the help of the MainChain.

In addition, each SideChain can also serve as the MainChain, serving as the data center for the next level of SideChains.

In this article, we will discuss:

- Modules for implementing cross chain mechanism
- Cross chain mechanism technical foundation
- The process of initializing a SideChain
- The process of cross chain token transfer
- Merkle Path generation

## Modules for implementing cross chain mechanism

Cross chain mechanism on aelf is a very independent module,
and there was a requirement in the initial design:
assuming that aelf nodes are unaware of their ability of cross-chain indexing and verification.
The structuring of aelf code is better as a result, but it also increases the complexity of cross chain modules to some extent.

![Cross Chain Class Diagram](images/cross-chain-class-diagram.png)

`AElf.CrossChain.Core` is responsible for the core implementation logic of the cross chain mechanism, including:

- New SideChain creation.
- Cross chain indexing.
- Cross chain indexing related transactions' generation.

In order to ensure that communication between the MainChain and SideChains does not affect communication between aelf nodes,
we have specifically implemented a GRpc module for cross chain communication, that is `AElf.CrossChain.Grpc`.

In addition, we all know that the modification of blockchain status (StateDb) requires the execution of transactions.
The interfaces for these transactions are defined in [acs7](https://docs.aelf.io/en/latest/reference/acs/acs7.html).

**CrossChain Contract**, which is the focus of this article's upcoming discussion,
is responsible for implementing these interfaces.

## Cross chain mechanism technical foundation

As explained in [this](https://aelf-ean.readthedocs.io/en/latest/architecture/cross-chain/crosschain-verification.html) document,
we use **Merkle Tree** to achieve cross chain validation.

Every piece of information that needs to be transmitted from the MainChain to SideChains, or from a SideChain to the MainChain and other SideChains,
will serve as a leaf node and participate in building the Merkle Tree.

This transmission process is completed through the `AElf.CrossChain.Grpc` module mentioned above.
Which means that the MainChain node must be able to establish GRpc connections with all the SideChains nodes.
This is similar to the **Merged Mining**:
The nodes elected on the MainChain will also be responsible for block production on all SideChains.

In the implementation of the aelf cross chain mechanism, the leaf nodes of Merkle Tree are composed of two entities:

- TransactionId
- TransactionResultStatus

`TransactionId` is computed from a `Transaction` entity.
And `TransactionResultStatus` is an enum value, here's the definition:

```protobuf
enum TransactionResultStatus {
// The execution result of the transaction does not exist.
NOT_EXISTED = 0;
// The transaction is in the transaction pool waiting to be packaged.
PENDING = 1;
// Transaction execution failed.
FAILED = 2;
// The transaction was successfully executed and successfully packaged into a block.
MINED = 3;
// When executed in parallel, there are conflicts with other transactions.
CONFLICT = 4;
// The transaction is waiting for validation.
PENDING_VALIDATION = 5;
// Transaction validation failed.
NODE_VALIDATION_FAILED = 6;
}
```

Regardless of the execution result of a transaction,
its related information will be condensed into the hash value calculated by these two data,
which will be used as leaf nodes to construct the Merkle Tree.

Subsequently, the **Merkle Tree Root** will be transmitted to the SideChain or MainChain through the GRpc module.

![Verify Parent Chain Tx](images/verify-parent-chain-tx.png)

Finally, on another chain,
**Merkle Path** can be used to verify that the information of a certain transaction exists and has been successfully executed by the user.

Taking the above image as an example, transactions are executed in the MainChain, the verification process happens in the SideChain.
The Merkle Path to validate the existence and successful execution of the transaction represented using `Hash3` is:
`[Hash3, Hash4, Hash12, Hash5656, Root]`.
(Hash3 = `Hash(TransactionId, TransactionResultStatus.Mined)`)

If the Merkle Path is successfully validated and the `Root` does exist within the SideChain CrossChain Contract,
then the code following the validation logic can be executed in the SideChain.

## The process of initializing a SideChain

![Initialize SideChain](images/initialize-side-chain.png)

## The process of cross chain token transfer

![Cross Chain Token Transfer](images/cross-chain-token-transfer.png)

217 changes: 217 additions & 0 deletions docs-sphinx/reference/smart-contract/genesis-contract.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
# Genesis Contract

## Overview

Genesis Contract, also known as the Zero Contract, is mainly used to deploy and maintain smart contracts running on the aelf blockchain.

This contract will be deployed first when aelf blockchain launched so that it can be used to deploy other smart contracts.

To achieve this purpose, the Genesis Contract implements the following methods defined in [acs0](https://docs.aelf.io/en/latest/reference/acs/acs0.html):

```protobuf
service ACS0 {
// Deploy a system smart contract on chain and return the address of the system contract deployed.
rpc DeploySystemSmartContract (SystemContractDeploymentInput) returns (aelf.Address) {
}

// Deploy a smart contract on chain and return the address of the contract deployed.
rpc DeploySmartContract (ContractDeploymentInput) returns (aelf.Address) {
}

// Update a smart contract on chain.
rpc UpdateSmartContract (ContractUpdateInput) returns (aelf.Address) {
}

// and others.
// ...
}
```

Therefore, developers can deploy (and update) their own smart contracts by interacting with the Genesis Contract.

In this article, we will discuss:

- Implementation of deploy and update contracts
- How the contract will be loaded to the smart contract execution environment
- The current process of deploying and updating aelf smart contracts
- Other details of the Genesis Contract

## `SmartContractRegistration` and `ContractInfo`

There is a critical data structure defined in `aelf/core.proto`, called SmartContractRegistration:

```C#
message SmartContractRegistration {
// The category of contract code(0: C#).
sint32 category = 1;
// The byte array of the contract code.
bytes code = 2;
// The hash of the contract code.
Hash code_hash = 3;
// Whether it is a system contract.
bool is_system_contract = 4;
// The version of the current contract.
int32 version = 5;
// The version of the contract.
string contract_version = 6;
// The address of the current contract.
Address contract_address = 7;
// Indicates if the contract is the user contract.
bool is_user_contract = 8;
}
```
Smart Contract code is stored in the `code` field.

However, each `SmartContractRegistration` entity is not a one-to-one correspondence with the contract, and its storage structure is:

```C#
public MappedState<Hash, SmartContractRegistration> SmartContractRegistrations { get; set; }
```

The `SmartContractRegistration` entity can be fetched by the hash value of the contract code.
It is only written once when deploying the contract.

The data structure that corresponds one-to-one with contracts is called `ContractInfo`.
Structure `ContractInfo` is defined in [acs0](https://docs.aelf.io/en/latest/reference/acs/acs0.html).

```C#
message ContractInfo
{
// The serial number of the contract.
int64 serial_number = 1;
// The author of the contract is the person who deployed the contract.
aelf.Address author = 2;
// The category of contract code(0: C#).
sint32 category = 3;
// The hash of the contract code.
aelf.Hash code_hash = 4;
// Whether it is a system contract.
bool is_system_contract = 5;
// The version of the current contract.
int32 version = 6;
string contract_version = 7;
// Indicates if the contract is the user contract.
bool is_user_contract = 8;
}
```

We use the MappedState to store related instances.

```C#
public MappedState<Address, ContractInfo> ContractInfos { get; set; }
```

From the `code_hash` field of `ContractInfo`, it is not difficult to guess:

1. When trying to retrieve the contract code, the `code_hash` of ContractInfo is first read, and then the contract code itself is read from the `State.SmartContractRegistrations` mapped state.
2. Upgrading a contract on aelf is replacing the `code_hash` of `ContractInfo`.

## Deploy and update contracts

To deploy a smart contract to aelf, developers need to interact with the `DeploySmartContract` or `DeployUserSmartContract` defined by [acs0](https://docs.aelf.io/en/latest/reference/acs/acs0.html) and implemented by the Genesis Contract.
The differences between these two methods will be explained later.

When executing the deployment method, the contract code will be stored in the StateDb through the structure we mentioned before: `SmartContractRegistration`.
More specifically, it is the `code` field.

If developer's smart contract is written by C#, the `category` should be `0`.
The execution environment will select which runtime to load the contract code into based on the `category` field.

And the `code_hash` is a unique identifier for the contract code.
For C# smart contract, the code hash is calculated by the Genesis Contract during deployment.

After the contract code is saved in StateDb, another field is used to store the relevant information of the contract.
The structure is also mentioned before: `ContractInfo`.
There is a `code_hash` field defined in this structure, make it possible to use `GetContractInfo` method to get the contract information of provided contract address,
then use `GetSmartContractRegistrationByCodeHash` method to get contract code via contract code hash.
In addition, the contract code can also be obtained through method `GetSmartContractRegistrationByAddress`.

As for updating the contract code, the contract information (`ContractInfo`) can be directly modified through method `UpdateSmartContract`,
then aelf smart contract execution environment can obtain the new contract code via new contract hash from the Genesis Contract in the future.

## Execution of contract code

Although the execution process of the contract is unrelated to the Genesis Contract.
Developers may be concerned about how their contract code will be consumed in the future after deployment.
Therefore, here are some brief explanations.

![Contract Execution](images/contract-execution.png)

As shown in the above figure, assuming that the contract code has been stored in the Genesis Contract.
When a caller tries to call a method of the contract, within the aelf node, the corresponding `SmartContractRegistration` will be obtained from the Genesis Contract, the contract code will be extracted, encapsulated as an Executive type, for the contract execution environment to call.
After completing the call, return the transaction result to the caller.

Upgrading the contract will change the `SmartContractRegistration` obtained during the above process, so it is feasible to upgrade the deployed contract in aelf.

## Calculation of contract address

The contract address is calculated through a field that increases with the number of contract deployments.

```C#
public Int64State ContractSerialNumber { get; set; }
```

Its calculation process is located in the `DeploySmartContract` method:

```C#
var contractAddress = AddressHelper.BuildContractAddress(Context.ChainId, serialNumber);
```

- The contract address of each chain of aelf is different.
- The contract address is not related to the contract code, but only to the order in which it is deployed on this chain.
- Therefore, when testing newly written contracts in `aelf-boilerplate` or `aelf-developer-tools`, the new contract always has a fixed address.

After the 1.6.0 version, Salt is added to the imported parameter of the deployment/upgrade contract. The contract address is calculated by using the Deployer address of the deployment account and the hash value Salt.

```C#
var contractAddress = AddressHelper.ComputeContractAddress(deployer, salt);
```

- Deploying contracts with the same account and using the same Salt can make the contract address of each chain of aelf the same.

## Contract deployment and update process

### Deploy contract with audit

![Deploy Contract With Audit](images/deploy-contract-with-audit.png)

The current pipeline starts with Propose, which generates a parliamentary proposal.
When more than 2/3 of the BPs agree to deploy/update, a new proposal is released to request code inspection.
Finally, after the code audition is passed, the real contract deployment/upgrade will be achieved through the proposal of releasing the code inspection.

### Deploy contract without audit

![Deploy Contract Without Audit](images/deploy-contract-without-audit.png)

Developers send deployment/update user contract transactions, generate a parliamentary CodeCheck proposal, and when more than 2/3 of the BPs conduct code checks and pass, achieve real contract deployment/upgrade through the proposal of automatically releasing code checks.

### Contract deployment and upgrade new version number

When upgrading a contract, check the contract version information
- If the contract version is less than or equal to the original contract version, the upgrade contract transaction fails
The old version of the contract only has a version number after being upgraded.
- If the version number is increasing, the upgrade contract transaction is successful.

In the updateSmartContract method, increase the version number judgment:

```C#
var contractInfo = Context.UpdateSmartContract(contractAddress, reg, null, info.ContractVersion);
Assert(contractInfo.IsSubsequentVersion,
$"The version to be deployed is lower than the effective version({info.ContractVersion}), please correct the version number.");
```

## Contract error message

`DeployUserSmartContract` method:
- No permission. Trying to deploy a smart contract to an aelf private sidechain, and the transaction sender is not in the allowlist.
- contract code has already been deployed before. Contract code deployed.
- Already proposed. Duplicate deployment request.

`UpdateUserSmartContract` method:
- No permission. The transaction sender is not the contract author.
- Code is not changed. The contract code has not changed since deployment or the previous update.
- The version to be deployed is lower than the effective version({currentVersion}), please correct the version number. The updated contract version number is too low.
- Already proposed. Duplicate deployment request.

## Usage
Check the `deploy` command of [aelf-command](https://docs.aelf.io/en/latest/reference/cli/methods.html#deploy-deploy-a-smart-contract).
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions docs-sphinx/reference/smart-contract/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
Smart Contract
==============

.. toctree::

Genesis Contract <genesis-contract>
Consensus Contract <consensus-contract>
MultiToken Contract <multi-token-contract>
Cross Chain Contract <cross-chain-contract>
Vote Contract <vote-contract>
Profit Contract <profit-contract>
Loading