原文链接:https://www.onflow.org/post/flow-blockchain-cadence-programming-language-resources-assets
翻译:Jihui Zheng(来自Flow开发社区)
前言
Flow 是一个新的区块链,最初由 CryptoKitties 和 NBA Top Shot 的母公司 Dapper Labs 设计和开发。在接下来的一系列文章中,我们将从技术角度探讨 Flow 链的各个基础组件。
-
Cadence,一种使智能合约开发过程更快、更安全的新编程语言
-
Flow Client Library (FCL),它类似于以太坊上的 Web3.js,但更加简洁通用
-
Flow 多节点架构,面向未来的主流扩展架构(即将推出)
随着加密货币的大规模采用,区块链应用程序上承载的价值在不断增长, 但用来处理这些链上数字资产的技术工具仍不成熟。尽管有高成本且耗时的安全审计,但链上智能合约通常无法提供长期可持续的安全模型,一个可以安全且公平地处理链上存储价值的模型,开发人员通常需要从头创建一些工具才能实现一些基本的安全功能。直到现在,还缺乏一种能够完全安全地处理数字资产的编程语言。
PROFILE
进入Cadence的世界
Cadence 是第一种专门用于链上数字资产所有权的编程语言,例如区块链上的艺术品、收藏品或加密货币。在 Cadence 中,数字资产是一等公民,在可以很好的控制数字资产的访问的同时,做到了防止数字资产意外丢失或恶意复制的可能性。
Cadence 使用一种独特的数字资产数据模型:资源。资源使数字资产的创建、传输和存储更容易、更安全。与基于权利属性的的资源访问控制策略相结合,让这门编程语言的学习曲线更平缓、更容易被审计,并且比任何当前的其他替代方案的开发效率都更高。
基于 Flow 以用户为中心的账户模型,Cadence 引入了数字资产的直接所有权模型,可实现更高程度的去中心化和抗攻击性。用户的数字资产被安全地存储在用户的帐户中。
Cadence 在编写时考虑到了消费级用例,在其坚实的科学研究基础之上构建了可扩展性。作为 NBA Top Shot 的支柱,它已经过大规模的实战测试,这是有史以来增长最快的区块链应用程序之一,注册人数超过一百万。
除此之外,每天都有成千上万的用户与越来越多的 Cadence 驱动的应用程序(如市场、游戏或交易所)进行交互,证明了其耐用性和可靠性。这些好处每天都会吸引新的开发人员,使他们能够享受 Cadence 改进的安全性、生产力和可读性带来的好处。
Diem (Move) 等行业的其他大玩家开始利用资源的力量这一事实暗示下一代智能合约编程可能会开启面向资源的语言时代,而 Cadence 是第一个准备就绪的面向资源的语言今天在区块链上使用
数字资产应对的挑战
让区块链技术开辟一个充满可能性的新世界的最大创新是实现原生数字价值。在区块链上,代码不仅仅是对某种外部资产的映射,而是这些链上的代码本身就是资产。区块链上的数据不会轻易丢失、无法被任意复制和篡改,这些链上的数据自身是有价值的,是用户可以去持有的。无论是 NFT、收藏品、加密货币还是治理代币,它们都是这一类新兴数字资产类别的一部分。
尽管这种资产演变的前景令人兴奋,但令人担忧的是,目前用来管理这些数字资产的工具依然处于原始社会:像 Solidity 这样的智能合约编程语言处理数字资产及其可能带来的巨大价值和处理任何其他可变的数据结构没有任何区别,同时这些数字资产又是存储在一个*账本中。下面用一些例子来说明这些编程语言在处理数字资产方面所面临的巨大风险和挑战。
■ 案例1: *账本创建蜜罐陷阱
以下代码片段展示了使用 Solidity来简易的实现同质化代笔。这个受 ERC-20标准启发的同质化代币智能合约包含两个功能:允许生成新代币的铸币功能,以及允许将资金转移到不同地址的发送功能。
contract AnyCoin {
mapping (address => uint) public balance;
function mint(address receiver, uint amount) {
balance[receiver] += amount;
}
function send(address receiver, uint amount) {
balance[msg.sender] -= amount;
balance[receiver] += amount;
}
}
关于数字资产的关键问题是:每个人的代币持有量在哪里以及如何存储?该片段显示,这些代币持有量由合约顶部的数据结构表示:余额映射。这种数据结构是一个*账本,将每个持有人的地址映射到特定的代币余额,有效地将所有数字资产存储在智能合约本身中。
mapping(address => uint) public balance;
这些*映射通常负责一次处理数十亿美元的等值价值,正如看一眼以太坊上最受欢迎的 ERC-20 代币合约所示。以如此集中的方式存储这些大量的数字资产为黑客创建了*蜜罐。不幸的是,数百万美元的黑客已经成为许多团队和用户的悲惨现实:仅在 2020 年,整个加密犯罪造成的总价值就达到了 19 亿美元,其中黑客的总价值为 5.13 亿美元[来源](https://www.securitymagazine.com/articles/94627-19b-in-crypto-currency-stolen-by-hackers-last-year)。但这种集中存储只是 Solidity 等语言存在的问题中的一个。
■ 案例2: 数字资产需要一个更灵活的数据模型
因为Solidity中的映射是可变的数据结构,它没有强加任何处理数字资产的约束规则,所以没有什么可以阻止开发人员错误地编写恶意代码。为了说明这一点,让我们看一下代币合约的另一个实现。
contract BugCoin {
mapping (address => uint) public balance;
function mint(address receiver, uint amount) {
balance[receiver] += amount;
}
function send(address receiver, uint amount) {
balance[msg.sender] -= amount;
// balance[receiver] += amount;
}
}
在这个例子中,发送函数中被注释了一行必不可少的代码:BugCoin 的转移会导致发送方的余额被扣除 ,但接收方的余额永远不会增加。由于缺少一行代码,该合约的任何转移的的价值都将永久丢失。令人震惊的是,没有什么能阻止以太坊上的合约发生类似的情况。由于Solidity编译器不会对这类语义错误做检查,所以这段代码可以毫无障碍地部署在测试网甚至主网上,在每笔转移资产的交易中吞噬转移的代笔并让用户的权益受损。
智能合约的不可随意修改的性质及其上承载的数额巨大的资产给区块链开发人员带来了巨大的责任和压力。正如上面两个例子所展示的,现有智能合约编程语言的局限性让程序员的开发过程异常的艰难。事实上,还有更多底层代码需要处理,比如管理数值上下溢出的问题,或者在不同货币单位之间进行转换。这在一个每天需要处理大量资产的地方,这些问题会造成不少麻烦。这就产生了能够有一种可以安全地处理数字资产的智能合约编程语言的需求。
> 认识 Cadence,这是为数字资产而设计的语言。
Cadence: 使用面向资源范式来解决数字资产安全问题
Cadence 通过为数字资产引入一种新的自定义数据模型:资源,来消除了现有智能合约编程语言所带来的大部分风险。受线性类型的启发,资源模型能让开发人员提前发现运行时错误,在开发期间就可以即使发现并且做出代码修改来规避。
开发人员在使用Cadence的时候可以很清楚的知道自己是否在处理资源类型数据,因为资源的创建或传输需要使用移动运算符 (<-),而资源数据的类型会使用符号 (@) 来标注说明。这些直观的符号可以防止开发者错误地使用Cadence,并且让代码更易于阅读、编写、学习和维护。
但是 Cadence 的资源模型并不仅仅只是现有数据模型的语法糖,而是在操作资产时会执行严格的规则约束,可以避免因为开发人员的错误而导致数字资产丢失。资源模型规定一个资源只能在一个确定的时间存在于一个确定的地方,使其不可以被恶意复制或意外删除,并提高所有涉及数字资产操作的安全性。
还记得我们在 BugCoin 合约中的制造的恶意发送功能吗?在 Cadence 中,这种代码从一开始就不会被编译。这是因为 Cadence 中同质化代币合约的代币持有量是通过严格的规则约束的资源模型来实现的。每个代币持有者都有自己的保险库资源,用于在其账户中持有该代币,并且该资源会提供提款和存款方法。
pub resource Vault: Provider, Receiver, Balance {
// pub = publicly readable, internally writable
pub var balance: UFix64
init(balance: UFix64) {
self.balance = balance
}
pub fun withdraw(amount: UFix64): @Vault {
self.balance = self.balance - amount
return <-create Vault(balance: amount)
}
pub fun deposit(from: @Vault) {
self.balance = self.balance + from.balance
destroy from
}
}
资产在进行转移的时候永远是安全的,因为交易金额在被提款后会被放入临时金库资源中。这个临时金库然后可以存入其他人的存入功能,或被显式删除。但与 Solidity 示例中的 send 函数不同,代币是不可能会意外丢失的,因为如果有资源没有被使用,Cadence编译器将抛出错误。
transaction {
var temporaryVault: @ExampleToken.Vault
prepare(...) {
...
self.temporaryVault <- myVault.withdraw(amount: 10.0)
}
execute {
...
// Type-check will not pass if temporaryVault is not explicitly used!
receiverRef.deposit(from: <-self.temporaryVault)
}
post {
...
}
}
这个例子说明了这种数据模型在安全性方面的两个额外优势:
-
首先,如果接收者没有代币保险库 - 无论是因为地址错误还是该账户不想接收这些类型的代币 - 交易将会被回滚。不会再有代币因为发送地址拼写错误而丢失!
-
其次,在事务和函数中包含前置和后置条件使得开发人员可以很容易实现对正确结果的断言检查,因此开发人员和用户可以对其基于区块链的交互的正确性充满信心。
除了使对数字资产操作的开发更具可读性和安全性之外,资源模型还允许使用组合和嵌套等高级用例。如果要对资源进行分组,您只需创建一个集合资源作为单个资源的包装器。这使得开发人员很容易实现资源的批量转移(多个资源同时转移),加快开发过程,让用户更快、更安全地进行价值传递。
所有权模型: 让资产呆在它们本应该呆的地方
Cadence 的另一个巨大优势在于它与 Flow 协议的深度集成:资源存储在它们所属的地方,直接存储在用户的帐户中。
let myCoolAsset <- create CoolAsset()
account.save<@CoolAsset>(<-myAsset, to: /storage/myCoolAsset)
这种以人为本的账户模型对数字资产有更直接的所有权,并且与Solidity等语言提供的*账本方法相比具有多种优势:
■更去中心化更安全
> 不同于Solidity等语言会将数字资产存储在智能合约中会造成单点事故,Cadence永远都将数字资产存储在用户自己的账户中。这显着提高了安全性,因为它最大限度地减少和分散了大规模攻击的载体,通过分散潜在攻击目标使得攻击成本足够高使得攻击行为性价比变低。
■ 提高效率
> 使用*账本模型很难完整地收集一个特定用户拥有的所有资产的信息,因为这需要对用户可能持有资产的每一个智能合约进行查询交互。使用 Flow,用户的所有数字资产都在他们的账户中,使这些资产更易于查询和交互。
■ 更容易使用
> 不仅仅是开发人员,Flow上的用户也都会发现这种以人为中心的帐户模型更容易去理解,因为它避免了不必要的复杂性并建立在大多数人的直觉模型上 ——显然*帐本模型违反直觉且难以理解。
但最重要的是,Flow 直观的账户模型为基于权利属性的访问控制奠定了基础,这是 Cadence 以细粒度和高度可读的方式来管理资源访问的方式。
■ 权利属性: 易于理解的资源访问权限控制
权利属性类似于权限:它们控制用户只可以对资源执行给定的操作。如果你想调用一个资源的方法,你需要有一个有效的权利属性。
权利属性是通往资源的门户。与 REST API 一样,权利属性也有路径。如果该路径存在于帐户的公共域中,则任何人都可以获得该权利属性;私有域中的权利属性只能由该帐户的所有者访问。
无论是在公共域还是私有域,权利属性总是链接到一个目标资源。该目标可以是整个资源,也可以只是这个资源所提供所有方法的一个子集。对于后者,接口可以作为权利属性链接的目标。这就是权利属性如何提供给用户易读且细粒度的资源访问控制。
要与资源进行交互,您首先必须在借用其底层资源之前获得特定的权利属性。这可以在任何事务中轻松完成。
account.getCapability<...>(/public/MyCapability).borrow()
与Solidity中严重依赖检查 `msg.sender` 值的基于访问列表的模型相反,权利属性允许灵活的资源访问控制模型,允许以简单,可读和安全的方式授予、修改和撤销对资源甚至部分资源的访问的权限。
总而言之,资源模型、权利属性和 Flow 的帐户模型使 Cadence 成为一种学习速度更快、更易于审计且更高效的语言,让开发人员可以在确保用户资产安全的同时更快地构建应用程序。由于这些优势,越来越多的团队正在使用这种面向资源范式的模式来开发链上应用。
行业觉醒:开启面向资源编程的链上开发时代
“当旧的思维模式或者做事方式被一种完全不同的方式所取代时,一种非常重要且全新的范式转变就出现了”社会学家托马斯·库恩在他的著作《科学革命的结构》一书中简洁地概述了这一点。
对于技术革命来说也是如此:新的挑战引发了新的解决方案,随着软件开发逐渐进入新的领域,如何构建软件的“正确方法”一致在发生变化 — 就像 SQL 是解决原子事务的答案一样,对用户图形界面开发的需求导致了 Java 等面向对象语言的出现。
我们今天面临的挑战是如何在区块链上安全地处理数以亿记的资产。Cadence 提出的解决方案是整个行业在逐渐靠拢的新范式:面向资源编程。
目前位置,很多业内的大玩家都已经开始实现了面向资源范式的编程语言,比如 Diem 团队开发了他们的智能合约语言 Move。因为资源导向范式的优点很容易被理解,所以会有越来越多的开发者和团队会遵循这种开发范式。
Cadence 是第一个使用面向资源范式的智能合约编程语言,在安全性、可读性和可组合性方面树立了新的标准。由于这些优于现有其他智能合约编程语言的优势,Cadence很有可能会成为下一代智能合约的通用语言。
您可以从今天开始使用我们为开发者量身定制的学习资源来学习 Cadence,成为这种智能合约编程新范式的一份子,这些学习资源都是由 Flow 和 Cadence 背后的核心团队所编写的。
-
Cadence介绍:https://docs.onflow.org/cadence/
-
Cadence系列教程:https://docs.onflow.org/cadence/tutorial/01-first-steps/
-
Cadence语言手册:https://docs.onflow.org/cadence/language/
-
Cadence playground:https://play.onflow.org/local?type=account&id=LOCAL-account-0
结论
希望这些信息能对你有所帮助!一如既往的,有任何问题或者建议,都通过下面的这些渠道联系我们!
Flow Discord: https://discord.gg/flow
Flow Forum: https://forum.onflow.org
Flow Github: https://github.com/onflow/flow
下周见!