本文参考sawtooth官网的教程:https://sawtooth.hyperledger.org/docs/core/releases/latest/app_developers_guide/docker.html
本文在Ubuntu 20.04环境下进行安装,docker版本为19.03.11,docker-compose版本为1.29.0,docker和docker-compose都是需要事先安装好的,在之后会用到,sawtooth版本为v1.2.6。
该实验完成了如下目标:
- 检查Sawtooth组件的状态
- 使用sawtooth命令来提交交易,展示区块数据,看全局状态
- 检查sawtooth日志
- 停止sawtooth并且重置Docker环境
并且搭建起来的环境还可以用于之后的交易族(类似链码)部署。
这个docker环境启动了一个单节点的sawtooth,运行一个验证器,一个REST API,Devmode的共识引擎以及三个交易处理器。
该环境通过处理业务逻辑的IntegerKey和Settings交易处理器引入了基础的sawtooth功能,并使用命令行作为客户端,此外还引入了一个XO交易处理器,会在之后的教程中使用到。
这三个交易族中,IntegerKey和XO属于一个交易族的简单案例,但是Settings是一个参考实现,在生产环境中,也应该运行Settings的处理器来处理Settings的交易族。(个人感觉是配置相关的交易的处理)。
步骤1:下载sawtooth的docker compose文件
docker compose可以通过docker compose配置文件进行多个docker容器的启动,所以下载某个配置文件就相当于下载了docker容器整个的配置结构。这里下载的dockercompose文件中包含如下的容器:
- 一个单独的使用Devmode共识的验证者
- 连接到验证者的REST API
- Settings交易处理器
sawtooth-settings
- IntegerKey交易处理器
initkey-tp-python
- XO交易处理器
xo-tp-python
- 一个运行Sawtooth命令的客户端容器
整个docker compose配置文件还指定了从哪个仓库去下载镜像等,之后开发自己的相关容器时,也可以根据这个文件去进行相关的修改。
文件地址如下:
用如下命令将其下载在本地:
wget https://github.com/hyperledger/sawtooth-core/blob/1-2/docker/compose/sawtooth-default.yaml
如果wget命令下不动可以考虑在浏览器中打开这个地址复制粘贴下来。
如果Github下不动可以尝试寻找相关镜像网站等:https://blog.csdn.net/gongbing798930123/article/details/124493514。
步骤2:启动sawtooth docker环境
- 打开终端窗口
- 修改当前目录到sawtooth-default.yaml所在的目录
- 执行启动命令
这里我的工作目录为/home/zekdot/sawtooth/sawtooth-default.yaml,所以我运行了如下命令来启动:
cd /home/zekdot/sawtooth
docker-compose -f sawtooth-default.yaml up
PS:这里如果之前运行过启动命令了,想要清除相关镜像目录等再重启,可以运行如下命令:
docker-compose -f sawtooth-default.yaml down
运行启动命令之后就是漫长的等待了,因为有若干的镜像需要进行下载,当下载完成之后会打印出如下的内容:
....
beginning heartbeat pings.
sawtooth-intkey-tp-python-default | [2021-10-22 10:08:11.974 DEBUG core] received message of type: PING_REQUEST
sawtooth-settings-tp-default | INFO | sawtooth_sdk::proces | Message: 877c0e09535346ee8e900bbab686181d
sawtooth-settings-tp-default | INFO | sawtooth_sdk::proces | sending PingResponse
到这里就算启动完成了,这个终端需要保留,当在其他容器中运行命令时,这里仍然会打印日志,这里这样做应该是为了方便调试,这里亲测即使终端断开,容器仍然会在后台运行。
步骤3:登录客户端容器
在这步首先需要新开一个窗口,用于执行之后的命令。
这个客户端容器可以用于运行sawtooth命令,和验证者通过REST API进行交互。
使用如下命令来进入客户端容器:
docker exec -it sawtooth-shell-default bash
当提示符变成了root@7cf5f9cf4558:/#
,说明了已经进入了容器中。
这里的环境是用于实验的,所以执行的任何命令引起的变化,当docker-compose退出时都会丢失掉,如果要持久化这些变化,就需要挂载本地的实际目录到docker容器中。
步骤4:确认和REST API的连接
为了确保REST API和validator都在运行中并且客户端可达,可以使用如下命令来进行确认:
curl http://rest-api:8008/blocks
我这里会输出如下内容:
{
"data": [
{
"batches": [
{
"header": {
"signer_public_key": "02140f7b924c7b1cbc250ab8d33c40bd3cccb157f130b6652606dc2301b690249b",
...
"head": "bb29318d7689923818f25a32e941dbed844911e0f078d47250ec1de8a36a15b918c980ebd0e4a6a80d099d469a46de6fdc983f4dba670195772ae46778fcac74",
"link": "http://rest-api:8008/blocks?head=bb29318d7689923818f25a32e941dbed844911e0f078d47250ec1de8a36a15b918c980ebd0e4a6a80d099d469a46de6fdc983f4dba670195772ae46778fcac74&start=0x0000000000000000&limit=100",
"paging": {
"limit": null,
"start": null
}
}
在==本机(不处于客户端容器中)==的话可以使用如下命令来检测与REST API和validator的可达性:
curl http://localhost:8008/blocks
输出和在容器中的一致,这里如果有问题则使用curl命令不会有任何输出。
步骤5.作为客户端使用sawtooth命令
可以使用sawtooth命令来把命令行当做客户端使用,这里使用到intkey
和sawtooth
命令来创建和提交交易、列出区块以及区块数据和检查全局状态数据。
以下的命令需要在客户端容器中运行,因为本机是没有intkey
和sawtooth
这两个命令的,这也是客户端容器存在的意义。
使用intkey来创建和提交交易
intkey
命令来创建和提交IntegerKey交易族的交易来进行测试。
1.首先创建一个交易批次,这个交易批次会将一部分key对应随机的一部分value,然后随机的增加或者减少这些value,这些批次保存在本地文件batches.intkey中。
intkey create_batch --count 10 --key-count 5
执行完之后可以看到当前目录下出现了一个batches.intkey文件,这里的intkey命令应该对应的是IntegerKey交易族,利用交易族提供的API来进行账本的交互。
2.提交交易批次到验证者。
intkey load -f batches.intkey --url http://rest-api:8008
可以看到打印出如下内容:
batches: 11 batch/sec: 218.50195829564345
同时,使用docker-compose
命令的那个窗口打印出如下内容
ived message of type: TP_PROCESS_REQUEST
sawtooth-intkey-tp-python-default | [2021-10-23 09:28:46.333 DEBUG handler] Incrementing "uTlltv" by 1
sawtooth-intkey-tp-python-default | [2021-10-23 09:28:46.336 DEBUG core] received message of type: TP_PROCESS_REQUEST
sawtooth-intkey-tp-python-default | [2021-10-23 09:28:46.339 DEBUG handler] Incrementing "hOnjtl" by 2
sawtooth-validator-default | [2021-10-23 09:28:46.345 INFO (unknown file)] [src/journal/block_validator.rs: 265] Block 17d743ff8fdaec2245a5f28822c1866d522a5828b5aeaabd0dfdabfe87d55eb607c2aa6ca21758de3d94629349609a49848d232605bbbd01d75cae8049f6b1a7 passed validation
sawtooth-validator-default | [2021-10-23 09:28:46.364 DEBUG gossip] Connection None is no longer valid. Removing from list of peers.
使用sawtooth批量提交来提交交易
1.首先创建一个交易批次
intkey create_batch --count 10 --key-count 5
2.然后使用sawtooth批量提交命令来提交交易
sawtooth batch submit -f batches.intkey --url http://rest-api:8008
事实上也可以在docker-compose那个窗口看到打印的信息:
sawtooth-intkey-tp-python-default | [2021-10-23 09:46:25.912 DEBUG core] received message of type: TP_PROCESS_REQUEST
sawtooth-intkey-tp-python-default | [2021-10-23 09:46:25.914 DEBUG handler] Incrementing "HkxYni" by 1
sawtooth-intkey-tp-python-default | [2021-10-23 09:46:25.918 DEBUG core] received message of type: TP_PROCESS_REQUEST
sawtooth-intkey-tp-python-default | [2021-10-23 09:46:25.921 DEBUG handler] Decrementing "HkxYni" by 7
使用sawtooth block命令查看区块链和区块数据
sawtooth block
命令可以展示区块链中的区块相关信息。
1.展示存储在世界状态中的区块列表:
sawtooth block list --url http://rest-api:8008
可以看到如下的输出:
NUM BLOCK_ID BATS TXNS SIGNER
3 3290cd2c3728eb24182bb9a8c4cdccdf49210ecd002cb49a1cad1b568cb545c509edd7b35afa6abfcf8f8f07b7c7f0a694c433c7e7ceec8f34a6f51d13b8eb49 11 63 03516a...
2 17d743ff8fdaec2245a5f28822c1866d522a5828b5aeaabd0dfdabfe87d55eb607c2aa6ca21758de3d94629349609a49848d232605bbbd01d75cae8049f6b1a7 1 6 03516a...
1 3bd5b562ba342bae9910c766bc351b28535ead0da833e08c4fcf3d2b58a5df852ca62f42b49bb57a232f10b3d2300d106361ac29429ea4500c594741169d4cef 10 50 03516a...
0 75a6f03a05fa8e1befa5a2bb0784dbde56d32e64eef8713295cce92932dc9a276f64aae161a00ea014bb3b4a6cbfd3cf0152cb821d99ee7d6b9cd8eb84a2f573 2 3 03516a...
输出包含区块序号以及区块的id,可以通过区块id(BLOCK_ID)查看区块中的详情,比如这里想查3号区块中的内容:
sawtooth block show --url http://rest-api:8008 3290cd2c3728eb24182bb9a8c4cdccdf49210ecd002cb49a1cad1b568cb545c509edd7b35afa6abfcf8f8f07b7c7f0a694c433c7e7ceec8f34a6f51d13b8eb49
输出内容比较长,因为是整个区块存储的所有数据
...
trace: false
transactions:
- header:
batcher_public_key: 0221b77a9d442ac7d4a469c88c739d54c20b40d4c2f474a89ea0dbafdd0bafc51f
dependencies:
- 1c4d842544eb268041d77f55405d06d781d616c7012dede9b86e22d5511d66361a748aec15fccc252b96bde1f22ef986dbbe5fd1e679f746fdd9aa99f1240bd8
family_name: intkey
family_version: '1.0'
inputs:
- 1cf12628e5c082723b6111e4051aee7e2fc52ae91eb56a515f1683d47b495f54d05d03
nonce: '0x902fd36a99cace2f'
outputs:
- 1cf12628e5c082723b6111e4051aee7e2fc52ae91eb56a515f1683d47b495f54d05d03
payload_sha512: 0a241d556b73bc167bfce635054a386d5ded228f56c106d043e718ffdd916747767b6100b46a99431bb2b9c5fc82d5d95b54fbf1e3059bf087f0f0986f1ce1db
signer_public_key: 0221b77a9d442ac7d4a469c88c739d54c20b40d4c2f474a89ea0dbafdd0bafc51f
...
大概扫了一眼,包含区块头、签名、各交易输出以及包含的交易族等信息,之后再细看吧。
使用sawtooth state命令查看世界状态
使用sawtooth state
命令可以列出世界状态数据,sawtooth的世界状态存在一个叫Merkle-Radix tree的数据结构中,可以点开这个链接去看更加细节的内容。
1.使用如下命令列出世界状态中的所有地址
sawtooth state list --url http://rest-api:8008
会返回如下内容:
ADDRESS SIZE DATA
000000a87cb5eafdcca6a8c983c585ac3c40d9b1eb2ec8ac9f31ff5ca4f3850ccc331a 45 b'\n...
000000a87cb5eafdcca6a8c983c585ac3c40d9b1eb2ec8ac9f31ff82a3537ff0dbce7e 46 b'\n...
000000a87cb5eafdcca6a8cde0fb0dec1400c5ab274474a6aa82c12840f169a04216b7 110 b'\n...
...
1cf126a08e9952f54c4029f1baccd451bac584858d7c5ff123544e5847222c49047107 11 b'\x...
1cf126a835f7289f0dfce601f1829bbbae010c1b5e67e71a7e5abee815b08c8a5a8dc4 13 b'\x...
HEAD BLOCK: "3290cd2c3728eb24182bb9a8c4cdccdf49210ecd002cb49a1cad1b568cb545c509edd7b35afa6abfcf8f8f07b7c7f0a694c433c7e7ceec8f34a6f51d13b8eb49"
2.如果想看特定地址存储的数据(这个地址为Merkle-Radix数据库的一个节点),则可以使用如下命令,这里以第一个地址为例。
sawtooth state show --url http://rest-api:8008 000000a87cb5eafdcca6a8c983c585ac3c40d9b1eb2ec8ac9f31ff5ca4f3850ccc331a
输出如下
DATA: "b'\xa1fuTlltv\x19\xea\xfb'"
HEAD: "3290cd2c3728eb24182bb9a8c4cdccdf49210ecd002cb49a1cad1b568cb545c509edd7b35afa6abfcf8f8f07b7c7f0a694c433c7e7ceec8f34a6f51d13b8eb49"
步骤5:检查容器的日志
首先可以用如下命令列出sawtooth相关的日志。
docker ps | grep sawtooth
会打印出如下内容
ccfbffcf90e0 hyperledger/sawtooth-shell:chime "bash -c 'sawtooth k…" 4 hours ago Up 4 hours 4004/tcp, 8008/tcp sawtooth-shell-default
83a3ae3e08d9 hyperledger/sawtooth-xo-tp-python:chime "xo-tp-python -vv -C…" 4 hours ago Up 4 hours 4004/tcp sawtooth-xo-tp-python-default
7b7795d78435 hyperledger/sawtooth-rest-api:chime "sawtooth-rest-api -…" 4 hours ago Up 4 hours 4004/tcp, 0.0.0.0:8008->8008/tcp, :::8008->8008/tcp sawtooth-rest-api-default
cb30b023fb2b hyperledger/sawtooth-intkey-tp-python:chime "intkey-tp-python -v…" 4 hours ago Up 4 hours 4004/tcp sawtooth-intkey-tp-python-default
749d1f103386 hyperledger/sawtooth-settings-tp:chime "settings-tp -vv -C …" 4 hours ago Up 4 hours 4004/tcp sawtooth-settings-tp-default
31047737a31f hyperledger/sawtooth-devmode-engine-rust:chime "devmode-engine-rust…" 4 hours ago Up 4 hours sawtooth-devmode-engine-rust-default
fc9e937af688 hyperledger/sawtooth-validator:chime "bash -c 'sawadm key…" 4 hours ago Up 4 hours 0.0.0.0:4004->4004/tcp, :::4004->4004/tcp sawtooth-validator-default
查看某个容器的日志有两种方式。
第一种,直接使用docker的日志命令。
docker logs (OPTIONS) (ContainerName)
第二种,首先进入容器,然后查看/var/log/sawtooth下的内容。
docker docker exec -it {ContainerName} bash
ls -1 /var/log/sawtooth
步骤6:停止sawtooth环境
在docker-compose命令的终端下按CTRL+C,停止容器的运行。
然后到sawtooth-default.yaml所在的路径下,我这里的路径为/home/zekdot/sawtooth,运行如下命令移除相关容器。
docker-compose -f sawtooth-default.yaml down
到这里sawtooth环境就停止了,需要注意的一点是在该环境下进行的所有操作都会丢失,如果想要保留这些操作的话,需要挂载本地路径到容器中,才能把持久化真正应用到本地磁盘中。