当前位置:首页 > 物联网 > 区块链
[导读] Tendermint(TM)是the Cosmos network旗下的一个区块链项目。TM能安全且保持一致性地在多台机器之间复制应用程序。TM的共识算法基于节点不可信的设计,也就是允许拜占庭错

Tendermint(TM)是the Cosmos network旗下的一个区块链项目。TM能安全且保持一致性地在多台机器之间复制应用程序。TM的共识算法基于节点不可信的设计,也就是允许拜占庭错误。TM主要分成两个部分。

一是一个区块链共识引擎(Tendermint Core)。他主要负责节点之间的数据同步有序传输,实现拜占庭共识机制。二是区块链应用接口(ABCI)。它是一种接口通讯协议,可以通过各种编程语言实现应用逻辑。应用逻辑和TM Core通过ABCI实现了解耦。


下面简单介绍一下如何在windows环境下编译及使用Tendermint。

下载源码及依赖

当然前提是已经配置好go环境和git,并且需要梯子,使用如下命令:

go get github.com/Masterminds/glide

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

执行时间比较长,耐心等待完成后,可以发现%GOPATH%目录和%GOPETH%srcgithub.com目录下多出许多东西

编译

有两种方式:

2.1

cd $GOPATH/src/github.com/tendermint/tendermint

glide install

go install 。/cmd/tendermint

这里作者遇到一个坑,执行glide install报错:[ERROR] Failed to find glide.yaml file in directory tree: Cannot resolve parent of D:

首先执行glide create,然后按照提示一步步操作,在执行glide install。

这时又遇到一个问题:[ERROR] Unable to export dependencies to vendor directory: Error moving files: exit status 1. output: Access is denied. 0 dir(s) moved.

网上查到资料,是因为glide版本造成的,修改到v0.12.3版本即可解决。

接下来重新glide install,新的问题出现了:Error looking for crypto/ed25519: Cannot detect VCS.这是由于国内访问golang.org被墙导致的,可以添加镜像文件解决:

glide mirror set https://golang.org/x/crypto https://github.com/golang/crypto

2.2

以上步骤很麻烦,不用怕,我们可以手动使用go build命令编译:

cd %GOPATH/src/github.com/tendermint/cmd/tendermint

go build

cd %GOPATH/src/github.com/tendermint/abci/cmd/abci-cli

go build

两次build之后,分别生成了tendermint.exe和abci-cli.exe,将这两个文件拷到%GOPATH/bin目录下

tendermint version

abci-cli version

以上两个命令如果有版本号输出,那么可以进入下一个步骤了。

运行官方的例子

官方的代码为我们展示了一个kvstore的例子,它的作用就是存储数据,类似与levelDB。

打开三个cmd窗口,cmd1,cmd2,cmd3

在cmd1中输入 abci-cli kvstore

可以看到程序在Waiting for new connecTIon.。.

接下来在cmd2输入 tendermint init,然后tendermint node

C:Usersch》tendermint init

I[2019-08-04|18:28:48.105] Found private validator module=main keyFile=.tendermintconfigpriv_validator_key.json stateFile=.tendermintdatapriv_validator_state.json

I[2019-08-04|18:28:48.113] Found node key module=main path=.tendermintconfig ode_key.json

I[2019-08-04|18:28:48.118] Found genesis file module=main path=.tendermintconfiggenesis.json

C:Usersch》tendermint node

I[2019-08-04|18:28:57.497] Version info module=main software=0.32.1 block=10 p2p=7

I[2019-08-04|18:28:57.514] StarTIng Node module=main impl=Node

I[2019-08-04|18:28:57.528] Started node module=main nodeInfo=“{ProtocolVersion:{P2P:7 Block:10 App:1} ID_:fe807a7617494c46d38bc040801ab567cc330852 ListenAddr:tcp://0.0.0.0:26656 Network:test-chain-17UaI5 Version:0.32.1 Channels:4020212223303800 Moniker:caohuan Other:{TxIndex:on RPCAddress:tcp://127.0.0.1:26657}}”

I[2019-08-04|18:28:58.539] Executed block module=state height=1 validTxs=0 invalidTxs=0

I[2019-08-04|18:28:58.546] Committed state module=state height=1 txs=0 appHash=0000000000000000

I[2019-08-04|18:28:59.552] Executed block module=state height=2 validTxs=0 invalidTxs=0

I[2019-08-04|18:28:59.558] Committed state module=state height=2 txs=0 appHash=0000000000000000

I[2019-08-04|18:29:00.573] Executed block module=state height=3 validTxs=0 invalidTxs=0

I[2019-08-04|18:29:00.579] Committed state module=state height=3 txs=0 appHash=0000000000000000

I[2019-08-04|18:29:01.592] Executed block module=state height=4 validTxs=0 invalidTxs=0

I[2019-08-04|18:29:01.599] Committed state module=state height=4 txs=0 appHash=0000000000000000

tendermint init是初始化tendermint服务,tendermint node则是启动服务

服务启动后,即开始出块,那是因为和cmd1启动的abci-cli建立了链接,如果想不要自动出空块,可以在启动的时候加上参数 tendermint node --consensus.create_empty_blocks=false

tendermint服务启动后,再看cmd1窗口:

C:Usersch》abci-cli kvstore

I[2019-08-04|18:28:50.646] StarTIng ABCIServer module=abci-server impl=ABCIServer

I[2019-08-04|18:28:50.693] WaiTIng for new connection.。. module=abci-server

I[2019-08-04|18:28:57.473] Accepted a new connection module=abci-server

I[2019-08-04|18:28:57.478] Waiting for new connection.。. module=abci-server

I[2019-08-04|18:28:57.484] Accepted a new connection module=abci-server

I[2019-08-04|18:28:57.488] Waiting for new connection.。. module=abci-server

I[2019-08-04|18:28:57.492] Accepted a new connection module=abci-server

I[2019-08-04|18:28:57.496] Waiting for new connection.。. module=abci-server

能够发现这里建立了三个连接,这三个连接分别是:

Info/Query Connection:用于查询服务通信

Mempool Connection:用于发送交易通信

Consensus Connection:用于共识通信

后面还会提到这三个连接的作用。

接下来可以开始测试了,在cmd3窗口输入 curl -s localhost:26657/broadcast_tx_commit?tx=“author=caohuan”

C:Usersch》curl -s localhost:26657/broadcast_tx_commit?tx=“author=caohuan”

{

“jsonrpc”: “2.0”,

“id”: “”,

“result”: {

“check_tx”: {

“gasWanted”: “1”

},

“deliver_tx”: {

“events”: [

{

“type”: “app”,

“attributes”: [

{

“key”: “Y3JlYXRvcg==”,

“value”: “Q29zbW9zaGkgTmV0b3dva28=”

},

{

“key”: “a2V5”,

“value”: “YXV0aG9y”

}

}

},

“hash”: “B339C04B9163F0585B8DB0703E2A107A9B21034B2F5D18BF9B66BDEF5DD627E3”,

“height”: “168”

}

}

友情提示:这条命令在linux系统中是这么写的:curl -s ‘localhost:26657/broadcast_tx_commit?tx=“author=caohuan”’。windows环境中,少了单引号,多了转义的反斜杠。

现在查询一下这个操作有没有成功:curl -s localhost:26657/abci_query?data=“author”

C:Usersch》curl -s localhost:26657/abci_query?data=“author”

{

“jsonrpc”: “2.0”,

“id”: “”,

“result”: {

“response”: {

“log”: “exists”,

“key”: “YXV0aG9y”,

“value”: “Y2FvaHVhbg==”

}

}

}

查询出的这个value是base64编码的,可以使用在线工具转码,也可以在golang中自己实现一个转码,转码之后可以发现“Y2FvaHVhbg==”就是“caohuan”

除了使用curl命令以外,还可以使用浏览器,直接在地址栏输入 http://localhost:26657/abci_query?data=“author” 即可。

以上kvstore的例子就运行成功了,官方还有一个例子counter,这里就不详细展开介绍了,有兴趣的小伙伴可以去官方文档看一下。

简单分析一下

下面简单分析一下刚才经历了什么过程

首先开启abci-cli(cmd1)服务,然后开启tendermint(cmd2)服务,然后使用客户端client(cmd3)向tendermint发送交易,具体过程如下:

1,client产生了一条数据“author=caohuan”,要把这条数据发送到链上去

2,client发起请求:curl -s localhost:26657/broadcast_tx_commit?tx=“author=caohuan”

3,tendermint收到tx=“author=caohuan”的交易,发送给abci

4,abci接受到tx之后,调用CheckTx方法,验证这个tx是否符合交易规范。在/tendermint/abci/example/kvstore/kvstore.go可以看到代码,这里的CheckTx没有做任何事

6,tendermint把该tx存在内存池里,并把这条tx通转发给其他tendermint节点,所有节点对该交易进行两轮投票,PreVote--》PreCommit--》Commit,PreVote超过三分之二同意之后进入PreCommit,再超过三分之二投票后进入Commit(在该例中只有一个节点,所以没有经过共识)

7,tendermint共识完成之后进入commit阶段,再对abci发送请求:BeginBlock -》 DeliverTx * n次 --》 EndBlock --》 Commit,即:新区快 --》 正在接受区块内容 * n条 --》 区块内容接受完了 --》 提交到区块链。这些方法在/tendermint/abci/example/kvstore/kvstore.go中都可以找得到

8,abci在Commit之后会通知tendermint

9,区块链上多了一个区块记录着“author=caohuan”

现在在回过头来看一下刚才提到的三个连接包含哪些东西:

Info/Query Connection:Info,SetOption,Query

Mempool Connection:CheckTx

Consensus Connection:InitChain,BeginBlock,DeliverTx,EndBlock,Commit

这些接口是定义在/tendermint/abci/types/application.go中的,这些接口在协助完成了整个交易过程。

// Info/Query Connection

Info(RequestInfo) ResponseInfo // Return application info

SetOption(RequestSetOption) ResponseSetOption // Set application option

Query(RequestQuery) ResponseQuery // Query for state

// Mempool Connection

CheckTx(RequestCheckTx) ResponseCheckTx // Validate a tx for the mempool

// Consensus Connection

InitChain(RequestInitChain) ResponseInitChain // Initialize blockchain with validators and other info from TendermintCore

BeginBlock(RequestBeginBlock) ResponseBeginBlock // Signals the beginning of a block

DeliverTx(RequestDeliverTx) ResponseDeliverTx // Deliver a tx for full processing

EndBlock(RequestEndBlock) ResponseEndBlock // Signals the end of a block, returns changes to the validator set

Commit() ResponseCommit // Commit the state and return the application Merkle root hash

也就是说,如果我们想使用tendermint实现自己的一条链,就必须实现这些接口。

实现自己的一条链

接下来,我们尝试着实现自己的一条链,逻辑很简单:初始化xiaoMing和daZhuang两个账户,余额各为100,由xiaoMing向daZhuang转账。

代码:

func NewCounterApplication(serial bool) *CounterApplication {

fmt.Println(“NewCounterApplication进来了吗”)

return &CounterApplication{accountMap: map[string]int{“xiaoMing”: 100, “daZhuang”: 100}}

}

func (app *CounterApplication) DeliverTx(req types.RequestDeliverTx) types.ResponseDeliverTx {

fmt.Println(“DeliverTx进来了吗”)

//xiaoming转给dazhuang

tx8 := make([]byte, 8)

copy(tx8[len(tx8)-len(req.Tx):], req.Tx)

balance := int(binary.BigEndian.Uint64(tx8))

if app.accountMap[“xiaoMing”] 《 balance {

return types.ResponseDeliverTx{

Code: code.CodeTypeEncodingError,

Log: fmt.Sprintf(“Insufficient balance”)}

}

app.accountMap[“xiaoMing”] -= balance

app.accountMap[“daZhuang”] += balance

return types.ResponseDeliverTx{Code: code.CodeTypeOK}

}

func (app *CounterApplication) CheckTx(req types.RequestCheckTx) types.ResponseCheckTx {

fmt.Println(“CheckTx进来了吗”)

//xiaoming转给dazhuang

tx8 := make([]byte, 8)

copy(tx8[len(tx8)-len(req.Tx):], req.Tx)

balance := int(binary.BigEndian.Uint64(tx8))

if app.accountMap[“xiaoMing”] 《 balance {

return types.ResponseCheckTx{

Code: code.CodeTypeEncodingError,

Log: fmt.Sprintf(“Insufficient balance”)}

}

fmt.Println(“CheckTx ok”)

return types.ResponseCheckTx{Code: code.CodeTypeOK}

}

func (app *CounterApplication) Commit() (resp types.ResponseCommit) {

fmt.Println(“Commit进来了吗”)

appHash := make([]byte, 8)

binary.PutVarint(appHash, int64(len(app.accountMap))) //这里随便commit了一个hash

return types.ResponseCommit{Data: appHash}

}

func (app *CounterApplication) Query(reqQuery types.RequestQuery) types.ResponseQuery {

fmt.Println(“Query进来了吗”)

name := string(reqQuery.Data)

amount, ok := app.accountMap[name]

if !ok {

return types.ResponseQuery{Log: fmt.Sprintf(“Invalid name %v”, reqQuery.Data)}

}

return types.ResponseQuery{Value: []byte(fmt.Sprintf(“%v”, amount))}

}

先使用unsafe_reset_all参数启动一次tendermint,以清除之前的数据,然后启动tendermint和abci-cli开始测试

首先查询一下xiaoMing和daZhuang的初始余额:

C:Usersch》curl -s localhost:26657/abci_query?data=“xiaoMing”

{

“jsonrpc”: “2.0”,

“id”: “”,

“result”: {

“response”: {

“value”: “MTAw”

}

}

}

C:Usersch》curl -s localhost:26657/abci_query?data=“daZhuang”

{

“jsonrpc”: “2.0”,

“id”: “”,

“result”: {

“response”: {

“value”: “MTAw”

}

}

}

这里查询出来的结果还是base64编码的。

接下来转账:

C:Usersch》curl localhost:26657/broadcast_tx_commit?tx=0x11

{

“jsonrpc”: “2.0”,

“id”: “”,

“result”: {

“check_tx”: {},

“deliver_tx”: {},

“hash”: “4A64A107F0CB32536E5BCE6C98C393DB21CCA7F4EA187BA8C4DCA8B51D4EA80A”,

“height”: “3”

}

}

这里的0x11是16进制,换算成十进制就是17

再次查询余额:

C:Usersch》curl -s localhost:26657/abci_query?data=“xiaoMing”

{

“jsonrpc”: “2.0”,

“id”: “”,

“result”: {

“response”: {

“value”: “ODM=”

}

}

}

C:Usersch》curl -s localhost:26657/abci_query?data=“daZhuang”

{

“jsonrpc”: “2.0”,

“id”: “”,

“result”: {

“response”: {

“value”: “MTE3”

}

}

}

经过base64解码,ODM=就是83,MTE3就是117,测试成功!

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

9月2日消息,不造车的华为或将催生出更大的独角兽公司,随着阿维塔和赛力斯的入局,华为引望愈发显得引人瞩目。

关键字: 阿维塔 塞力斯 华为

加利福尼亚州圣克拉拉县2024年8月30日 /美通社/ -- 数字化转型技术解决方案公司Trianz今天宣布,该公司与Amazon Web Services (AWS)签订了...

关键字: AWS AN BSP 数字化

伦敦2024年8月29日 /美通社/ -- 英国汽车技术公司SODA.Auto推出其旗舰产品SODA V,这是全球首款涵盖汽车工程师从创意到认证的所有需求的工具,可用于创建软件定义汽车。 SODA V工具的开发耗时1.5...

关键字: 汽车 人工智能 智能驱动 BSP

北京2024年8月28日 /美通社/ -- 越来越多用户希望企业业务能7×24不间断运行,同时企业却面临越来越多业务中断的风险,如企业系统复杂性的增加,频繁的功能更新和发布等。如何确保业务连续性,提升韧性,成...

关键字: 亚马逊 解密 控制平面 BSP

8月30日消息,据媒体报道,腾讯和网易近期正在缩减他们对日本游戏市场的投资。

关键字: 腾讯 编码器 CPU

8月28日消息,今天上午,2024中国国际大数据产业博览会开幕式在贵阳举行,华为董事、质量流程IT总裁陶景文发表了演讲。

关键字: 华为 12nm EDA 半导体

8月28日消息,在2024中国国际大数据产业博览会上,华为常务董事、华为云CEO张平安发表演讲称,数字世界的话语权最终是由生态的繁荣决定的。

关键字: 华为 12nm 手机 卫星通信

要点: 有效应对环境变化,经营业绩稳中有升 落实提质增效举措,毛利润率延续升势 战略布局成效显著,战新业务引领增长 以科技创新为引领,提升企业核心竞争力 坚持高质量发展策略,塑强核心竞争优势...

关键字: 通信 BSP 电信运营商 数字经济

北京2024年8月27日 /美通社/ -- 8月21日,由中央广播电视总台与中国电影电视技术学会联合牵头组建的NVI技术创新联盟在BIRTV2024超高清全产业链发展研讨会上宣布正式成立。 活动现场 NVI技术创新联...

关键字: VI 传输协议 音频 BSP

北京2024年8月27日 /美通社/ -- 在8月23日举办的2024年长三角生态绿色一体化发展示范区联合招商会上,软通动力信息技术(集团)股份有限公司(以下简称"软通动力")与长三角投资(上海)有限...

关键字: BSP 信息技术
关闭
关闭