blockstack-Trans

naming-Clarity Smart Contracts-H

2019-08-02  本文已影响5人  空乱木

FROM : https://docs.blockstack.org/core/smart/tutorial.html

在本教程中,您将学习如何使用Blockstack的智能合约语言Clarity。使用本教程快速了解Clarity和默认Blockstack测试环境。

开始之前(先决条件)
任务1:设置测试环境
任务2:回顾一个简单的Clarity程序
任务3:初始化数据空间和启动合约
任务4:检查SQLite数据库
任务5:执行一个公共函数
任务6:通过注册一个名称来使用令牌

Clarity在预发布中

Clarity及其附带的工具集已经发布。如果您遇到有关清晰度的问题或有特性请求,请在blockstack/blockstack-core存储库上创建一个问题。要阅读以前的或加入正在进行的关于智能合约的讨论,特别是关于Clarity的讨论,请访问Blockstack论坛中的智能合约主题。

开始之前(先决条件)

Clarity语言将在接下来的栈区块链fork中运行。在fork之前,您可以在测试环境中运行Clarity。您在Docker容器中运行这个测试环境。在开始本教程之前,请确保在工作站上安装了Docker。

如果由于某种原因您不想使用Docker运行测试环境,您可以构建和维护一个本地环境。下载和构建环境的说明可以在blockstack/blockstack-core repository的README文件中找到。

任务1:设置测试环境

Blockstack在Docker hub上发布了clarity-developer-preview镜像。从该镜像构建的容器包含示例程序、Blockstack核心和用于处理它们的工具。在这个任务中,您使用Docker在本地工作站上拉出并运行映像。

1.从Docker Hub中拉出Blockstack核心clarity-developer-preview镜像。

$ docker pull blockstack/blockstack-core:clarity-developer-preview

2.使用Bash shell启动Blockstack核心测试环境。

docker run -it -vHOME/blockstack-dev-data:/data/ blockstack/blockstack-core:clarity-developer-preview bash
上面显示的内容不准确:参考下边:

image.png

启动一个带有Clarity测试环境的容器,并在容器中打开一个bash shell。v标志在工作站上创建一个本地$HOME/blockstack-dev-data目录,并将其挂载在容器内的/data目录中。shell打开到src/blockstack-core目录。此目录包含核心的源代码,并包含可以运行的Clarity合约示例。

3.列出sample-programs目录的内容。

root@f88368ba07b2:/src/blockstack-core# ls sample-programs/
names.clar tokens.clar

示例程序目录包含两个简单的Clarity程序。Clarity代码文件有一个.clar后缀。

4.继续并显示tokens.clar的内容。用cat命令编写clar程序。
root@c28600552694:/src/blockstack-core# cat sample-programs/tokens.clar

下一节将通过研究这个程序的代码来介绍Clarity语言。

任务2:回顾一个简单的Clarity程序

如果还没有这样做,请使用cat或more命令来显示tokens.clar文件的代码。Clarity用于静态分析;它不是一种编译语言,图灵也不完整。是一种类似LISP的语言。LISP是列表处理的缩写。

tokens.clar标记的第一行包含一个用户定义的get-balance函数。

(define (get-balance (account principal))
(default-to 0 (get balance (fetch-entry tokens (tuple (account account))))))

get-balance是一个私有函数,因为它是用define调用构造的。要创建公共函数,可以使用define-public函数。公共函数可以从其他合约调用,甚至可以从命令行使用clear -cli调用。

注意,程序包含在()(括号)和每个语句中。get-balance函数接受特殊类型principal的account参数。主体表示支出实体,大致相当于Stacks地址。

除了主要类型外,Clarity还支持布尔值、整数和固定长度缓冲区。变量是通过let绑定创建的,但是不支持对set这样的函数进行修改。

下一行显示了一个if语句,它允许您设置语言执行的条件。

(define (token-credit! (account principal) (tokens int))
(if (<= tokens 0)
(err "must move positive balance")
(let ((current-amount (get-balance account)))
(begin
(set-entry! tokens (tuple (account account))
(tuple (balance (+ tokens current-amount))))
(ok tokens)))))

每个智能合约都有数据空间和代码。合约的数据空间只能与该合约交互。这个特殊的函数与一个名为tokens的映射交互。set-entry!函数是一个本机函数,它将与输入键关联的值设置为tokens数据映射中输入的值。因为set-entry!修改数据,使其具有!感叹号;按照惯例,这是很清楚的。

在第一个token-transfer公共函数中,您可以看到它调用私有get-balance函数并传递它tx-sender。tx-sender是一个全局定义的变量,表示当前主体。

(define-public (token-transfer (to principal) (amount int))
(let ((balance (get-balance tx-sender)))
(if (or (> amount balance) (<= amount 0))
(err "must transfer positive balance and possess funds")
(begin
(set-entry! tokens (tuple (account tx-sender))
(tuple (balance (- balance amount))))
(token-credit! to amount)))))

(define-public (mint! (amount int))
(let ((balance (get-balance tx-sender)))
(token-credit! tx-sender amount)))

(token-credit! 'SZ2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQ9H6DPR 10000)
(token-credit! 'SM2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQVX8X0G 300)

程序的最后两行传递一个主体(由Stacks地址表示)和一个金额给私有用户定义的token-credit函数。

智能合约可以使用contract-call!调用其他智能合约函数。这意味着,如果事务调用给定智能合约中的函数,该函数就能够代表您调用其他智能合约。读取和执行Clarity代码静态分析的能力允许客户端了解给定的智能合约将调用哪些函数。好的客户端应该始终警告用户给定事务的任何潜在副作用。

用cat命令查看一下names.clar文件的内容

cat names.clar

哪一个tokens.clar中的函数正在被调用?

任务3:初始化数据空间和启动合约

在此任务中,您将使用clear -cli命令行与合约进行交互。

1.在/data/目录中初始化一个新的db数据库

clarity-cli initialize /data/db

Database created

您应该看到一条消息,说数据库已经创建。该命令创建一个SQLlite数据库。数据库可以在容器中使用,也可以在工作站上使用。在本教程中,您的工作站挂载此时应该包含$HOME/blockstack-dev-data/db目录。

2.输入检查names.clar合约

clarity-cli check sample-programs/names.clar /data/db

你应该得到一个错误:

Type check error.
NoSuchContract("tokens")

这是因为names.clar合约调用tokens.clar合约,而该合约尚未在区块链上创建。

3.键入检查tokens.clar合约,它应该通过检查,因为它没有使用contract-call功能:

clarity-cli check sample-programs/tokens.clar /data/db

Checks passed.

4.启动tokens.clar合约
使用launch命令在blockstack区块链上实例化合约。如果合约之间存在依赖关系,例如names.clar依赖于tokens.clar,您必须首先启动依赖项。

clarity-cli launch tokens sample-programs/tokens.clar /data/db

Contract initialized!

一旦启动,就可以在合约上执行合约或公共方法。您的开发数据库有一个实例化的tokens合约。如果要关闭容器,稍后用相同的挂载点重新启动它,并且不需要重新启动该数据库;它会一直存在,直到您从本地驱动器中删除它。

5.重新检查names.clar合约

clarity-cli check sample-programs/names.clar /data/db

程序应该通过验证,因为它依赖于tokens.clar满足了。

6.实例化names.clar合约

clarity-cli launch names sample-programs/names.clar /data/db

任务4:检查SQLite数据库

测试环境使用SQLite数据库表示区块链。你初始化这个数据库,当你运行这个早些时候:

clarity-cli initialize /data/db

在处理合约时,数据被添加到db数据库中,因为您将该数据库作为参数传递,例如:

clarity-cli launch tokens sample-programs/tokens.clar /data/db

数据库存在于您的本地工作站上,并通过重新启动容器来保持。您可以使用这个数据库来检查Clarity程序的效果。SQLite数据库中的表如下:

名称 目的
contracts 列出合约并存储它的JSON描述。
data_table 列出与合约关联的数据。
maps_table 列出与合约关联的映射类型,并存储其JSON描述。
simmed_block_table 通过模拟对区块链信息查询的响应来支持测试环境。
type_analysis_table 提供描述合约数据的JSON。

虽然不是必需的,但是您可以在本地环境中安装SQLite,并使用它来检查与您的合约相关和受合约影响的数据。例如,这就是初始化tokens合约后maps_table所包含的内容。

sqlite> select * from maps_table;
1|tokens|tokens|{"Atom":{"TupleType":{"type_map":{"account":{"Atom":"PrincipalType"}}}}}|{"Atom":{"TupleType":{"type_map":{"balance":{"Atom":"IntType"}}}}}

sqlite>

任务5:执行一个公共函数

在本节中,您将使用公共mint!函数在tokens合约中生成一些新令牌。

1.使用clarity_cli命令创建演示地址。

clarity-cli generate_address

SP26CHZZ26Q25WDD1CFJYSED169PS9HTNX445XKDG

2.将地址添加到您的环境中。

DEMO_ADDRESS=SP26CHZZ26Q25WDD1CFJYSED169PS9HTNX445XKDG

3.获取新地址的当前余额。

echo "(get-balance '$DEMO_ADDRESS)" | clarity-cli eval tokens /data/db

Program executed successfully! Output:
0

该命令使用令牌合约中的私有get-balance函数,并将结果传递给eval子命令。eval子命令允许您以只读模式评估合约的公共函数和私有函数。

4.尝试生成一些令牌并将它们发送到我们将用于演示的地址。

clarity-cli execute /data/db tokens mint! $DEMO_ADDRESS 100000

这将执行公共mint!在tokens合约中定义的函数,将100,000令牌发送给您$DEMO_ADDRESS。

5.使用clear -cli eval命令检查这个调用的结果。

echo "(get-balance '$DEMO_ADDRESS)" | clarity-cli eval tokens /data/db
Program executed successfully! Output:
100000

任务6:通过注册一个名称来使用tokens

现在,让我们使用names.clar合约注册一个名称。在这个示例合约中,名称只是整数,所以您将注册名称10。

1.计算要注册的名称的哈希值。
你可以用8888加盐:

echo "(hash160 (xor 10 8888))" | clarity-cli eval names /data/db
Program executed successfully! Output:
0xb572fb1ce2e9665f1efd0994fe077b50c3a48fde

名称哈希值为:
0xb572fb1ce2e9665f1efd0994fe077b50c3a48fde

2.使用执行命令对名称进行预排序:

clarity-cli execute /data/db names preorder $DEMO_ADDRESS 0xb572fb1ce2e9665f1efd0994fe077b50c3a48fde 1000

Transaction executed and committed. Returned: 0

这将执行names.clar合约中的public preorder函数。明白”合同。函数通过支付名称费(在本例中是1000个tokens)来保留名称。

3.查看演示地址' new balance:

echo "(get-balance '$DEMO_ADDRESS)" | clarity-cli eval tokens /data/db
Program executed successfully! Output:
99000

4.通过执行Register函数注册名称:

clarity-cli execute /data/db names register DEMO_ADDRESS \'DEMO_ADDRESS 10 8888
Transaction executed and committed. Returned: 0clarity-cli execute /data/db names register DEMO_ADDRESS \'DEMO_ADDRESS 10 8888

5.查询名称的“所有者地址”:

echo "(get owner (fetch-entry name-map (tuple (name 10))))" | clarity-cli eval names /data/db
Program executed successfully! Output:
(some 'SP26CHZZ26Q25WDD1CFJYSED169PS9HTNX445XKDG)

下一步该去哪里

上一篇下一篇

猜你喜欢

热点阅读