亚博真人官网-CKB 脚本编程简介第二弹:脚本基础

亚博真人

亚博真人官网:薛洁是CKB虚拟机的核心开发者。在他的博客《少即是多》中,他创作了一系列解释CKB脚本编程的文章,这些文章可以作为一个详细的构造来弥补白皮书中写CKB脚本所需的所有缺陷。

本文是本系列的第二篇文章,详细介绍了如何将脚本代码部署到CKB网络。慢慢看。在最后一篇文章中,我解释了CKB目前的检查模式。这篇文章不会更有趣。

我们将向您展示如何将脚本代码部署到CKB网络。希望你看完这篇文章后,有能力去探索CKB的世界,按照自己的意愿去写新的剧本代码。但是请注意,虽然我坚信CKB目前的编程模式已经比较稳定,但是研发还在进行中,所以未来可能会有一些变化。我会尽量保证这篇文章是最近的状态,但是如果在过程中有什么混乱,这篇文章是基于这个版本的CKB:https://github.com/nevos network/ckb/commit/80b 51 a 9851 b5 d 535625 C5 d 144 E1 accd 38 c 32876 btips:这是一篇很长的文章,因为我想下周更有趣。

所以如果没有足够的时间,也不用马上看。我会试着把它分成几个独立的国家,这样你就可以一次读完其中的一些。语法在我们开始之前,让我们区分两个术语:脚本和脚本代码。

在本文和整个系列文章中,我们将区分脚本和脚本代码。脚本代码本质上是指你在CKB上编写、编译和操作的程序。Script,本质上是指CKB使用的脚本数据结构,不比script code多一点:pub struct script { pub args : vecbytes,pub code _ hash :h256,pub hash_type : script hash type,}我们目前可以再次忽略hash_type,然后我们会在后面的文章中说明hash _ type是什么,它有什么。

在本文的后面,我们将不解释code_hash本质上是用来标识脚本代码的,所以目前只能把它当作脚本代码来对待。剧本还包括什么?脚本还包含参数,用于区分脚本和脚本代码。这里可以使用Args为一个CKB脚本获取额外的参数,例如,虽然每个人都可能使用同一个配置文件的Lock Script Code,但是每个人都可能有自己的Pubkey Hash,args用来保存Pubkey Hash的位置。

这样,每个CKB用户可以享受不同的锁定脚本,但可以在一定程度上共享锁定脚本代码。请注意,在大多数情况下,脚本和脚本代码可以互换使用,但如果你在某些地方深感困惑,你可能需要适当考虑它们之间的差异。比这更大的CKB脚本代码以前可能听过。

CKB虚拟机是基于开源RISC-V指令集编写的。但是这到底意味着什么呢?用我自己的话来说,这意味着我们在CKB映射了一台真正的微型计算机,而不是虚拟机。真正的计算机的优点是,你可以用任何语言写出任何你想要的逻辑。

这里,网卓新闻。为了保持简单性,我们不会展示一些用c语言编写的例子(我指的是工具链中的简单性,而不是语言)。之后,我们不会切换到基于JavaScript的脚本代码,并期望在本系列中展示更好的语言。忘记CKB有无限的可能性!正如我们提到的,CKB虚拟机看起来更像一个真正的微型计算机。

CKB的代码脚本看起来更像是我们在电脑上运行的一个罕见的Unix风格的可执行程序。int main(int argc,char * argv[]){ return 0;}当你的代码通过C编译器的时候,就会简化为可以在CKB上运行的脚本代码。
换句话说,CKB只使用常见的老式Unix风格的可执行程序(但使用RISC-V架构,而不是流行的x86架构),并在虚拟机环境中运行。

如果程序的返回代码为0,我们表示脚本成功,所有非零的返回代码都将被视为结束脚本。在上面的例子中,我们展示了一个总是平滑的脚本代码。因为返回码总是0。但请不要将此作为您的锁定脚本代码,否则您的令牌可能会被任何人窃取。

但是上面这个例子好像没什么意思。这里先说一个有趣的想法:我个人不是很讨厌胡萝卜。我从营养的角度告诉胡萝卜是好的,但我仍然不讨厌它的味道。

如果我现在在原著中想要一个规则,比如我想让我在CKB的Cell没有以胡萝卜结尾的数据,怎么构造?让我们写一个脚本代码来试试。为了确保单元格数据中没有包含胡萝卜,我们必须首先在脚本中加载单元格数据。

CKB收购了syscalls来帮助解决这个问题。为了确保CKB脚本的安全性,每个脚本必须在一个几乎与运行CKB的主机分开的隔离环境中运行。所以不能采访不必要的数据,比如你的私钥或者密码。

但是,为了使脚本简单,需要采访具体的数据,比如脚本维护的单元格或者脚本验证。CKB获得系统调用来确保这一点。

系统调用在RISC-V标准中定义,它们获得访问环境中一些资源的方法。长期以来,这里的环境指的是操作系统,但在CKB虚拟机中,环境指的是实际的CKB进程。用于系统调用,CKB脚本可以采访整个数据包括它自己,包括输入,输出,证人和德普斯。

亚博真人官网

更重要的是,我们已经把syscalls PCB放在一个更容易使用的头文件中。非常欢迎您在这里查看此文件。了解如何构建syscalls:https://github.com/nevos network/ckb-system-scripts/blob/66 D7 da 8 EC 72 dfaa 7e 9 c 55904833951 ECA 2422 a 9/c/CKB _ syscalls . h最重要的是你只能提供这个头文件,并在carton函数中使用它来创建你想要的系统调用。现在我们有了syscalls,可以从禁止使用胡萝卜的脚本开始:# include memory . h # include ‘ ckb _ syscalls . h ‘ int main(int argc,char * argv[]){ int ret;size_t索引=0;volatile uint 64 _ t len=0;/* (1) */无符号字符缓冲区[6];while(1){ len=6;memset(缓冲区,0,6);ret=ckb _ load _ CELL _ by _ FIELD(buffer,len,0,index,CKB_SOURCE_OUTPUT,CKB _ CELL _ FIELD _ DATA);/*(2)*/if(ret==CKB _ INDEX _ OUT _ BOUND){/*(3)*/break;}if (memcmp(buffer,’胡萝卜’,6)==0){ return-1;}索引;}返回0;}以下几点必须说明:1。

由于c语言的怪癖,len字段必须标记为volatile。我们不会同时将其用作输出和输入参数。

当它还在内存中时,CKB虚拟机无法将其设置为输入参数。Volatile可以保证C编译器将其作为基于RISC-V内存的变量保存。2.在syscall中使用时,我们必须获得以下功能:一个缓冲区,用于保存syscall获得的数据;len字段,用于响应系统调用返回的缓冲区长度和可用数据长度;输出数据缓冲区中的一个偏移量,以及我们必须在事务中提供的清除字段的几个参数。

请参阅我们的RFC:https://github.com/nevrosnetwork/rfcs/blob/master/rfcs/0009-VM-syscalls/0009-VM-syscalls . md3 .为了确保仅次于的灵活性,系统调用的返回值使用CKB来响应数据捕获状态:0(或CKB_SUCCESS)表示成功,1(或CKB_INDEX_OUT_OF_BOUND)表示您已经以一种方式提供了所有索引,2(或CKB_ITEM_MISSING)表示
综上所述,这个脚本将循环遍历事务中所有的输入Cells,读取每个Cell Data的前6个字节,并测试这些字节是否是胡萝卜给出的。如果您寻找一个给定的,脚本将返回到-1并响应错误状态;如果找不到给定的,脚本将返回0进行溶解,响应将继续顺利执行。为了继续执行循环,脚本将保留一个索引变量。

在每个循环递归中,它将尝试让系统调用提供当前在单元中使用的索引值。如果系统调用返回到CKB _索引_输出_绑定,这意味着脚本已经迭代了所有的单元,并且在此之后不会分解循环。否则,在循环后,每次测试单元数据时,索引变量都不会递减一次。

这是第一个简单的CKB脚本代码!在下一节中,我们将展示如何在CKB部署和操作它。将脚本部署到CKB首先,我们必须编译上面写的关于胡萝卜的源代码。既然GCC已经赢得了RISC-V的反对,那么你可以在官方的GCC中使用它来创建脚本代码。

或者你可以把它用于我们预定的Docker映像(https://hub.docker.com/r/nervos/ckb-riscv-gnu-toolchain)为了防止编译器GCC的困难:$ls胡萝卜. cckb _ consts . hckb _ syscalls . h $ sudo dockerrun-RM-it-v ` pwd ` :/codenervos/ckb-riscv-GNU-tool chain 3360 xenial bash[email protected]:/# CD/code[email protected]:/code # Ricv64-unknown-elf-GCC-oscarro请注意,我将为CKB使用Ruby SDK,因为我已经做了很多次Ruby程序员,所以Ruby是我最习惯的(但不一定是最差的)。如何设置请求参考官方自述文件:https://github.com/nevos network/CKB-SDK-ruby/blob/developer/Readme . MD要将脚本部署到CKB,我们只需要新建一个Cell即可。

将脚本代码设置为Cell Data部分:pry (main) data=file.read(‘胡萝卜’)pry(main)Data . bytesize=6864 pry(main)胡萝卜_ tx _ hash=wallet . send _ capacity(wallet . address,Ckb: utils。byte _ to _ Shannon (8000),ckb:3360 utils。

bin _ to _ hex (data))在亚博真人这里,我首先想通过发送给自己来创建一个具有足够容量的新Cell。现在我们可以创建一个脚本,包括胡萝卜脚本代码:PRY(主)胡萝卜_数据_哈希=CKB:3360Blake布莱克2B。Hexdigest (data) PRY (main)胡萝卜_ type _ script=ckb : types 33603360 script . new(code _ has H3 3360胡萝卜_data_hash,Args 3360[])回想一下脚本数据结构:pubstruct script { pubstruct 3360 vekbytes,pubcode _ hash:h256,pubhash _ type3360scripthashtype,}您可以看到我不需要将脚本代码映射到脚本数据结构中,由于胡萝卜脚本不用于参数,我们可以将args部分用于空数组。请注意,这里仍然忽略hash_type,我们将在后面的文章中以另一种方式讨论登录代码hash。

现在,让我们尽可能简明扼要。要操作胡萝卜脚本,我们必须创建一个新的事务,并将胡萝卜类型脚本设置为输入Cell类型脚本之一:PRY(main)tx=wallet . generate _ tx(wallet 2 . address,CKB 33603360 UTILS . byte _ to _ Shannon(200))PRY(main)tx . outputs[0]。我们还必须扩展一个步骤:为了让CKB找到胡萝卜脚本,我们必须提到cell: pry (main)在事务的Deps中包含胡萝卜脚本胡萝卜_ out _ point=ckb 3360: types 33603360 output int . new(cell 3: ckb 3360: types 3360: celloutput . new(tx _ has H3)data . clear[46]PRY(main)tx=tx . sign(wallet . key,API.compute _ transaction _ hash(tx))[19]PRY(main)API . send _ transaction(tx)=’0xd 7 b 0 FEA 7 c 1527 CDE 27 cc 4 e7a 2e 055 e 494690 a 384 db 14 cc 35 CD 2e 51 EC 6 f 078163 ‘因为此事务的单元格中没有包含胡萝卜的单元格数据,类型脚本将成功验证。现在让我们尝试一个不同的事务,它显然包含一个以胡萝卜结尾的单元格:PRY (main) TX2=wallet。

generate _ TX(钱包2。地址,CKB :3360 utils . byte _ to _ Shannon(200))pry(main)tx2 . deps . push(胡萝卜_ out _ point . dup)pry(main)tx2 . outputs[0]。

亚博真人

instance _ variable _ set(: @ type,胡萝卜_ type _ script . dup)pry(main)tx2 . outputs[0]。instance _ variable _ set(: @ data,ckb :3360 utils . bin _ to _ hex(‘ carrot 123 ‘))pry(main)tx2 . witness[0]. data . clear pry(main)tx2=tx2 . sign(wallet . key,API.compute _ transaction _ hash(tx2))pry(main)API . send _ transaction(tx2)ckb : rpcerror 3360 jsonrpc error : { :因此,综上所述,要部署和操作一个Type script的脚本,必须做到以下几点:1。

将脚本编译成RISC-V可以继续执行的二进制文件;2.在单元格的数据部分部署二进制文件;3.创建一个Type脚本数据结构,用于二进制文件的Blake2b哈希作为代码哈希,以补充args部分脚本代码的必要参数;4.使用分解单元中设置的类型脚本创建新事务;5.将包含脚本代码的单元格输出加载到事务的Deps中。虽然我们在这里只讨论类型脚本,但是锁定脚本的工作方式完全相同。你唯一要忘记的是,当你用一个特定的Lock脚本创建Cell的时候,Lock脚本会在这里操作,只有你用它做Cell的时候才会操作。

因此,当结构创建单元时,类型脚本可以用作逻辑,而当结构密封单元时,锁定脚本可以用作逻辑。记住这一点,请确保您的锁定脚本是准确的,否则您可能会在以下场景中丢失令牌:您的锁定脚本有一个别人可以检查您的单元的错误。

你的锁定脚本有一个错误,没有人(包括你)可以检查你的手机。在这里,我可以得到一个技能。

您始终可以在事务的输出单元中选择脚本作为类型脚本进行测试。这样,当错误再次发生时,您可以立即告诉它,您的令牌总是安全的。分析配置文件的锁定脚本代码。

根据已经掌握的科学知识,让我们想到CKB包含的配置文件的Lock脚本代码。为了防止误解,我们可以在这个Commit: https://github中查找Lock脚本代码。

com/nevos network/ckb-system-scripts/blob/66e 2 B3 fc 4 fa 3 e 80235 E4 B4 f 94 a 16 e 81352 a 812 f 7/c/secp 256 k1 _ Blake 160 _ SIG hash _ all . c配置文件的Lock脚本代码将循环迭代所有与自身具有相同Lock脚本的Input Cell。并继续执行以下步骤:它通过获取的Syscall提供当前事务Hash,并提供适当的Witness数据作为当前输出。

对于配置文件Lock脚本,假设Witness中的第一个参数包括Cell所有者签名的可恢复签名,其余参数是用户获取的附加参数配置文件的Lock脚本操作的事务Hash链接的二进制程序的Blake 2bHash,用户获取的所有参数(如果不存在)都使用Blake2b Hash结果进行Secp256k1签名检查的消息部分。请注意,见证数据结构中的第一个参数获得了实际签名。

如果签名检查结束,脚本被解散并返回到错误代码。否则它将被下一个递归跟随。请注意,我们之前讨论过脚本和脚本代码的区别。

每个不同的公钥散列将产生不同的锁脚本。因此,如果事务的输出单元具有完全相同的配置文件锁定脚本代码,但是具有不同的公钥散列(因此不同的锁定脚本),则配置文件锁定脚本代码的多个实例将继续执行,并且每个实例具有一组共享完全相同的锁定脚本的单元。现在,我们可以迭代配置文件的不同部分,锁定脚本代码:if (argc!=2){ return ERROR _ ERROR _ NUMBER _ OF _ ARGUMENTS;} secp256k1 _ context contextif(secp 256 k1 _ CONTEXT _ INITIALIZE(CONTEXT,secp 256 k1 _ CONTEXT _ VERIFY)=0){ return ERROR _ SECP _ INITIALIZE;} len=BLAKE2B _ BLOCK _ SIZEret=ckb_load_tx_hash(tx_hash,len,0);if (ret!=CKB _成功){ return ERROR _ SYSCALL当参数包含在Script数据结构的args部分时,它们通过传统的Unix arc/argv模式被发送到实际的操作脚本程序。为了进一步维护承诺,我们在argv[0]处放置了一个伪参数,因此第一个包含的参数从argv[1]开始。

在配置文件Lock脚本代码的情况下,它拒绝接受一个参数,即从所有者的私钥分解而来的公钥Hash。ret=ckb _ load _ INPUT _ by _ FIELD(NULL,len,0,index,CKB_SOURCE_GROUP_INPUT,CKB _ INPUT _ FIELD _自);if(ret==CKB _ INDEX _ OUT _ BOUND){ ret 0;}if (ret!=CKB _成功){ return ERROR _ SYSCALL}我们再来看看胡萝卜,看看是否还有输出Cell要测试。与前面的例子有两个区别:如果我们只想告诉一个Cell是否不存在,不需要任何数据,我们只需要使用NULL作为数据缓冲区,一个len变量的值为0。

这样,Syscall跳过数据填充,只获取可用的数据长度和准确的返回码进行处置。在这个胡萝卜示例中,我们循环迭代事务中的所有输出,但是这里我们只关心具有相同锁脚本的输出单元。CKB用与组完全相同的目标(或类型)脚本来命名单元。我们可以使用CKB _源_组_输入来代替CKB _源_输入,以响应仅计算同一组中的单元格,例如,与当前单元格具有相同锁定脚本的单元格。

len=证人_大小;ret=ckb_load_witness(见证,len,0,索引,CKB _ SOURCE _ GROUP _ INPUT);if (ret!=CKB _成功){ return ERROR _ SYSCALL} if(len WITNESS _ SIZE){ return ERROR _ WITNESS _ TOO _ LONG;}if(!(witness_table=ns(证人_as_root(证人))){ return ERROR _ ENCODING}args=ns(证人_数据(证人_表));if(ns(Bytes _ vec _ len(args))1){ return ERROR _ FAULT _ NUMBER _ OF _ ARGUMENTS;}然后沿着这条路径,我们正在读取当前输出的见证。对应的见证和输出具有完全相同的索引。现在,在Syscalls for flatbuffer中使用CKB作为序列化格式,因此如果您感到惊讶,Flatcc的文档(https://github.com/dvidelabs/flatcc)可以帮助您解释它。

/*加载签名*/len=TEMP _ SIZE;ret=extract _ Bytes(ns(Bytes _ vec _ at(args,0)),temp,len);if (ret!=CKB _成功){ return ERROR _ ENCODING}/*第65个字节根据合同规范重新计算。*/RECID=temp[RECID _ INDEX];/* Recover publikey */secp 256 k1 _ ecdsa _ recoverable _ signature签名;if(secp 256 k1 _ ECD sa _ recoverable _ SIGNAL _ PARSE _ compact(context,SIGNAL,temp,recid)=0){ return ERROR _ SECP _ PARSE _ SIGNAL;} Blake 2 b _ state Blake 2 b _ CTX;blake2b_init(blake2b_ctx,Blake 2b _ BLOCK _ SIZE);blake2b_update(blake2b_ctx,tx_hash,Blake 2 b _ BLOCK _ SIZE);for(size _ t I=1;ins(Bytes _ vec _ len(args));I){ len=TEMP _ SIZE;ret=extract _ Bytes(ns(Bytes _ vec _ at(args,I)),temp,len);if (ret!=CKB _成功){ return ERROR _ ENCODING} blake2b_update(blake2b_ctx,temp,len);}blake2b_final(blake2b_ctx,temp,Blake 2 b _ BLOCK _ SIZE);Witness中的第一个参数是要读取的签名,剩下的参数(如果获得的话)可以选择作为Blake2b操作符的事务Hash。

亚博真人官网

secp256k1 _ pubkey pubkeyif(secp 256 k1 _ ECD sa _ recover(context,pubkey,signature,temp)!=1){ return ERROR _ SECP _ RECOVER _ PUBKEY;}然后使用散列的Blake2b结果作为信息来开发Secp256签名检查。size _ t pubkey _ size=PUBKEY _ SIZEif(secp 256 k1 _ EC _ pubkey _ serialize(context,temp,pubkey_size,pubkey,SECP256K1 _ EC _ COMPRESSED)!=1){ return ERROR _ SECP _ Serialize _ PUBKEY;} len=PUBKEY _ SIZEblake2b_init(blake2b_ctx,Blake 2b _ BLOCK _ SIZE);blake2b_update(blake2b_ctx,temp,len);blake2b_final(blake2b_ctx,temp,Blake 2b _ BLOCK _ SIZE);if (memcmp(argv[1],温度,BLAKE160_SIZE)!=0){ return ERROR _ PUBKEY _ BLAKE 160 _ HASH;}最后,在某种程度上,最重要的是,我们还必须检查一下,可恢复签名中包含的Pubkey,显然是用来分解Lock脚本参数中包含的Pubkey Hash的Pubkey。

否则,有人可能会使用另一个公钥分解签名来窃取您的令牌。简而言之,配置文件的锁定脚本中使用的方案与当今比特币中使用的方案非常相似。解释一下Duktape。我坚信你现在的感受和我一样:我们可以用c语言写合同,这很好,但是c语言总是有点枯燥,而且,更现实一点,很危险。

有没有更好的办法?当然可以!上面说的CKB-VM本质上是一个微型计算机,我们可以探索很多解决方案。我们现在要做的一件事是用JavaScript编写CKB脚本代码。

是的,你说得对,非常简单的ES5(是的,我告诉你,但这只是一个例子,你可以用它来做转换器)JavaScript。这怎么可能?由于我们有一个C编译器,我们只需要为嵌入式系统构建一个JavaScript。在我们的例子中,Duktape将它从C编译成RISC-V二进制文件,并将其放在链上,这样我们就可以在CKB上运行JavaScript了!因为我们使用的是真正的微型计算机,所以没有什么可以阻止我们将另一个虚拟机映射到CKB虚拟机,作为CKB脚本,并在虚拟机路径上探索这个虚拟机。从这条路开始,我们可以在CKB使用Duktape做JavaScript,也可以在CKB使用Mruby做ruby,甚至可以使用比特币脚本或EVM被放在链上,我们只需要编译他们的虚拟机并把它放在链上。

这确保了CKB虚拟机不仅可以帮助我们保留资产,还可以构建一个多元化的生态系统。在CKB,所有语言都应该得到公平对待,权利应该由区块链合同的开发者来控制。

在这个阶段,你可能实际上:是的,有可能,但是VM上面的VM会极快吗?我坚信这些是不一样的。你的例子是不是极快?我深信,除非把标杆管理放到一个有标准硬件市场需求的实际用例中去,否则标杆管理是没有意义的。

因此,我们必须让时间来检验这是否不会成为一个问题。在我看来,高级语言更有可能被用作类型脚本来维护单元切换。这样的话,我估计不会很快。此外,我们还希望在这一领域优化虚拟机上的CKB虚拟机和CKB虚拟机,以便将其用于CKB的杜克磁带。

首先,Duktape本身必须编译成RISC-V可执行二进制文件:$ git clone https://github.com/nervosnetwork/ckb-duktape$ CD ckb-Duk tape $ sudo docker run-RM-it-V ` pwd ` :/code nervos/ckb-riscv-GNU-tool chain : xenial bash[emailprotected]: ~ # CD/code[emailprotected]:/code # makerisvc 64-unknown-elf-gcc-OS-DCKB _ NO _ MMU-D _ _ riscv这里的第一步是在CKB细胞中部署杜卡带脚本代码./ckb-Duk tape/build/Duk tape ‘)pry(main)Duk tape _ data . bytesize=269064 pry(main)Duk tape _ tx _ hash=wallet . send _ capacity(wallet . address,ckb : utils . byte _ to _ Shannon(280000),ckb 33603360 utils . bin _ to _ hex(Duk tape _ data))pry(main)Duk tape _ data _ hash=ckb :6 ‘)’))])请注意,对于不同的参数,您可以为不同的用例创建Duktape反对的不同类型的脚本:pry(main)Duk tape _ hello _ type _ script=ckb :3360 types 33603360 script . new(code _ hash : Duk tape _ data _ hash,arg :[ckb 33603360 utils . bin _ to _ hex(‘ var a=1; nvar b=a2;)])这反映了脚本代码和上面提到的脚本的区别:这里使用Duktape作为脚本代码获取JavaScript引擎,而不同的脚本使用Duktape脚本代码获取链上不同的函数。
目前我们可以创建一个Cell和Duktape的Type Script附件:pry(main)tx=wallet . generate _ tx(wallet 2 . address,ckb 3360: utils . byte _ to _ Shannon(200))pry(main)tx . deps . push(Duk tape _ out _ point . dup)pry(main)tx . outputs[0]。instance _ variable _ set(: @ type,Duk tape _ hello _ type _ script . dup)pry(main)tx . witness[0]. data . clear pry(main)tx=tx . sign(wallet . key,API.compute _ transaction _ hash(tx))pry(main)API . send _ transaction(tx)=’0x 2 E4 D3 aab 4284 BC 52 fc 6 f 07 df 66 e7c 8 fc 0 e 236916 b 8 A8 b 8417 abb 2 a 2c 60824028 ‘如果在ckb.toml文件中将ckb-script日志模块的级别设置为debug,可以看到如下日志:2019-07-15 05:59336013.551 00:00 http。worker 8 debug ckb-script脚本组: c 35 b 9 fed 5 fc 0 DD 6 eaef 5a 918 CD 7 a 4a 4b 7 ea 93398 bece 4d 457 2b 67 a 444874641 DEBUG output :我在JS中运行!现在您已经在CKB成功地部署了一个JavaScript引擎,并在CKB运行了基于JavaScript的脚本!您可以在这里尝试理解JavaScript代码。

既然你已经熟悉了CKB剧本的基本知识,这里有一个想法:在这篇文章中,你已经看到了一个永远成功的剧本是什么样的,但是一个永远失败的剧本呢?永远失败的脚本(和脚本代码)可以有多小?提醒:这不是GCC优化比赛,只是一个思路。我告诉过你这是上一集预告片中的一个很长的帖子,我希望你已经尝试过了,并且成功地将一个脚本部署到了CKB。在下一篇文章中,我们将解释一个最重要的主题:如何让您自己的用户在CKB定义令牌(UDT)。

UDT在CKB最糟糕的地方在于,每个用户都可以将自己的UDT存储在自己的单元中,这与以太网上的ERC20令牌不同,在以太网上,每个人的令牌都必须位于令牌发起者的单个地址中。所有这些都可以通过为类型脚本单独使用它们来构建。

|亚博真人官网。

本文来源:亚博真人官方-www.shijicaoben.com

You may also like...

相关文章

网站地图xml地图