aelf Tech Talks — AElf Smart Contract Development-The First AElf Smart Contract — Part 3
Part 1 of this series looked at creating the framework for a smart contract on aelf. Part 2 of this series looked at the creation of the smart contracts. This post will focus on the deployment of the smart contracts.
4. Deploy smart contracts
Let AElf.Boilerplate.Mainchain reference the smart contract project and the corresponding Proto file, by adding it in the csproj file:
First, let me briefly introduce the generation process of the AELF blockchain genesis block.
Like other blockchain systems, in AELF’s initial stage, each node will independently generate a genesis block with the same block hash (if the genesis block hash generated by a node is different to that of all other nodes on the AELF main chain, it indicates that the particular node has started a different main chain to the aelf main chain).
In the genesis block, a series of system contracts are deployed through fixed code and configuration items to initialized contracts.
When using the staging test contracts, you can deploy your own contract as a system contract in the genesis block, and you only need to provide the corresponding Dto.
The location for providing Dtos is in the GetGenesisSmartContractDtos method of src/AElf.Boilerplate.Mainchain/GenesisSmartContractDtoProvider.cs. This method already includes staging to deploy and initialize other system contracts Dto. You only need to add Dto for the HelloWorld contract.
Create a C# code file named GenesisSmartContractDtoProvider_HelloWorld.cs, initialize a GenesisSmartContractDto list, and entering the relevant information is sufficient.
In the AELf system, each contract has a Hash type unique identifier, called the System Contract Name. The Hash.FromString (“AElf.ContractNames.HelloWorld”) in the above code is the name of the HelloWorld contract. It is the only identifier for the HelloWorld contract.
Finally, add GetGenesisSmartContractDtosForHelloWorld to the GetGenesisSmartContractDtos method of GenesisSmartContractDtoProvider:
5. Automatically Send Transactions to Test Smart Contracts
First, let’s introduce an interface in the AELf main chain code: ISystemTransactionGenerator.
This interface takes effect in the process of block packaging. By traversing all implementations of this interface, a series of system transactions are generated. These system transactions will be executed before the ordinary transactions received from the network are obtained from the transaction pool, in other words, they will modify the blockchain state before ordinary transactions are being executed. Like ordinary transactions, system transactions are also packaged into blocks. The difference is that system transactions are generated by the code of the main chain, and the Sender is the node of the packaged block itself.
Therefore, it is a good method to test new contracts in the staging process and use the ISystemTransactionGenerator interface to customize the “system transaction”. You only need to formulate the rules for issuing transactions in the implementation.
The ISystemTransactionGenerator interface contains only one method: GenerateTransactions. Its signature is:
Let’s look at an example. In the AELf blockchain, consensus trading is one of the system transactions, and the related implementation is:
Basically, the GenerateConsensusTransactionsAsync method of ConsensusService is called to generate transactions, and the generated transactions are added to the generatedTransactions variable marked with the ref keyword. Finally, add this implementation class to the composite root (XXModule’s ConfigureServices method) and add a dependency.
Based on this, we can implement an ISystemTransactionGenerator that automatically sends three transactions of Greet, GreetTo, and GetGreetedList.
In the src/AElf.Boilerplate.Tester/TestTransactionGenerator folder, create a C# code file HelloWorldTransactionGenerator and make it to implement ISystemTransactionGenerator.
Before implementing it, we need to introduce a service provided in the AELf main chain code: TransactionResultService, which can query the execution result of a transaction by providing a transaction ID. An instance of ITransactionResultService can be directly injected with the constructor.
A service for generating transactions is also provided in the staging: TransactionGeneratingService. Its implementation is not complicated. Just in the root directory of the AELf.Boilerplate.Tester project, its GenerateTransactionAsync method assembles a transaction through some other services provided by the main chain, and returns the transaction.
So, HelloWorldTransactionGenerator can be implemented like this:
For each block, the HelloWorldTransactionGenerator will generate three transactions with a MethodName of Greet, GreetTo, and GetGreetedList. The target contract system name is Hash.FromString (“AElf.ContractNames.HelloWorld”). When the previous block contains a GreetTo transaction (if (_lastGetGreetedListTxId! = Hash.Empty)), use the TransactionResultService to query the list of people who have been “greeted” and print it to the log.
After implementing HelloWorldTransactionGenerator, don’t forget to add the following dependency in the ConfigureServices method of src/AElf.Boilerplate.Tester/TesterModule.cs:
By doing this, restarting the staging node, you can see the transaction execution information printed on the console (because when the contract is implemented, some logs are printed through the Context.LogDebug method), and the growing Greyed list .
(The code in this article can be found from the tutorial branch of https://github.com/AElfProject/aelf-boilerplate)
Other Topics in aelf Tech Talks:
— Join the Community:
· Read weekly articles on the aelf blog
· Catch up with the develop progress on Github
· Instagram: aelfblockchain
· YouTube Channel: aelf
For more information, visit aelf.io