本文主要介绍用 C 语言实现的 Tendermint ABCI,以及如何在此之上构建一个属于自己的应用

原文作者:许莉
英文版本:C-ABCI

简介

首先简单介绍一下 Tendermint 和 ABCI。

Tendermint 的核心就是共识引擎,它主要负责两点:

  • 节点之间共享交易和区块
  • 建立一个规范且不可改变的交易顺序(也就是区块链)

ABCI(Application BlockChain Interface)是 Tendermint 与应用程序之间的一个接口,它可以使用各种语言来实现。目前已经实现的语言有 C++,JavaScript,Java和 Erlang,尚无 C 语言实现,故而本文实现了 C 版本的 ABCI。

如果对于 Tendermint 和 ABCI 尚不熟悉,或者想要了解更多有关内容,可自行参阅以下资料:

  • Tendermint Intro
  • ABCI Overview
  • Tendermint Intro 中文翻译

C-ABCI 的GitHub源码:chainx-org/c-abci。

运行示例

安装 Tendermint

在编译启动 C-ABCI 之前,首先需要安装 Tendermint,这里是官方的安装指南。

编译执行 c-dummy

Tendermint 安装完成之后,从 GitHub 下载 C-ABCI 源码到本地:

1
git clone https://github.com/chainx-org/c-abci.git ~/c-abci

进入到目录 c-abci ,执行 make 对源码进行编译:

1
2
cd ~/c-abci
make

编译成功, 可以看到如下信息:

编译完成后,会在 bin 目录下生成一个叫做 c-dummy 的可执行程序,执行该程序:

1
2
cd bin
./c-dummy

启动 Tendermint

c-dummy 启动后,开始启动 Tendermint。如果是首次执行Tendermint,需要先进行初始化再启动节点

1
2
tendermint init
tendermint node

如果之前有启动过 Tendermint,先对 Tendermint 进行重置再启动节点:

1
2
tendermint unsafe_reset_all
tendermint node

这就是整个启动过程了,下面有个C-ABCI启动过程的视频:

代码架构

Tendermint 提供了 GRPC 和 TSP 两种通信方式,C-ABCI 使用了后者,用基于 TCP 协议的 Socket 来完成通信模块。Tendermint 会保持3个连接:内存池连接(Mempool Connection)、共识连接(Consensus Connection)、查询连接(Query Connection),三个连接简介。在 C-ABCI 的实现中,每个连接都拥有一个独立的进程来专门处理此连接的所有请求,后期可能会增加用独立线程来处理的版本。

前面提到 ABCI 是一个接口,对 C 语言来说,它其实就是一个库。C-ABCI 就是一个用 C 语言实现的库,应用程序调用这个库来与 Tendermint 进行数据交互。C-ABCI 对于 Tendermint 与应用程序之间通信的具体数据并不感兴趣,它只是作为一个传递者而已!C-ABCI 与 Tendermint 之间数据的传输是通过 TCP Socket 来实现的,与应用程序之间数据的传输则是通过回调函数来实现的。

应用程序、C-ABCI、Tendermint 三者之间处理流程:

  1. Tendermint 向 C-ABCI 发送请求
  2. C-ABCI 接收请求,并解析数据,然后调用应用程序实现的回调函数,并将解析的数据通过回调函数的参数传递给应用程序
  3. 应用程序所实现的回调函数会根据不同的请求类型对数据进行不同的处理,并将处理的结果通过回调函数的返回值返回给 C-ABCI
  4. C-ABCI 将返回的结果按照 Tendermint 要求的数据格式进行处理,并将处理的最后数据响应给 Tendermint

C-ABCI 源码中,一共有 7 个目录,除了 include 目录之外每个目录都代表着一个模块,对于 socketencodingdlist 三个目录,是完全独立的,可以移出来放在任何项目中使用,后期有时间会把这三个独立的模块抽取出来继续完善!

下面具体说明一下每个目录的作用:

目录 功能
include 头文件目录,包含所有模块的头文件
socket 通信模块,主要功能是实现TCP协议的通信,提供了绑定监听端口,连接端口,关闭端口,以及接收,发送数据的接口
encoding 字符转换模块,主要功能是实现大小端整型数据与字符串之间的转换,分别提供了大端和小端不同位数的无符号整型与无符号字符串之间互相转换的接口
dlist 数据存储模块,主要功能是使用循环双向链表来实现数据的存储,提供了链表的创建,销毁,增加,删除,查找接口
type 数据类型处理模块,主要功能是实现数据结构体的的相关操作,提供结构体的创建,销毁等接口。Tendermint使用的数据类型保存在一个types.proto文件中,使用第三方软件protobuf-c软件将此文件生成C文件格式
core C-ABCI的核心模块,主要功能就是实现一个服务端,给应用程序提供了初始化服务,开始服务以及停止服务的接口
demo 实现了一个简单的应用程序,关于数据存储使用了dlist模块。

应用程序示例

在 C-ABCI 的源码中,demo 目录中实现了一个简单的应用程序,可以参考这个应用程序来实现自己的应用程序。
C-ABCI中有多个目录,但是编写一个应用程序不用每个目录都需要去了解,只需要了解:

  • core:核心模块
  • type:数据类型处理模块

下面结合 demo 讲述一下如何使用上面所说的两个模块在 C-ABCI 上编写一个属于自己的应用程序。

应用程序的 main 函数中只需要调用 core 提供的三个接口,就完成了整个框架的编写(对照 demo 中 main.c理解)

初始化C-ABCI服务

此接口是绑定和监听传入的IP地址和端口

1
int server_init(const char *ipaddr, const char *port);

启动C-ABCI服务

只要没有出错,此接口不会返回,会一直等待新的连接,传入的app参数就是由应用程序实现的回调函数

1
int server_start(Application app)

停止C-ABCI服务

此接口主要是关闭监听的端口

1
void server_stop();

这样,应用程序的框架代码就已经完成了。剩下所需要做的事情就是实现回调函数了,回调函数的实现:(demo中的dummy.c):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
void *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);
    }
}

每个应用程序回调函数的实现都是如此。回调函数的参数是由 C-ABCI 提供,根据不同的请求会有不同的具体实现函数,这些具体实现函数就是应用程序代码编写的重点了,也就是应用程序的业务处理的逻辑代码。业务逻辑代码写完,那么一个应用程序就完成了,剩下的就是编译运行了!

在 demo 中只实现了个别请求的具体实现,逻辑代码也非常的简单的,只是将请求的数据保存起来而已!demo 中对于数据存储这一块使用的是循环双向链表( dlist 模块),应用程序可以不用使用C-ABCI提供的数据存储模块(dlist),可以选择其他的数据存储技术,比如树,数据库等等!

GitHub Wiki:C-ABCI编译运行出现的问题

原始链接:https://lilymoana.github.io/Chi_C-ABCI.html

C语言实现的ABCI相关推荐

  1. 跨链Cosmos(5)ABCI 接口

    一个协议,支持任何语言的交易处理实现 1. 应用层实现交互的接口 // Application is an interface that enables any finite, determinist ...

  2. 区块链开发语言python_区块链开发中使用的最流行的编程语言

    我们目前正处于一个新兴的区块链开发行业中.区块链技术处于初期阶段,然而这种颠覆性技术已经成功地风靡全球,并且最近经历了一场与众不同的繁荣.由于许多资金充足的项目现在急于建立区块链网络并在其上部署分散的 ...

  3. Go语言的错误异常处理机制及其应用

    一.背景 在日常编写golang程序或阅读别人的golang代码时,我们总会看到如下的一堆代码块: xx, err = func(xx) if err != nil {//do sth. to tac ...

  4. Go 知识点(19)— Go 语言中的野指针

    野指针是一种指向内存位置是不可知的指针,一般是由于指针变量在声明时没有初始化所导致的.在 Go语言中,布尔类型的零值为 false,数值类型的零值为 0,字符串类型的零值为 "", ...

  5. gcc 自动识别的文件扩展名,gcc/g++ -x 选项指定语言,不同 gcc 版本 -std 编译选项支持列表

    对于执行 C 或者 C++ 程序,需要借助 gcc(g++)指令来调用 GCC 编译器. 对于以 .c 为扩展名的文件,GCC 会自动将其视为 C 源代码文件 对于以 .cpp 为扩展名的文件,GCC ...

  6. OpenCV 笔记(07)— Mat 对象输出格式设置(Python 格式、CSV 格式、NumPy 格式、C 语言格式)

    首先是下面代码中将要使用的 r 矩阵的定义.需要注意,我们可以通过用 randu 函数产生的随机值来填充矩阵, 需要给定一个上限和下限来确保随机值在期望的范围内. Mat r = Mat(2, 3, ...

  7. 利用牛顿法求平方根-Go语言实现

    牛顿法解释 百度的解释如下: 通俗的解释就是:多数方程不存在求根公式,牛顿提出了一种用迭代来求方程近似根的方法.思路就是不断取切线,用线性方程的根逼近非线性方程f(x)=0f(x)=0f(x)=0的根 ...

  8. 翻转二叉树 c语言实现 递归 栈 队列

    前言 题目比较好理解,就是翻转二叉树 代码 c语言实现 #include<stdio.h> #include<stdlib.h> #include<string.h> ...

  9. 字符串全排列的问题 python和c语言实现

    前言 这是一个的经典的问题 设计一个算法,输出一个字符串字符的全排列. 比如,String = "abc" 输出是"abc","bac",& ...

最新文章

  1. Core Location和MapKit的一些简单使用
  2. linux mysql忘记root_linux下mysql-5.6忘记root密码,重置root密码详细过程
  3. JAVA-接口和抽象类的区别
  4. Android——内存调试
  5. Eclipse中修改项目的文本字符集编码
  6. vue跨域/webpack跨域
  7. eeprom和编程器固件 k2_斐讯K1K2新版固件v22.4.xx.xx简单刷机教程
  8. linux版小米随身WIFI驱动,在官网中您就可以下载小米随身wifi的驱动程序了
  9. 论文翻译|疾病自动编码|Clinical-Coder: Assigning Interpretable ICD-10 Codes to Chinese Clinical Notes
  10. iOS逆向:破解 APP防止dyld注入 的方法
  11. topic是短语还是句子_词组、短语、句子--Unit 3 Topic 3
  12. WIN10安装配置JDK
  13. 如何做好一个中小型企业计算机网络管理员
  14. 计算机电源接通显示未充电怎么办,笔记本电脑显示“电源已接通,未充电”怎么办?...
  15. 谷歌离线地图API解析
  16. openMVS深度图计算:DenseReconstruction Estimate之EVTEstimateDepthMap之patchmatch的传播优化
  17. Acer商祺x4610安装及使用
  18. 构造Delaunay三角形网格(代码整理)
  19. centos 镜像文件说明
  20. Java泛型(11):潜在类型机制

热门文章

  1. ElasticSearch2.3.1环境搭建哪些不为人知的坑
  2. HTTP的 Basic 验证
  3. 掌握 Ajax,第 8 部分: 在请求和响应中使用 XML
  4. 安卓手机Charles抓包显示unknown原因及解决办法
  5. 编程方法学10:私有变量的重要性
  6. Python学习笔记:模块
  7. Centos6.5进入救援模式的方法
  8. synergy在Windows和Linux下使用全攻略(多台PC共享一套键盘鼠标)
  9. Adobe Reader 背景色修改
  10. 【笔记】Automatic recognition of soybean leaf diseases using UAV images and deep convolutional neural ne