技术分享| Stable Cadence 的进展更新
2022-10-21 01:00
福洛链 Flow Official
2022-10-21 01:00
订阅此专栏
收藏此文章

原文标题:Another Update on Stable Cadence

原文链接:https://forum.onflow.org/t/another-update-on-stable-cadence/3715


在 2022 年 1 月,Cadence 团队分享了关于 Stable Cadence 之路的想法。自那之后我们已经取得了长足的进步:我们发布了 Secure Cadence 里程碑,实现了无许可合约部署,同时我们也在继续推进 Stable Cadence 的里程碑和其他语言功能和改进。


在这篇文章中,我们想向大家介绍目前在 Stable Cadence 里程碑上 Flow 开发社区所取得的进展,以及明年年中左右将发布哪些内容,可以准备些什么。

我们还要感谢所有积极参与并做出贡献的社区成员,没有你们会更加困难。



已完成 / 已合并

■ View 函数 / 函数条件中的调用

  • https://github.com/onflow/flow/pull/1056

  • https://github.com/onflow/cadence/pull/1871

Cadence 增加了一个新的函数修饰关键字的支持:view,该关键词将强制函数体内不会发生 mutate 操作。 view 关键字在声明中需要放在 fun 关键字之前。

如果一个函数没有 view 注释,它将被认为“非视图”,这将与之前没有任何区别。 而如果函数有了 view 关键字声明,则不允许包含以下操作:

  • 写入、修改或销毁任何资源

  • 写入或修改任何引用

  • 分配或修改除 view 函数内创建之外的任何变量。 即要注意,这意味着不能在这些函数中写入传入的或全局的变量

  • 发出事件

  • 调用任何非视图函数

此外,函数的前置和后置条件现在也被视为 view 上下文; 这意味着在 view 函数内部禁止的任何操作在前置或后置条件中也是不允许的。 这是为了避免在条件内修改全局或合约状态的不正当代码,它们应该只是简单地对状态属性进行断言。 特别的是由于在条件中只允许使用表达式,这意味着如果希望在条件中调用任何函数,那就必须将这些函数设为 view 函数。


■ 未报告的缺失或错误参数标签

  • https://github.com/onflow/cadence/pull/1717

  • https://github.com/onflow/cadence/pull/2013

缺失或错误参数标签的函数调用以前不会报告为 error。这种不正确的函数调用现在将会一个 error,应该通过提供预期的参数标签来修复。

举例说明:

// Contract "TestContract" deployed at address 0x1
pub contract TestContract { pub struct TestStruct { pub let a: Int pub let b: String init(first: Int, second: String) { self.a = first self.b = second } }}

错误的程序:

TestContract.TestStruct 的初始化代码需要参数标签 firstsecond

但是,初始化的调用为第一个参数提供了错误的参数标签,并且缺少第二个参数标签。

// Scriptimport TestContract from 0x1
pub fun main() {    TestContract.TestStruct(wrong: 123, "abc")}

现在这会导致以下错误:

error: incorrect argument label  --> script:4:34   | 4 |           TestContract.TestStruct(wrong: 123, "abc")   |                                   ^^^^^ expected `first`, got `wrong`
error: missing argument label: `second`  --> script:4:46   | 4 |           TestContract.TestStruct(wrong: 123, "abc")   |

正确的程序:

// Scriptimport TestContract from 0x1
pub fun main() {    TestContract.TestStruct(first: 123, second: "abc")}

我们要感谢社区成员 justjoolz 报告此错误。


■ 未报告引用表达式中的错误运算符

  • https://github.com/onflow/cadence/pull/1661

  • https://github.com/onflow/cadence/pull/2010

引用表达式的语法是 &v as &T,表示将对值 v 的引用设为类型 T

使用其他错误的运算符引用表达式(例如 as?as!)在以前没有被报告为 error

这种错误的引用表达式现在将是一个 error,应该使用 as 运算符来修复。


错误的程序:

引用表达式使用错误的运算符 as!

let number = 1let ref = &number as! &Int

现在结果将是以下的报错:

error: cannot infer type from reference expression: requires an explicit type annotation --> test:3:17  |3 |       let ref = &number as! &Int  |

正确的程序:

let number = 1let ref = &numberas &Int

或者,同样的代码现在也可以写成如下:

let number = 1let ref: &Int = &number


在大多数情况下,标识符不能是关键字

  •  https://github.com/onflow/cadence/pull/1937

以前,我们允许在标识符位置使用关键字(例如 continuefor 等)。

例如,解析器允许以下程序:

pub fun continue(import: Int, break: String) {...}


这导致了很多歧义,因此大多数关键字将不被允许用作名称。


在仔细审查了语言语法之后,我们目前将以下关键字指定为软限制,这意味着由于在语言中的意义有限,它们仍然可以用作标识符。 这些允许的关键字如下:

  • from: 只用在 import 语句中 import foo from ...

  • account: 用于访问修饰符 access(account) let ...

  • set:用于访问修饰符 pub(set) var globalMutVar = ...

  • all:用于访问修饰符 access(all) let ...

任何其他关键字都会在解析过程中引发错误,例如:

let break: Int = 0// error: expected identifier after start of variable declaration, got keyword break

将合约迁移到 Stable Cadence 需要重命名与保留关键字冲突的任何标识符。

例如: let contract let nftContract 等。


■ 修改了 U?Int(128|256) 的 toBigEndianBytes() 结果

  • https://github.com/onflow/cadence/pull/1917

先前 .toBigEndianBytes() 的实现是错误的,受影响的大整数类型有:

  • Int128

  • Int256

  • UInt128

  • UInt256

在较小的整数类型上调用 .toBigEndianBytes() 通常会返回适合父类型的确切字节数(左填充零)。 例如, (x: Int64).toBigEndianBytes() 返回一个 8 字节的数组。 这些较大的类型错误地返回了没有填充的可变长度字节数组,这足以存储他们的最高字节位。但这与较小的固定大小数值类型(例如 Int8 和 Int32)不一致。 为了解决这种不一致,Int128 和 UInt128 现在将返回 16 字节的数组,而 Int256 和 UInt256 返回 32 字节的数组。

let someNum: UInt128 = 123456789let someBytes: [UInt8] = someNum.toBigEndianBytes()// old behaviour:// someBytes = [7, 91, 205, 21]// new behaviour:// someBytes = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 91, 205, 21]

如果您的合约代码需要和之前一样不做零的填充,则可以使用任意精度的 Int 和 UInt 类型来表示可变字节数组。


可以通过先转换为可变长度类型来恢复原来的效果,例如:

let someNum: UInt128 = 123456789let someBytes: [UInt8] = UInt(someNum).toBigEndianBytes()// someBytes = [7, 91, 205, 21]


■ 删除已弃用的密钥管理 API

  • https://github.com/onflow/cadence/pull/2044

去年已弃用的第一个帐户密钥管理 API 已被删除。 现在需要使用新的密钥管理 API:

更多信息可以参考 开发文档(https://developers.flow.com/cadence/language/accounts#account-keys)


■ 对资源可选绑定的修复

  • https://github.com/onflow/cadence/pull/2044

对资源的可选绑定(if-let 语句)现在被正确实现并修复了。 这可能会影响不正确使用的现有代码。

例如,下面的程序曾经是无效的,会报告 optR 的资源丢失错误:

resource R {}          fun asOpt(_ r: @R): @R? {              return <-r          }          fun test() {    let r <- create R()    let optR <- asOpt(<-r)    if let r2 <- optR {        destroy r2    }}

这段代码现在将不在报错,会被视为有效的。

但是,以前为解决这个问题的所使用的部分代码,例如通过在 else 分支或 if 语句销毁资源的方式,现在将是错误的:

// invalidfun test() {    let r <- create R()    let optR <- asOpt(<-r)    if let r2 <- optR {        destroy r2    } else {        destroy optR    }}



即将到来的改动

以下更改可能包含在 Stable Cadence 中,但细节与决策尚未敲定。


■ Capability API 可能会被替换为一个改进的版本

  • https://github.com/onflow/flow/pull/798

有一个 FLIP 建议用更强大且更易用的 API 替换现有的 Capability API。私有存储域 (private) 将被移除,创建新 Capability 将更简单,撤销 Capability 也将更直接。 这不会改变 Capability 的消费 / 使用方式,只会改变它们的创建方式。 任何调用 AuthAccount::(un)link 的代码都需要更改。


■ 当资源被转移后,对资源类型的值引用可能会失效

  • https://github.com/onflow/flow/pull/1043

  • https://github.com/onflow/cadence/pull/2037

  • https://github.com/onflow/cadence/pull/1999

在以前即使资源被转移,对该资源的引用仍然是有效的。 换句话说引用永远存在,这可能是一个潜在的风险,可以通过引用获得 / 给予 / 持有对资源的意外访问。


通过此更改,如果在获取引用后若资源发生移动,则引用将无效。 它在第一次转移时就会失效,无论是来源还是目标。

例如:

// Create a resource.let r <-create R()
// And take a reference.let ref = &r as &R
// Then transfer the resource into an account.account.save(<-r, to: /storage/r)
// Update the reference.ref.id = 2

以前的效果:

// 这里将正常更新存储在账户的资源ref.id = 2

现在的效果:

// 尝试更新或访问引用时,将报出以下的错//     "invalid reference: referenced resource may have been moved or destroyed"ref.id = 2

但是,并非所有场景都可以静态检测。 例如:

pub fun test(ref: &R) {    ref.id = 2}

在上述函数中,无法确定引用的资源是否已被移动。

因此,这种情况会在运行时进行检查,如果资源已被移动,则会发生运行时错误。


■ 必要内嵌类型可能仅限于事件

必要内嵌类型 目前支持所有类型的复合类型。

但未来的提案中可能会被限制在仅支持事件。

必要内嵌类型是一个相当高级的概念。就像接口需要实现中提供某个字段或函数一样,它也需要提供符合的内嵌类型。

这在其他编程语言中并不常见并且难以理解。 此外,必要内嵌类型的价值从未实现过。


■ 可能会引入防止重入攻击的语言支持

未来的提案可能会引入额外的语言特性,并可能改变现有的语言语义,以允许开发者自动或至少较容易地进行防重入攻击。


■ 可能会增加对外部修改的限制

当前可以对内部类型外可变值进行字段修改。未来的提案可能会限制这一点。


■ for 循环语句中变量的语义可能会改变

  • https://github.com/onflow/flips/pull/13

一份 FLIP 建议更改 for 循环语句中变量的效果。这将从语言中删除意外效果并减少错误的可能。

这种变化只会影响少数程序,因为只有当程序在函数闭包中获取 for 循环语句变量时,该效果才会明显。

// Capture the values of the array [1, 2, 3]let fs: [((): Int)] = []for x in [1, 2, 3] {    // Create a list of functions that return the array value    fs.append(fun (): Int {        return x    })}
// Evaluate each function and gather all array values let values: [Int] = [] for f in fs {    values.append(f())}

以前,这个值的结果将是 [3, 3, 3],这可能会令人意外。 这是因为 x 将在每次迭代中被重新分配为当前的数组元素,导致 fs 中的每个函数都返回数组的最后一个元素。

如果提议的更改获得批准并实施,则结果将为[1, 2, 3],这会是程序作者所期望的。



相关内容

■ FT / NFT 的标准变化(尚在修改)

Fungible Token 和 Non-Fungible Token 的标准接口正在升级,以允许每个合约使用多个代币,修复原标准的一些问题,并引入社区建议的其他各种改进。

  • 最初提案 :https://forum.onflow.org/t/streamlined-token-standards-proposal/3075

  • FT 修改 PR: https://github.com/onflow/flow-ft/pull/77

  • NFT 修改 PR: https://github.com/onflow/flow-nft/pull/126

这些修改和 FLIP 仍在进行中,因此开发者关注的预期变化尚未最终确定,但它将涉及通过事件、函数签名、资源接口一致性和其他小的更改来升级你的代币合约。会有更多示例代码即将推出。

 END 

什么是 Flow 福洛链?


Flow 福洛链是一个快速,去中心化,且对开发者友好的区块链,旨在为新一代游戏、娱乐应用程序提供动力的数字资产的基础。Flow 是唯一一个由始至终为消费者提供出色体验的 Layer-1 区块链团队。其团队创造的 dApp 包括:CryptoKittiesDapper WalletsNBA Top shot


CrytoKitties 于 2017 年推出时便快速成为加密市场最受欢迎的 dApp,因其成功而导致以太坊堵塞。在 Flow 上运营的 NBA Top shot 也已成为增长最快的 dApp,在公开发布后的 6 个月创造了 7 亿美金销量。正因为 Flow 公链的可扩展性和消费者友好的体验,让这一切成为可能。目前有 1000 多个项目正在 Flow 链上筹备中,我们期待看到一个伟大的生态系统蓬勃发展。


关于 Dapper Labs

Dapper Labs 是一家位于加拿大的全球顶尖区块链服务商,在 2017 年年底通过 CryptoKitties 收藏游戏成功进入⽤户视野,并且因为加密猫的爆⽕导致以太坊拥堵,从而推出 Flow 公链以及全新的开发语言—— Cadence,旨在吸引更多的开发者在 Flow 上开发应⽤。 


Flow 的合作伙伴们:

我们欢迎越来越多的小伙伴加入 Flow 星球,为星球增添色彩!


Flow 官网:https://zh.onflow.org/

Flow 论坛: https://forum.onflow.org/

Flow Discord:

https://discord.com/invite/flow

Flow CN Telegram: https://t.me/flow_zh

Flow B 站:https://space.bilibili.com/1002168058

Flow 微博: 

https://weibo.com/7610419699

Flow CSDN:

https://blog.csdn.net/weixin_57551966?spm=1010.2135.3001.5343


扫码添加 Flow 官方账号微信号,加入 Flow 生态群

微信号 : FlowChainOfficial

相关Wiki

【免责声明】市场有风险,投资需谨慎。本文不构成投资建议,用户应考虑本文中的任何意见、观点或结论是否符合其特定状况。据此投资,责任自负。

在 App 打开