当前位置: 首页 > Linux

Facebook:开始使用Libra的Move

时间:2023-04-06 04:16:34 Linux

Move是一种新的编程语言,为Libra区块链提供安全和可编程的基础。Libra区块链中的账户是任意数量的Move资源和Move模块的容器。提交给Libra区块链的每笔交易都将其逻辑编码在用Move语言编写的交易脚本中。该交易脚本可以调用模块声明的过程来更新区块链的全局状态。在本指南的第一部分,我们将概述Move语言的主要特性:Move交易脚本支持可编程交易Move模块允许可组合的智能合约Move语言为好奇的读者提供一流的资源,技术论文Move编程语言包含有关该语言的更多详细信息:在本指南的第二部分,我们将向您展示如何在Move中间表示的上下文中编写您自己的应用程序。初始测试网不支持自定义Move程序,但这些功能可供您在本地试用。Move语言的主要特性Move交易脚本支持可编程交易每个Libra交易都包含一个Move交易脚本,该脚本编码验证者应代表客户执行的逻辑(例如,将Libra币从A的账户转移到B的账户);交易脚本通过调用一个或多个Move模块与发布在Libra区块链全局存储中的Move资源进行交互;交易脚本不会保存在全局状态中,所以其他交易脚本无法调用它,这是一个一次性过程;我们在编写交易脚本时提供了几个示例交易脚本;Move模块允许可组合的智能合约。Move模块定义了更新Libra区块链全局状态的规则。Move模块解决了与其他区块链中的智能合约相同的问题。模块声明可以在用户帐户下发布的资源类型。Libra区块链中的每个账户都是任意数量资源和模块的容器。模块声明结构类型(包括资源,这是一种特殊结构)和过程;Move模块的过程定义了创建、访问和销毁其声明类型的规则。模块是可重用的。在一个模块中声明的结构类型可以使用在另一个模块中声明的结构类型,在一个模块中声明的过程可以调用在另一个模块中声明的公共过程。模块可以调用在其他Move模块中声明的过程。事务脚本可以调用已发布模块的任何公共过程。最终,Libra用户将能够在自己的账户下发布模块。Move语言拥有一流的资源。Move的主要功能是定义自定义资源类型。资源类型用于对具有丰富可编程性的安全数字资产进行编码。资源是语言中的普通值,可以存储为数据结构、作为参数传递给过程、从过程返回等;Move类型系统为资源提供特殊的安全保障。移动资源不能被复制、重复使用或丢弃。资源类型只能由定义该类型的模块创建或销毁。这些保证由Move虚拟机通过字节码验证静态强制执行。Move虚拟机将拒绝运行未通过字节码检查器的代码;作为一种资源类型,ibra硬币被命名为LibraCoin.T。LibraCoin.T在语言上无特殊地位,各资源享有同等保护待遇;Move语言底层Move中间代码优化(MoveIntermediateRepresentation)本节介绍如何使用MoveIR编写交易脚本和模块。提醒读者,这个MoveIR还处于早期阶段,因此还不稳定,它也是接下来介绍的Move源语言的前身(详见未来开发者体验部分)。MoveIR是Move字节码之上的一个薄语法层,用于测试字节码验证器和虚拟机,对开发者不是特别友好。MoveIR足以编写人类可读的代码,但不能直接转换为Move字节码。尽管MoveIR仍然有点粗糙,但我们对Move语言感到兴奋,并希望开发人员能够尝试一下。我们在MoveIR上展示了重要的演示代码片段,并鼓励读者通过在本地编译、运行和修改示例来了解它。libra/language/README.md和libra/language/ir_to_bytecode/README.md中的文档解释了如何执行此操作。编写交易脚本正如我们在移动交易脚本启用可编程交易部分中所解释的那样,用户编写交易脚本来请求更新Libra区块链的全局存储。几乎所有交易脚本中都会出现两个重要的构建块:LibraAccount.T和LibraCoin.T资源类型,其中LibraAccount是模块的名称,T是模块声明的资源的名称。这是Move中的通用命名约定。模块声明的“主要”类型通常命名为T。当我们说用户“在地址0xff的Libra区块链上有一个帐户”时,我们的意思是这个地址0xff持有LibraAccount.T资源的一个实例。每个非空地址都有一个LibraAccount.T资源。此资源存储帐户数据,例如序列号、身份验证密钥和余额。Libra系统中任何想要与账户交互的部分都必须从LibraAccount.T资源读取数据或调用LibraAccount模块。账户余额是LibraCoin.T的一种资源。正如我们在Movehasfirst-classresources部分中解释的那样,这是一种Libra硬币。这种类型在语言中是“一等公民”,就像其他Move资源一样。LibraCoin.T类型的资源可以存储在进程变量中,在进程之间传递等。我们鼓励感兴趣的读者检查Libra/language/stdlib/modules/中LibraAccount和LibraCoin模块中这两个关键资源的MoveIR定义目录目录。现在,让我们看看程序员如何在事务脚本中与这些进行交互。模块与资源交互。//简单的点对点支付示例。//使用LibraAccount模块发布在区块链上的账户地址//0x0...0(有64个零)。0x0是IR通过添加前导零填充到//256位(64位)的简写。import0x0.LibraAccount;import0x0.LibraCoin;main(payee:address,amount:u64){//字节码(因此,theIR)键入了本地人。//每个本地的范围是整个过程。所有局部变量声明都必须//在过程的开头。//变量的声明和初始化是独立的操作,但字节码验证器将阻止//任何使用未初始化变量的尝试。让硬币:R#LibraCoin.T;//上述类型的R#部分是两种*kindannotation*R#和V#//(“Resource”和“unrestrictedValue”的简写)之一。这些注解//必须与类型声明的种类相匹配(例如,LibraCoin//模块是否声明`resourceT`或`structT`?)。//从发送者的//账户获取一个值为`amount`的LibraCoin.T资源。如果发件人的余额小于“金额”,这将失败。coin=LibraAccount.withdraw_from_sender(移动(金额));//将LibraCoin.T资源移动到`payee`的账户中。如果在地址`payee`上没有//账户,此步骤将失败LibraAccount.deposit(move(payee),move(coin));//每个过程都必须以`return`结束。IR编译器非常直白://它直接翻译给定的源代码。它不会做花哨的事情//比如插入缺失的`return`s。return;}这个交易脚本有问题:如果地址的接收者没有账户,会执行失败。我们将通过修改脚本为收件人创建一个帐户来解决这个问题(如果收件人还没有帐户)。//点对点支付示例的一个小变体,如果账户不存在,则创建一个新的//账户。import0x0.LibraAccount;import0x0.LibraCoin;main(payee:address,amount:u64){letcoin:R#LibraCoin.T;让account_exists:bool;//从发送者的//账户获取一个值为`amount`的LibraCoin.T资源。如果发件人的余额小于“金额”,这将失败。coin=LibraAccount.withdraw_from_sender(move(amount));account_exists=LibraAccount.exists(副本(收款人));if(!move(account_exists)){//通过在此地址下发布//LibraAccount.T资源,在地址`payee`上创建一个新帐户。如果该地址下已经有//LibraAccount.T资源,这将失败。create_account(copy(payee));}LibraAccount.deposit(移动(收款人),移动(硬币));return;}let让我们看一个更复杂的例子。在此示例中,我们将使用交易脚本为多个收件人(而不是单个收件人)付款。//多个收款人示例。这是以稍微冗长的方式编写的,以//强调拆分`LibraCoin.T`资源的能力。更简洁的//方法是多次调用`LibraAccount.withdraw_from_sender`.import0x0.LibraAccount;import0x0.LibraCoin;main(payee1:address,amount1:u64,payee2:address,amount2:u64){letcoin1:R#LibraCoin.T;让coin2:R#LibraCoin.T;让总计:u64;总计=移动(数量1)+副本(数量2);coin1=LibraAccount.withdraw_from_sender(move(total));//这会改变`coin1`,它现在的值为`amount1`。//`coin2`的值为`amount2``.coin2=LibraCoin.withdraw(&mutcoin1,move(amount2));//执行支付LibraAccount.deposit(move(payee1),move(coin1));LibraAccount.deposit(移动(payee2),移动(coin2));return;}好了,交易脚本的介绍到此结束。更多示例,包括初始测试网支持的交易脚本,请参考libra/language/stdlib/transaction_scripts。编写模块现在,让我们专注于编写我们自己的Move模块,而不是仅仅重用现有的LibraAccount和LibraCoin模块。考虑这样一种情况,Bob将在未来某个时间在地址a创建一个账户,Alice想“指定”Bob一笔资金,以便他可以在账户创建后将其存入她的账户。但她也希望,如果Bob一直不创建帐户,她将能够取回资金。为了解决Alice的问题,我们将编写一个专用的EarmarkedLibraCoin模块,它将:声明一个新的资源类型EarmarkedLibraCoin.T,它封装了一个Libra币和接收者的地址;允许Alice创建此类资源,并在其帐户下发布(创建过程);允许Bob声明资源(claim_for_recipient过程);允许任何拥有EarmarkedLibraCoin.T资源类型的人销毁它并获得底层Libra货币(解包过程);允许任何拥有EarmarkedLibraCoin.T的人销毁它并获取底层硬币(解包程序)。//用于为特定接收者指定硬币的模块模块EarmarkedLibraCoin{import0x0.LibraCoin;//一个包含Libra硬币和收件人地址的包装器//硬币被指定用于。resourceT{coin:R#LibraCoin.T,recipient:address}//使用给定的`recipient`创建一个新的专用硬币。//在交易发送者的账户地址下发布硬币。publiccreate(coin:R#LibraCoin.T,recipient:address){lett:R#Self.T;//构造或“打包”类型为T的新资源。只有//`EarmarkedCoin`模块的程序才能创建`EarmarkedCoin。T`.t=T{coin:move(coin),recipient:move(recipient),};//在交易发送者的账户//地址下发布指定硬币。每个帐户最多可以包含一个给定类型的资源;//如果发送者已经有这种类型的资源,这个调用将失败。move_to_sender(移动(t));返回;}//允许交易发送者领取指定给她的代币。publicclaim_for_recipient(earmarked_coin_address:address):R#Self.T{lett:R#Self.T;让t_ref:&R#Self.T;让发件人:地址;//删除在`earmarked_coin_address`下发布的专用币资源。//如果该地址下发布了类型为T的资源,则失败。t=move_from(移动(earmarked_coin_address));t_ref=&t;//这是一个返回交易发送者地址的内置函数。发件人=get_txn_sender();//确保交易发送者i是收件人。如果此断言//失败,则交易将失败,并且不会提交其任何影响(例如,//删除指定硬币)。99是一个错误代码//如果断言失败,它将在事务输出中发出。assert(*(&move(t_ref).recipient)==move(sender),99);返回移动(t);}//允许指定代币的创建者收回它。publicclaim_for_creator():R#Self.T{lett:R#Self.T;让硬币:R#LibraCoin.T;让收件人:地址;让发件人:地址;发件人=get_txn_sender();//如果发件人地址下没有类型T的资源,这将失败。t=move_from(移动(发件人));返回移动(t);}//从包装器中提取Libra硬币并将其返回给调用者。publicunwrap(t:R#Self.T):R#LibraCoin.T{letcoin:R#LibraCoin.T;让收件人:地址;//这通过破坏外部资源来“解包??”资源类型,但是//返回其内容。只有声明资源类型的模块//才能将其解包。T{coin,recipient}=move(t);返回移动(硬币);}}Alice可以为Bob创建一个预定币,方法是创建一个交易脚本,调用createBob的地址a,以及她拥有的LibraCoin。一旦创建了地址a,Bob就可以通过从a发送交易来领取硬币,这将调用claim_for_recipient,这会将结果传递给unwrap,返回的LibraCoin存储在他希望的任何地方。如果Bob创建a的时间太长,而Alice想要取回她的资金,Alice可以使用claim_for_creator,然后解包。细心的读者可能已经注意到,该模块中的代码与LibraCoin.T的内部结构无关。它可以使用泛型编程轻松编写(例如,资源T{coin:AnyResource,...})。我们目前正致力于将这种参数多态性添加到Move中。未来的开发者体验在不久的将来,MoveIR将变得稳定,编译和验证程序将变得更加用户友好。此外,IR源的位置信息将被跟踪,然后传递给验证器,以便更容易排除错误消息。但是,IR将继续作为测试Move字节码的工具。它是底层字节码的语义透明表示。为了允许有效测试,IR编译器需要生成错误代码,这些代码将被字节码验证器拒绝,或者在编译器运行时失败。虽然用户友好的源语言是另一种选择,但它应该拒绝编译在管道的后续步骤中会失败的代码。以后我们会有更高层次的Move源语言。该源语言将被设计为安全、轻松地表达常见的Move习语和编程模式。由于Move字节码是一种新语言,而Libra区块链是一种新的编程环境,我们对支持的习语和模式的理解仍在不断发展。目前,源语言处于开发的早期阶段,我们还没有准备好发布时间表。