Installation and usage of the platform
Example of a smart contract with gRPC¶
This section describes an example of creating a simple smart contract in Python. The smart contract uses a gRPC interface to exchange data with a node.
Before you start, make sure that the utilities from the grpcio package for Python are installed on your machine:
pip3 install grpcio
To install and use the gRPC utilities for other available programming languages, see the official gRPC website.
Program description and listing¶
When a smart contract is initialized using the 103 transaction, the sum
integer parameter with a value of 0
is set for it.
Whenever a smart contract is called using transaction 104, it returns an increment of the sum
parameter (sum + 1
).
Program listing:
If you want transactions calling your contract to be able to be processed simultaneously, you must pass the async-factor
parameter in the contract code itself. The contract passes the value of the async-factor
parameter as part of the ConnectionRequest
gRPC message defined in the contract_contract_service.proto
file:
message ConnectionRequest {
string connection_id = 1;
int32 async_factor = 2;
}
Detailed information about parallel execution of smart contracts.
Authorization of a smart contract with gRPC¶
To work with gRPC, a smart contract needs authorization. For the smart contract to work correctly with API methods, the following steps are performed:
The following parameters must be defined in the environment variables of the smart contract:
CONNECTION_ID
- connection identifier passed by the contract when connecting to a node;CONNECTION_TOKEN
- authorization token passed by the contract when connecting to a node;NODE
- IP address or domain name of the node;NODE_PORT
- port of the gRPC service deployed on the node.
The values of the NODE
and NODE_PORT
variables are taken from the node configuration file of the docker-engine.grpc-server section. The other variables are generated by the node and passed to the container when the smart contract is created.
Development of a smart contract¶
1. In the directory that will contain your smart contract files, create an``src`` subdirectory and place the file contract.py with the smart contract code in it.
2. In the src
directory, create a protobuf
directory and put the following protobuf files in it:
contract_contract_service.proto
data_entry.proto
These files are placed in the we-proto-x.x.x.zip archive, which can be downloaded from the official GitHub repository of Waves Enterprise.
3. Generate the code of the gRPC methods in Python based on the contract_contract_service.proto
file:
python3 -m grpc.tools.protoc -I. --python_out=. --grpc_python_out=. contract_contract_service.proto
As a result, two files will be created:
contract_contract_service_pb2.py
contract_contract_service_pb2_grpc.py
In the contract_contract_service_pb2.py
file, change the line import data_entry_pb2 as data__entry__pb2
as follows:
import protobuf.data_entry_pb2 as data__entry__pb2
In the same way, change the line import contract_contract_service_pb2 as contract__contract__service__pb2
in the file contract_contract_service_pb2_grpc.py
:
import protobuf.contract_contract_service_pb2 as contract__contract__service__pb2
Then generate an auxiliary file data_entry_pb2.py
based on the data_entry.proto
:
python3 -m grpc.tools.protoc -I. --python_out=. data_entry.proto
All three resulting files must be in the protobuf directory along with the source files.
4. Create a run.sh shell script, which will run the smart contract code in the container:
#!/bin/sh
eval $SET_ENV_CMD
python contract.py
Place the run.sh file in the root directory of your smart contract.
5. Create a Dockerfile script file to build and control the startup of your smart contract. When developing in Python, the basis for your smart contract image can be the official Python python:3.8-slim-buster'' image. Note that the packages ``dnsutils
and grpcio-tools
must be installed in the Docker container to make the smart contract work.
Dockerfile example:
FROM python:3.8-slim-buster
RUN apt update && apt install -yq dnsutils
RUN pip3 install grpcio-tools
ADD src/contract.py /
ADD src/protobuf/common_pb2.py /protobuf/
ADD src/protobuf/contract_pb2.py /protobuf/
ADD src/protobuf/contract_pb2_grpc.py /protobuf/
ADD run.sh /
RUN chmod +x run.sh
ENTRYPOINT ["/run.sh"]
Place the Dockerfile in the root directory of your smart contract.
6. In case you are working in the Waves Enterprise Mainnet, contact the Technical Support team to place your smart contract in the public repository.
If you work on a private network, build your smart contract yourself and place it in your own registry.
How a smart contract with gRPC works¶
Once called, the smart contract with gRPC works as follows:
After the program starts, the presence of environment variables is checked.
Using the values of the
NODE
andNODE_PORT
environment variables, the contract creates a gRPC connection with a node.Next, the
Connect
stream method of the gRPCContractService
is called. The method receives aConnectionRequest
gRPC message, which specifies the connection identifier (obtained from theCONNECTION_ID
environment variable). The method metadata contains theauthorization
header with the value of the authorization token (obtained from theCONNECTION_TOKEN
environment variable).If the method is called successfully, a gRPC stream is returned with objects of type
ContractTransactionResponse
for execution. The objectContractTransactionResponse
contains two fields:transaction
- a transaction to create or call a contract;auth_token
- authorization token specified in theauthorization
metadata header of the called method of gRPC services.
If transaction
contains a 103 transaction, the initial state is initialized for the contract. If transaction
contains a call transaction (the 104 transaction), the following actions are performed:
the value of
sum
key (GetContractKey
method of theContractService
) is requested from the node;the key value is incremented by one, i.e.
sum = sum + 1
;The new key value is saved on the node (
CommitExecutionSuccess
method of theContractService
), i.e. the contract state is updated.