带你读《GO语言公链开发实战》之二:交互工具

本文涉及的产品
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
简介: 本书的目标是引导读者全面了解区块链技术实现原理,笔者也一直坚信,了解某一系统最直接的方式就是研读它的源码,所以本书并不是只介绍区块链技术,而是深入分析其背后的实现原理。通过阅读本书,读者可以全面地了解一条公链的技术实现。本书基于比原链的源代码进行分析,比原链是一个开源的有智能合约功能的公共区块链平台,是国内优秀的公链,目前比原链的代码量不多,而且源码结构清晰,特别适合初学者学习。

点击查看第一章
点击查看第三章

第2章

交互工具

2.1 概述

bytomcli和dashboard是比原链提供的与bytomd进程交互的工具(基于RPC协议)。bytomcli是命令行客户端,dashboard是Web图形界面。dashboard相比bytomcli使用体验更友好,用户可随意选择。
通过交互工具可以完成与token、账户、交易、钱包、挖矿等相关的管理操作。
本章中,我们对bytomcli与bytomd进程的交互过程原理和代码进行分析,并对dashboard做一些简介,主要内容包括:

  • bytomcli交互工具介绍。
  • dashboard使用方法。

2.2 bytomcli交互工具

2.2.1 bytomcli命令flag参数

bytomcli的使用方式分为两种:一种是后面接flags参数,bytomcli [flags],bytomcli使用-h参数查看命令的帮助文档;另一种是后面接子命令,bytomcli [command]。所有的命令选项都可以通过执行-h或--help获得指定命令的帮助信息。bytomcli的帮助信息、示例相当详细,简单易懂。建议大家使用帮助信息。
$ ./bytomcli -h
Bytomcli is a commond line client for bytom core (a.k.a. bytomd)

Usage:
bytomcli [flags]
bytomcli [command]

Available Commands:
build-transaction 创建一笔交易
check-access-token 校验access token 是否合法
create-access-token 创建 accesss token
create-account 创建账户
create-account-receiver 创建账户地址
create-asset 创建资产
create-key 创建key
create-transaction-feed 创建交易feed过滤器
decode-program 将程序解码为指令和数据
decode-raw-transaction 解码原始交易
delete-access-token 删除access token
delete-account 删除账户
delete-key 删除key
delete-transaction-feed 删除交易feed 过滤器
estimate-transaction-gas 估算交易费
gas-rate 显示当前交易费比例
get-asset 通过资产id获得资产详情
get-block 根据区块哈希值或高度获取完成区块信息
get-block-count 获取最新区块的数量
get-block-hash 获取最新区块的哈希值
get-block-header 根据区块哈希值或高度获取完成区块的头部信息
get-difficulty 获取最新区块的难度值
get-hash-rate 获取最新区块的nonce值
get-transaction 根据交易hash值获取交易信息
get-transaction-feed 通过别名获取交易feed
get-unconfirmed-transaction 根据交易哈希值获取未确认的交易信息
help 显示帮助信息
is-mining 判断客户端是否开启挖矿功能
list-access-tokens 显示access token信息
list-accounts 显示账户信息
list-addresses 显示账户地址信息
list-assets 显示资产信息
list-balances 显示账户余额
list-keys 显示存在的key信息
list-pubkeys 显示账户公钥
list-transaction-feeds 显示所有的交易feed
list-transactions 显示交易信息
list-unconfirmed-transactions 显示未确认交易的哈希值
list-unspent-outputs 显示账户未使用的输出
net-info 显示当前网络信息
rescan-wallet 重新扫描块信息到钱包
reset-key-password 重置key 密钥
set-mining 开始/停止挖矿
sign-message 对消息进行签名
sign-transaction 使用账户密钥对交易进行签名
submit-transaction 提交签名的交易
update-asset-alias 更新资产别名
update-transaction-feed 更新交易feed
validate-address 校验交易地址
verify-message 校验消息签名
version 显示客户端版本信息
wallet-info 显示钱包信息
以上介绍了bytomcli命令行工具的详细参数。下面,将以一个实际的用例介绍如何使用bytomcli命令行工具。

2.2.2 使用bytomcli查看节点状态信息

使用net-info参数可以查看bytomd节点运行的网络状态。首先,使用bytomcli net-info-h查看net-info的帮助信息。命令执行如下:
$ ./bytomcli net-info -h
Print the summary of network
Usage:
bytomcli net-info [flags]
Flags:
-h, --help help for net-info
由输出的帮助信息可知,net-info命令仅支持一个可选的flags参数,flags参数列表又仅包含-h参数,可用来查看net-info命令的帮助信息。所以net-info命令的用法是十分简单的,使用bytomcli net-info即可查看节点的网络状态:
$ ./bytomcli net-info
{
"current_block": 36714,
"highest_block": 36714,
"listening": true,
"mining": false,
"network_id": "mainnet",
"peer_count": 10,
"syncing": false,
"version": "1.0.5+2bc2396a"
}
net-info参数返回数据如下所示。

  • current_block:当前节点的当前区块高度为36714。
  • highest_block:网络中最高区块高度为36714,表明节点已经拥有完整的区块数据。
  • listening:当前节点处于监听状态。
  • mining:当前节点是否启用挖矿功能。
  • network_id:标识节点连接的网络类型(mainnet为正式主网,wisdom为测试网络,solonet为单节点网络)。
  • peer_count:节点当前连接的其他节点个数。
  • syncing:当前节点是否正在同步区块数据。
  • version:节点的版本号。

2.2.3 bytomcli运行案例

本小节我们以net-info命令为例对bytomcli的源码进行剖析,其他命令参数与net-info参数执行的过程大同小异。
bytomcli相关代码文件结构如下所示:
$ tree cmd/bytomcli/
cmd/bytomcli/
├── bytomcli
├── commands commands目录存放bytomcli所有参数的实现
│ ├── accesstoken.go token参数相关
│ ├── account.go 账户参数相关
│ ├── asset.go 资产参数相关
│ ├── block.go 块参数相关
│ ├── bytomcli.go bytomcli flag解析相关
│ ├── key.go key参数相关
│ ├── mining.go 挖矿参数相关
│ ├── net.go 节点状态参数相关
│ ├── program.go 合约参数相关
│ ├── template.go 交易模板参数相关
│ ├── transaction.go 交易参数相关
│ ├── txfeed.go 目前版本该功能未使用
│ ├── util.go bytomcli相关输出结构体
│ ├── version.go 节点版本参数相关
│ └── wallet.go 本地钱包参数相关
└── main.go bytomcli入口函数
1.Cobra库介绍
bytomcli命令行工具是基于Cobra实现的。Cobra既可以用来创建强大的现代CLI应用程序库,也可以用来生成应用和程序文件。很多知名的开源软件都使用Cobra实现其CLI部分,例如kubernetes、docker、etcd等。
Cobra基于三个基本的概念—commands、arguments和flags,实现对命令参数的解析和行为控制。commands是应用程序的中心,应用程序支持的每个交互都包含在命令中,命令可以具有子命令并可选地运行子命令。flags是修改命令行为的方法,Cobra支持POSIX标准和GO的flags包,并可以同时作用于父命令和子命令的参数,也支持只在父命令或者子命令有效的参数。
如何使用Cobra库来构建自己的CLI程序呢?下面我们简单介绍Cobra库的使用。
(1)安装Cobra库
Cobra是非常容易使用的,使用go get来安装最新版本的库。Cobra库相对比较大,安装它可能需要花费一些时间。安装完成后,在GOPATH/bin目录下应该有已经编译好的Cobra程序。
$ go get -v github.com/spf13/cobra/cobra
(2)使用cobra命令生成应用程序
假设现在我们要开发一个基于CLI的命令程序,名字为demo。首先打开cmd,切换到GOPATH的src目录下,执行如下命令:
$ cobra init demo
在src目录下会生成一个demo的文件夹,如下:
$ tree demo/
demo/
├── LICENSE
├── cmd
│ └── root.go
└── main.go
如果此时应用程序不需要子命令,那么Cobra生成应用程序的操作就结束了。这里我们先实现一个没有子命令的CLI程序,之后再为程序添加子命令。
接下来继续为demo设计功能。我们打开Cobra自动生成的main.go文件查看,如下:
package main

import "demo/cmd"

func main() {

cmd.Execute()

}
main函数执行cmd包的Execute()方法,打开cmd包下的root.go文件查看,发现里面进行了一些初始化操作,并提供了Execute接口。其实,Cobra自动生成的root.go文件中有很多初始化操作是不需要的,其中viper是Cobra集成的配置文件读取的库,这里不需要使用,可以注释掉,如不注释掉则生成的应用程序会大10M左右。
在demo下面新建一个imp包,imp.go内容如下:
package imp

import(

"fmt"

)

func Show(name string, age int) {

fmt.Printf("My Name is %s, My age is %d\n", name, age)

}
在imp.go文件中,Show函数接收两个参数—name和age,使用fmt打印出来。此时,整个demo项目目录结构如下:
$ tree demo/
demo/
├── LICENSE
├── cmd
│ └── root.go
├── imp
│ ├── imp.go
└── main.go
Cobra的所有命令都是通过cobra.Command结构体实现的。为了实现demo功能,我们需要修改RootCmd。修改demo/cmd/root.go文件,如下所示:
var RootCmd = &cobra.Command{

Use:   "demo",
Short: "A test demo",
Long:  `Demo is a test appcation for print things`,
// Uncomment the following line if your bare application
// has an action associated with it:
Run: func(cmd *cobra.Command, args []string) {
    if len(name) == 0 {
        cmd.Help()
        return
    }
    imp.Show(name, age)
},

}
虽然我们已经定义了command结构,也能通过Execute接口调用RootCmd定义的回调方法。但是若要实现demo的功能还需从命令行解析传入的参数,这部分应该如何实现?这部分可以在cmd包的init方法中实现。init()函数会在每个包完成初始化后自动执行,并且执行优先级比main函数高。init()函数通常被用来对变量进行初始化操作。这里我们使用init()函数在main函数执行之前解析命令行参数。修改demo/cmd/root.go文件,如下所示:
var (

name string
age  int

)

func init() {

RootCmd.Flags().StringVarP(&name, "name", "n", "", "person's name")
RootCmd.Flags().IntVarP(&age, "age", "a", 0, "person's age")

}
至此,demo的功能已经实现了,我们编译运行一下看看实际效果,如下所示:
$ go run main.go
Usage:
demo [flags]

Flags:
-a, --age int person's age

  --config string   config file (default is $HOME/.demo.yaml)

-h, --help help for demo
-n, --name string person's name
-t, --toggle Help message for toggle
如果我们想实现一个带有子命令的CLI程序,只需要再执行cobra add为程序新增子命令。下面我们为demo程序新增一个server的子命令,如下所示:
$ cd demo
$ cobra add server
在demo目录下生成了一个cmd/server.go文件,如下所示:
$ tree demo/
demo/
├── LICENSE
├── cmd
│ ├── root.go
│ └── server.go
├── imp
│ └── imp.go
└── main.go
接下来配置server子命令,此操作与前文中修改root.go文件类似效果如下:
$ go run main.go
Usage:
demo [flags]
demo [command]

Available Commands:
help Help about any command
server A brief description of your command

Flags:
-a, --age int person's age

  --config string   config file (default is $HOME/.demo.yaml)

-h, --help help for demo
-n, --name string person's name
-t, --toggle Help message for toggle

Use "demo [command] --help" for more information about a command.
2. bytomcli运行流程与原理
对Cobra库有了了解之后,我们再来学习bytomcli的代码时会感觉比较容易,其运行原理如图2-1所示。同上一节中的demo程序一样,bytomcli在main函数中使用cmd.Execute()来启动应用程序,cmd.Execute()是调用commands包的Execute()方法。在mian.go中引入commands包的时候,给它起了一个别名cmd。
image.png

image.png

当程序调用commands包的Execute()方法时,会先执行commands包中所有的init()方法,这些init()主要用来解析命令行参数。当执行完commands包中所有的init()方法之后,才会执行Execute()。在Execute()方法中,首先执行AddCommands()方法,该方法主要用来给BytomcliCmd命令添加子命令;而AddTemplateFunc()方法则是为子命令添加使用模板的。在解析flags参数、添加子命令和添加使用模板这些初始化操作完成之后,才真正进入命令的执行过程。在BytomcliCmd.ExecuteC()方法中,Cobra库会根据用户输入的命令跳转到相应的子命令,同时执行命令定义的Run方法。
image.png

下面我们以create-access-token命令为例,看看这个命令的Run方法都执行了哪些操作。首先会取args参数的第一位作为tokenID,然后调用util包下的ClientCall方法请求/create-access-token路径,并将tokenID传入,创建token。
image.png
image.png

ClientCall方法封装了一个RPC的client,根据用户传入的路径和参数发送请求,并解析RPC server返回的内容。
image.png

至此,create-access-token命令执行完成,其生命周期终止。

2.3 dashboard交互工具

在比原链中,dashboard是单独一个项目,项目源码地址:https://github.com/Bytom/bytom-dashboard 。可能会有读者疑惑,既然dashboard是一个单独的项目,为什么在启动bytomd进程的时候会启用dashboard服务呢?这是因为dashboard编译后被硬编码到bytomd中,源码在dashboard/dashboard.go中。而在API Server下的api/api.go,我们可以看到引用handle信息如下:
image.png

2.3.1 使用dashboard发送一笔交易

在浏览器中输入http://127.0.0.1:9888/ ,打开dashboard页面。页面左下方显示当前节点同步区块的进度。点击右上角“新建交易”如图2-2所示。

image.png

在比原链中,新建交易分为两种,一种是简单交易,一种是高级交易。本节中使用简单交易发送一笔交易。高级交易会在后面章节进行详细讲解。
如图2-3所示,我们从本地钱包derek账户下的BTM资产往bm1q5p9d4gelfm4cc3zq3slj7vh2njx23ma2cf866j地址中打入了8 254 800Neu(诺),其中Gas的手续费约为500 000Neu(诺)。然后输入钱包密码并提交交易。得到结果如图2-4所示。
交易ID为3ebe89ddb64f3a7ef1742e...目前正在往主网中广播,待到交易确认则说明这笔交易最终成功。一般认为,一笔交易经过6个区块的验证后此交易无法逆转。

2.3.2 使用dashboard开启挖矿模式

在第1章介绍编译部署及应用时,介绍了如何使用bytomcli命令行交互的方式开启节点的挖矿模式,同样,我们也可以使用dashboard来启用或关停挖矿模式。
如图2-5所示,点击dashboard左上角齿轮按钮,点击核心状态,显示节点的配置信息,如图2-6所示。默认情况下挖矿选项是关闭状态,在这里我们可以启用节点的挖矿模式。

image.png

image.png

image.png

2.4 本章小结

本章对用户交互层做了详细介绍,对bytomcli命令行和dashboard进行了分析,对Cobra库的使用做了详细的介绍,并对Cobra如何生成CLI下flag的流程进行阐述。本章从源码的角度深入分析了bytomcli与bytomd的RPC交互过程。最后以dashboard发送一笔交易为例,展示了dashboard的使用方法。

相关文章
|
1天前
|
Go C语言
Go语言入门:分支结构
本文介绍了Go语言中的条件语句,包括`if...else`、`if...else if`和`switch`结构,并通过多个练习详细解释了它们的用法。`if...else`用于简单的条件判断;`if...else if`处理多条件分支;`switch`则适用于基于不同值的选择逻辑。特别地,文章还介绍了`fallthrough`关键字,用于优化重复代码。通过实例如判断年龄、奇偶数、公交乘车及成绩等级等,帮助读者更好地理解和应用这些结构。
27 14
|
16天前
|
存储 监控 算法
内网监控系统之 Go 语言布隆过滤器算法深度剖析
在数字化时代,内网监控系统对企业和组织的信息安全至关重要。布隆过滤器(Bloom Filter)作为一种高效的数据结构,能够快速判断元素是否存在于集合中,适用于内网监控中的恶意IP和违规域名筛选。本文介绍其原理、优势及Go语言实现,提升系统性能与响应速度,保障信息安全。
25 5
|
25天前
|
算法 安全 Go
Go语言中的加密和解密是如何实现的?
Go语言通过标准库中的`crypto`包提供丰富的加密和解密功能,包括对称加密(如AES)、非对称加密(如RSA、ECDSA)及散列函数(如SHA256)。`encoding/base64`包则用于Base64编码与解码。开发者可根据需求选择合适的算法和密钥,使用这些包进行加密操作。示例代码展示了如何使用`crypto/aes`包实现对称加密。加密和解密操作涉及敏感数据处理,需格外注意安全性。
41 14
|
25天前
|
Go 数据库
Go语言中的包(package)是如何组织的?
在Go语言中,包是代码组织和管理的基本单元,用于集合相关函数、类型和变量,便于复用和维护。包通过目录结构、文件命名、初始化函数(`init`)及导出规则来管理命名空间和依赖关系。合理的包组织能提高代码的可读性、可维护性和可复用性,减少耦合度。例如,`stringutils`包提供字符串处理函数,主程序导入使用这些函数,使代码结构清晰易懂。
70 11
|
25天前
|
存储 安全 Go
Go语言中的map数据结构是如何实现的?
Go 语言中的 `map` 是基于哈希表实现的键值对数据结构,支持快速查找、插入和删除操作。其原理涉及哈希函数、桶(Bucket)、动态扩容和哈希冲突处理等关键机制,平均时间复杂度为 O(1)。为了确保线程安全,Go 提供了 `sync.Map` 类型,通过分段锁实现并发访问的安全性。示例代码展示了如何使用自定义结构体和切片模拟 `map` 功能,以及如何使用 `sync.Map` 进行线程安全的操作。
|
30天前
|
监控 安全 算法
深度剖析核心科技:Go 语言赋能局域网管理监控软件进阶之旅
在局域网管理监控中,跳表作为一种高效的数据结构,能显著提升流量索引和查询效率。基于Go语言的跳表实现,通过随机化索引层生成、插入和搜索功能,在高并发场景下展现卓越性能。跳表将查询时间复杂度优化至O(log n),助力实时监控异常流量,保障网络安全与稳定。示例代码展示了其在实际应用中的精妙之处。
41 9
|
2月前
|
算法 安全 Go
Go 语言中实现 RSA 加解密、签名验证算法
随着互联网的发展,安全需求日益增长。非对称加密算法RSA成为密码学中的重要代表。本文介绍如何使用Go语言和[forgoer/openssl](https://github.com/forgoer/openssl)库简化RSA加解密操作,包括秘钥生成、加解密及签名验证。该库还支持AES、DES等常用算法,安装简便,代码示例清晰易懂。
64 12
|
JSON Go 数据格式
用Go语言编写一门工具的终极指南
我以前构建过一个工具,以让生活更轻松。这个工具被称为: gomodifytags ,它会根据字段名称自动填充结构体的标签字段。示例如下: (在 vim-go 中使用 gomodifytags 的一个用法示例) 使用这样的工具可以 轻松管理 结构体的多个字段。
8982 0
|
2月前
|
存储 监控 算法
员工上网行为监控中的Go语言算法:布隆过滤器的应用
在信息化高速发展的时代,企业上网行为监管至关重要。布隆过滤器作为一种高效、节省空间的概率性数据结构,适用于大规模URL查询与匹配,是实现精准上网行为管理的理想选择。本文探讨了布隆过滤器的原理及其优缺点,并展示了如何使用Go语言实现该算法,以提升企业网络管理效率和安全性。尽管存在误报等局限性,但合理配置下,布隆过滤器为企业提供了经济有效的解决方案。
92 8
员工上网行为监控中的Go语言算法:布隆过滤器的应用
|
2月前
|
存储 Go 索引
go语言中数组和切片
go语言中数组和切片
47 7