主页 > imtoken百科 > 5 分钟 GET Blockchain - 开发区块链 开发 BlockChain

5 分钟 GET Blockchain - 开发区块链 开发 BlockChain

imtoken百科 2023-09-27 05:08:54

本文攻略:解决区块链开发难题,学习Tendermint,自己搭建区块链

推荐玩家等级:技术新手、学生党、初级码农

先阅读本文解锁技能:

一点命令行基础一点GO基础:3天包学一点区块链知识:5分钟学区块链-关于区块链的一切All About Blockchain

练习本文的推荐设备:

操作系统:macOS Sierra(Windows没问题)IDE:VSCode,并自动安装一批官方推荐的GO插件Restful API工具:Paw(非必需,浏览器也可以)

第 1 部分:什么是 Tendermint

上一篇我们引用了哥打麻将联合记账的Rebs、Jack Ma、Pone Ma和强东栗子,这次PO提倡他们的手写记账太原始了,所以他想写一个区块链记账APP这四个人,让他们可以告别手写书籍。

既然没有重新发明轮子这回事,我想介绍一个叫Tendermint(以下简称TM)的区块链轮子。如果有玩家听说过以太坊的话,这个What Workshop有一个分支,Ethermint,它是基于TM开发的。无论如何,PO所有者只知道如何编码而不是投机硬币。他真的不明白这是什么研讨会。

好,我们先来了解一下TM的原理,因为真的没有什么UI可以可视化让玩家一眼看懂。 TM主要由两部分组成:

Tendermint Core:区块链共识引擎。它负责两件事:节点之间同步有序的数据传输,以及拜占庭共识机制的实现。 ABCI:区块链应用程序接口。它被设计成一组带有接口规范的协议,使得区块链应用逻辑可以用多种语言实现。

那他们两个在做什么,我看了半天还是不明白。可以先记住它们。 PO高手第一次看原稿的感觉和玩家一样。

第 2 部分:Tendermint 安装和运行

1.官方安装指南

让我们忽略更多的理论,卷起袖子做一个程序员我最喜欢做的事情,先下载轮子,进入命令行:

go get github.com/Masterminds/glide
go get github.com/tendermint/tendermint/cmd/tendermint

TECO区块链能做吗

下载过程比较长,这个轮子比较大(可能需要科学上网),下载安装完成后进入命令行:

cd $GOPATH/src/github.com/tendermint/tendermint
glide install
go install ./cmd/tendermint

安装过程也比较长。安装完成后,验证是否安装成功。输入命令行:

tendermint version
abci-cli version

截至本文发表,tendermint版本0.15.0,abci-cli版本0.9.0

2.跑官方栗子

官方文档提供了两个栗子,之前的安装已经集成:

dummy:一个简单的键值存储区块链应用程序,使用有点像 Redis 或 ElasticSearch。 counter:一个简单的计数器区块链应用,写入区块的数字必须递增,否则不会被区块接受。

这里简单介绍一下栗子dummy,首先启动区块链应用,进入命令行:

abci-cli dummy

然后启动 TM ,命令行输入:

tendermint init
tendermint node

如果顺利的话,可以看到abci和tendermint这两个程序是连通的(Connect),并且tendermint会像心跳一样每秒提交一个空块。接下来,我们准备编写一个包含大量内容的新块。输入命令行:

curl -s 'localhost:46657/broadcast_tx_commit?tx="abcd"'
curl -s 'localhost:46657/broadcast_tx_commit?tx="name=satoshi"'

TECO区块链能做吗

在我们的区块链中有一个记录“abcd”的区块,另一个记录“name=satoshi”的区块,如果需要查询区块链的内容,输入命令行:

curl -s 'localhost:46657/abci_query?data="name"'

curl是Linux的常用工具,玩家可以通过网页浏览器直接输入localhost:46657/abci_query?data="name"

3. 探索官方工具

最后,让我们关闭刚刚运行的dummy application和tendermintTECO区块链能做吗,重新进入命令行运行dummy:

abci-cli dummy

再次输入命令行:

abci-cli console

那么这两者是连通的(Connect),这时候很多玩家都会被这两个叫abci的家伙搞糊涂了,怎么会互相连通,abci是什么?他做了什么?让我们通过 PART 3 重新组织我们刚刚在区块链中所做的事情。

第 3 部分:重新理解 Tendermint

PO 首先列出了官方文档中最常用和最容易混淆的术语:

ABCI ServerABCI ClientTendermint CoreABCI ApplicationABCI App

然后总结三个术语帮助理解,以下约定统一使用这三个术语:

ABCI:区块链内部,ABCI Server,启动后加载ABCI Application/App,为Tendermint提供Socket服务,服务地址:tcp://localhost:46658Tendermint:区块链内部,ABCI Client/Tendermint Core,启动后,使用 ABCI 提供的 Socket 服务创建 3 个连接(Connect),同时会向区块链外的客户端提供 HTTP 服务,服务地址::46657Client:区块链外,真正的客户端,读写权限通过 Tendermint 提供的服务进行区块链

TECO区块链能做吗

或者把栗子一个动作,假设强哥用的是我写的区块链记账APP(iOS开发):

Client是区块链记账APP,强哥记录了一个新的Data 'Jack Pony $10',然后save Client会发起请求:46657/broadcast_tx_commit?tx="Jack Pony $10" Tendermint收到tx="Jack Pony $10 "并通过Socket向ABCI发送指令CheckTx:"Jack Pony $10"ABCI 在我写的ABCI App(用GO开发)中运行CheckTx方法,作用是验证“Jack Pony $10”是否符合数据规范如果不符合,它将通知 Temdermint 拒绝此 tx。假设通过 ABCI CheckTx 并通知 TendermintTendermint 将“Jack Pony $10”临时存储在 mempool 中,并通过 P2P 网络将这个 tx 复制到其他 Tendermint 节点(由 Jack Ma、Pony Ma 和 Rebs 运行的 Tendermint 节点)。 Jack Pony $10" 拜占庭共识投票为本次交易,所有 4 十个 dermint 节点都参与其中。投票过程分为三轮,第一轮预投票(PreVote),第二轮预提交(PreCommit ) 超过 2/3 批准后,最后一轮正式提交(Commit)超过 2/3 批准(Commit)Tendermint 提交(Commit)),依次向 ABCI 发送指令:BeginBlock -> DeliverTx * n 次-> EndBlock -> Commit,大致意思是:快速接受新区域 -> 接受区块内容 * n 块 -> 区块内容已被接受 -> 提交 上链TECO区块链能做吗,提交成功后 ABCI 会通知 Tendermint 有区块链中多了一个区块,记录了一笔交易“Jack Pony $10”。当然我们也可以记录n个项目,然后保存,这个区块会记录n个交易。

最后我总结几点:

回到刚才的abci-cli,当他运行'abci-cli dummy'的时候,其实是在运行ABCI。他运行'abci-cli console'的时候,其实是在运行Tendermint,所以一起运行之后,会建立一个Socket连接(Connect)Tendermint和ABCI之间有3个Socket连接:1个用于验证数据(CheckTx命令) , 1个为查询数据(Query command),1个为共识数据(BeginBlock, DeliverTx, EndBlock, Commit command) Tendermit提供给Client的HTTP接口很多,浏览器访问:46657都知道,玩家也可以看官方亲自提交文件

第 4 部分:开发区块链

终于到了编码部分,我们先梳理一下项目结构:

ClientApp:区块链记账APP,可实现任何语言、任何平台(iOS/Android/H5/other)。在这个版本中,我们使用 GO 做最简单的控制台命令行实现,甚至没有 UI 界面。 . TendermintApp:区块链服务程序,包括 Tendermint 和 ABCI。 ABCI:因为是接口协议,所以可以设计成任何语言实现。我们使用 GO 语言。开发主要是实现 CheckTx、DeliverTx、Commit 等 ABCI 指令的具体逻辑。 Tendermint:几乎不需要开发。如前所述,它为我们做了两件事,P2P网络同步有序传输数据和拜占庭共识引擎。我们可以在这里运行它。

接下来正式开始代码,主要讲解一些核心逻辑:

1. 客户端应用程序

模拟5个block,每个block Block记录10条记录,将这些记录转成json提交给Tendermint

blocksNumber := 5                                     // how many blocks
transactionsPerBlock := 10                            // how many transactions in each block
players := []string{"Lei", "Jack", "Pony", "Richard"} // 4 players
random := rand.New(rand.NewSource(time.Now().UnixNano()))
json := jsoniter.ConfigCompatibleWithStandardLibrary
for i := 0; i < blocksNumber; i++ {
    time.Sleep(time.Second * 1)
    transactions := []controllers.Transaction{}
    for j := 0; j < transactionsPerBlock; j++ {
        from := players[random.Intn(len(players))]
        to := players[random.Intn(len(players))]
        for from == to {
            to = players[random.Intn(len(players))]
        }
        btc := float32(random.Intn(10) + 1)
        tran := controllers.Transaction{
            From:    from,
            To:      to,
            Bitcoin: btc,
        }
        _, _ = tran.Create()
        transactions = append(transactions, tran)
    }
    bytes, _ := json.Marshal(&transactions)
    data := strings.Replace(string(bytes), "\"", "'", -1)
    tx := data
    // tmAsync(tx)
    tmCommit(tx)
}

func tmCommit(tx string) {
	url := "http://localhost:46657/broadcast_tx_async?tx=\"" + tx + "\""
	txHandle(url)
}

2.@ > Tendermint

从命令行运行已定义的 shell 脚本并将结果打印到控制台和日志文件

TECO区块链能做吗

f, err := os.Create("logs/tendermint.log")
if err != nil {
    fmt.Println("Tendermint log init error:", err)
}
multiWriter := io.MultiWriter(f, os.Stdout)
go func() {
    cmd := exec.Command("bash", "-c", "sh run-tm.sh")
    cmd.Stdout = multiWriter
    cmd.Start()
}()

run-tm.sh 脚本内容:

echo tendermint start
tendermint init
tendermint unsafe_reset_all
tendermint node --consensus.create_empty_blocks=false
echo tendermint end

unsafe_reset_all 每次都会重置本地区块链数据,仅供开发使用共识。 create_empty_blocks的作用是关闭Tendermint自带的每秒生成新空块的功能

3.ABCI

实现ABCI命令接口,这里我们直接使用官方的栗子dummy应用,保存提交的json记录,并在各个实现接口打印日志(限于篇幅,长代码省略)

func (app *DummyApplication) CheckTx(tx []byte) types.ResponseCheckTx {
	lib.Log.Debug("CheckTx")
	lib.Log.Notice(string(tx))
	return types.ResponseCheckTx{Code: code.CodeTypeOK}
}
func (app *DummyApplication) DeliverTx(tx []byte) types.ResponseDeliverTx {
	lib.Log.Debug("DeliverTx")
	lib.Log.Notice(string(tx))
	// ...
	return types.ResponseDeliverTx{Code: code.CodeTypeOK, Tags: tags}
}
func (app *DummyApplication) Commit() types.ResponseCommit {
	lib.Log.Debug("Commit")
	// ...
	lib.Log.Debug("Commit Hash", hash)
	return types.ResponseCommit{Code: code.CodeTypeOK, Data: hash}
}
func (app *DummyApplication) Query(reqQuery types.RequestQuery) (resQuery types.ResponseQuery) {
	lib.Log.Debug("Query")
	// ...
}

4. 编译

我们已经编写好了编译脚本,进入命令行:

sh make.sh

编译脚本的本质是从一个正在运行的程序中编译出来的:

go build ./TendermintApp/ABCIServer/
go build ./TendermintApp/ABCIClient/
go build  -o Client ./ClientApp/

5.测试

在激动人心的时刻,我们已经离自制的区块链很近了。

TECO区块链能做吗

首先运行ABCI,命令行输入:

./ABCIServer

然后运行Tendermint,命令行输入:

./ABCIClient

可以看到Tendermint和ABCI已经有3次连接(Connect)Socket握手,说明整个区块链服务已经准备好了,最后我们只需要使用Client进入区块链就可以了,写入数据,进入命令行:

./Client

命令理解为使用记账APP记录5页,每页10条记录,然后点击保存后发送到区块链。

附上运行结果图,大致可以看出三个程序都运行成功了

最后,我们创建了一个区块链,共有 7 个区块。区块 2 到 6 各有 10 条分类账记录。区块 1 和 7 是系统创建的空区块。

空块呢?原 PO 所有者也认为是 bug,到官方开发 issue 中了解到,每次 Tendermint 收到新的 tx 或区块链哈希值发生变化(即区块链状态发生变化)时,都会生成一个新的区块接受内存池中未提交的新交易,该交易由 Tendermint 生成,用于正常的自检工作。

让我们看看这个区块链长什么样,这里是区块 2、3、4 的账本记录

我觉得这些小街区里有很多$$。最后,我将提供本文的代码。我希望所有玩家都创建自己的区块链。