本文参考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的共识引擎以及三个交易处理器。

rustdesk windows自启动_docker


该环境通过处理业务逻辑的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配置文件还指定了从哪个仓库去下载镜像等,之后开发自己的相关容器时,也可以根据这个文件去进行相关的修改。

文件地址如下:

sawtooth-default.yaml

用如下命令将其下载在本地:

wget https://github.com/hyperledger/sawtooth-core/blob/1-2/docker/compose/sawtooth-default.yaml

如果wget命令下不动可以考虑在浏览器中打开这个地址复制粘贴下来。

如果Github下不动可以尝试寻找相关镜像网站等

步骤2:启动sawtooth docker环境

  1. 打开终端窗口
  2. 修改当前目录到sawtooth-default.yaml所在的目录
  3. 执行启动命令

这里我的工作目录为/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命令来把命令行当做客户端使用,这里使用到intkeysawtooth命令来创建和提交交易、列出区块以及区块数据和检查全局状态数据。

以下的命令需要在客户端容器中运行,因为本机是没有intkeysawtooth这两个命令的,这也是客户端容器存在的意义。

使用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环境就停止了,需要注意的一点是在该环境下进行的所有操作都会丢失,如果想要保留这些操作的话,需要挂载本地路径到容器中,才能把持久化真正应用到本地磁盘中。