This article is about a C-ABCI program I implemented.
Original Author: XU LI
Chinese Version: C-ABCI
Brief Introduction
This article will focus on the implementation of C-ABCI which means use C language to implement Tendermint ABCI ! First of all,let’s brief introduce Tendermint and ABCI:
Temdermint’s core is consensus engine, it would be responsible for:
- Sharing blocks and transactions between nodes
- Establishing a canonical/immutable order of transactions (the blockchain)
ABCI(Application BlockChain Interfac) is interface between Tendermint and Application, which means Application will use ABCI to communicate with Tendermint. It can be implemented with any language, so far it’s been implemented with C++ and JavaScript, Java, Erlang. But not include C language, so I took the chance, use C language implemented C-ABCI.
Learn more about Tendermint: Tendermint Intro
Learn more about ABCI : ABCI Overview
Source code of C-ABCI : chainx-org/c-abci
How to run C-ABCI demo?
This is pretty easy part, there’s only five step to run a C-ABCI demo, do as the following:
Step 1: Install Tendermint
Install Tendermint into your computer, here is the guide of Installation of Tendermint
Step 2: Clone code
Clone the C-ABCI source code to your computer:1
git clone https://github.com/chainx-org/c-abci.git ~/work/c/c-abci
This is where I keep C-ABCI source code, you can chose your own path to keep it.
Step 3: Compile code
Enter into c-abci directory and compile the C-ABCI:1
2cd ~/work/c/c-abci
make
when you successfully compile the C-ABCI, you will see the terminal output like this:
And in the c-abci/bin directory you will see the c-dummy binary file, it can be executed !
Step 4: Run test program
Enter into c-abci/bin directory and run c-dummy program:1
2cd bin/
./c-dummy
Step 5: Run Tendermint
Run Tendermint program:
If it is your first time run Tendermint in your computer, execute command:1
2tendermint init
tendermint node
If you have already run Tendermint in your computer , then execute command:1
2tendermint unsafe_reset_all
tendermint node
This is whole procedure of How to run C-ABCI demo. Here is the video of runing C-ABCI:
C-ABCI code framework
Tendermint provides two methods to communicate with, that’s GRPC and TSP ! C-ABCI chose the latter, it use TCP protocol to implement communication module. Tendermint keep three connections: Mempool Connection, Consensus Connection, Query Connection. Connections Introduction. In C-ABCI’s implementation each connection has it’s own process to dispose the connection’s request, maybe latter on I will implement another version which use separated threads to dispose each connection.
As we said before, ABCI is a interface, in C language term it means that C-ABCI is a library which provides three interfaces. Application can use C-ABCI library to communicate with Tendermint. C-ABCI doesn’t interested in the data which Application and Tendermint communicate with, it’s just a transmitter. Data transmission between Tendermint and C-ABCI is relay on TCP Socket, but C-ABCI and Application data transmission use callback function to achieve!
Processing flow among Tendermint, Application, C-ABCI:
- Tendermint send a request to C-ABCI
- C-ABCI receive the request and parse request data, then pass the data to the callback function which is Application implemented
- The callback function according to request type to act different with the data, and pass the result to C-ABCI via callback function return value
- C-ABCI pack the returned value and send it to Tendermint
In C-ABCI source code, there have been seven directories , each directory represent a individual modular except include directory. The sheet below describes each directory:
directory | description |
---|---|
include | Include all modular head files |
socket | Communication modular which implemented communication of network based on TCP Socket |
encoding | Character conversion modular which implemented conversion between unsigned char and unsigned integer of big endian and little endian |
dlist | Data storage modular which use Circular Doubly Linked List to store data |
type | Data type modular which dispose Tendermint data type, produce from Tendermint type.proto file with protobuf-c software |
core | C-ABCI core modular which provides three interface to Application |
demo | C-ABCI demo which is very simple Application for show you how to use C-ABCI library |
How to build a Application on top of C-ABCI?
Even though C-ABCI have seven directories, there only have two directories you have to study:
- core : use this modular to code Application’s framework
- type : use this modular to malloc data struct and free data struct
I have already implemented a very simple application called c-dummy in c-abci/demo directory, you can draw lessons from it.
C-ABCI is very easy to start on, it provides only three interfaces which is all you need to code a Application framework!
The three interfaces is:
Initialize C-ABCI serve
Bind and listen the provided IP address and port.1
int server_init(const char *ipaddr, const char *port);
Start C-ABCI serve
It will not return until some error occurred. app is callback function which need Application to implemented.1
int server_start(Application app)
Stop C-ABCI server
Close listened socket.1
void server_stop();
You just need write this three functions in your Application’s main function then the code framework of your Application is completed (see main function in main.c
file of c-abci/demo/ directory) !
Rest of the work is to implement callback function which you provide to server_start function. It should look like this:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24void *ABCIApplication(Types__Request *request)
{
switch( request->value_case )
{
case TYPES__REQUEST__VALUE_INFO:
return Info();
case TYPES__REQUEST__VALUE_SET_OPTION:
return SetOption(request->set_option);
case TYPES__REQUEST__VALUE_DELIVER_TX:
return DeliverTx(request->deliver_tx);
case TYPES__REQUEST__VALUE_CHECK_TX:
return CheckTx(request->check_tx);
case TYPES__REQUEST__VALUE_COMMIT:
return Commit();
case TYPES__REQUEST__VALUE_QUERY:
return Query(request->query);
case TYPES__REQUEST__VALUE_INIT_CHAIN:
return InitChain(request->init_chain);
case TYPES__REQUEST__VALUE_BEGIN_BLOCK:
return BeginBlock(request->begin_block);
case TYPES__REQUEST__VALUE_END_BLOCK:
return EndBlock(request->end_block);
}
}
You can find this code in c-abci/demo/dummy.c
file. The parameter of request passed by C-ABCI, which is received from Tendermint.
You can see in this callback function each request type has it’s own function to dispose request. This is most important part of your Application code, you need implement functions of each request type, these functions are your Application’s business logic . And when you finished these functions, your Application’s code is completed!
In c-abci/demo/ directory just implemented a few functions of some request type, and it’s very simple business logic which just store data or query them. It use dlist modular to store data. You can choose your own method to store data, such as tree, database.
Problem’s Solution:C-ABCI’s problems during compiling