深入浅出谈谈智能合约:编译、创建和部署合约

尚力财经 335 0

契约是代码(其功能)和数据(其状态)的集合,存在于以太坊区块链的特定地址。合同账户可以在彼此之间传递信息,并执行Turing complete操作。该合同在一个名为以太坊虚拟机(EVM)的字节码(以太坊特有的二进制格式)区块链上运行。

合约一般用Solidity之类的高级语言编写,然后编译成字节码上传到区块链。

另见:

其他语言也存在,尤其是Serpent和LLL,这将在本文以太坊高级语言一章中进一步阐述。分散的应用程序开发资源列出了一个全面的开发环境,以帮助您用这些语言开发开发人员工具,提供测试和部署支持。

契约运行在一个名为以太坊虚拟机(EVM)的字节码(以太坊特有的二进制格式)区块链上。然而,该合同通常是用Solidity等高级语言编写的,然后由邰方虚拟机编译器编译成字节码并上传到区块链。

以下是开发者可以用来编写以太坊智能合约的高级语言。

Solidity是一种类似于JavaScript的语言,你可以用它来开发契约,编译成以太坊虚拟机的字节码。

是目前以太坊最流行的语言。

Solidity TextSolidity是以太坊的旗舰高级语言,用来写合同。Solidity online实时编译器标准契约API有用的去中心化模式——去中心化应用开发的代码片段。

Serpent是一种类似于Python的语言,可以用来开发契约,编译成以太坊虚拟机的字节码。它力求简洁,将低级语言在效率上的优势与编程风格的简洁结合起来,同时契约式编程增加了独特的特定领域功能。蛇与LLL编译。

以太坊维基百科上的SerpentSerpent以太坊虚拟机编译器 LISP like语言(LLL)是一种类似于汇编的低级语言。它追求极简主义;本质上只是以太坊虚拟机直接的一点包装。

GitHub上LIBLLLLLL的实例

Mutan Mutan是一个静态类型,是由Jeffrey Wilcke开发设计的C类语言。它不再被维护。

写合同没有Hello World这个程序,语言是不完整的。Solidity在以太坊环境下运行,没有明显的方式“输出”字符串。我们能做的最接近的就是记录事件把字符串放入区块链:

1234 contract hello world { event print(string out);function() { Print('Hello,World!');} }

每次执行此契约时,都会在区块链中创建一个日志条目,内容为“Hello,World!”参数。

参见:

Solidity docs提供了更多编写Solidity代码的示例和说明。

编译契约solidity契约的编译可以通过很多机制来完成。

从命令行使用solc编译器。使用geth或eth提供的javascript控制台中的web3.eth.compile.solidity(这个还是需要安装solc编译器)。在线实时编译器。流星dapp宇宙建立坚实的合同。混合IDE .以太坊钱包。

注意:关于solc和编译Solidity合同代码的更多信息可以在这里查看。

在geth设置solidity编译器如果启动geth节点,可以看到哪个编译器可用。

12 web 3 . eth . get compilers();['LLL ''坚固''蛇'] [X]这个指令将返回一个字符串,显示当前可用的编译器。

注意:solc编译器是和cpp-以太坊一起安装的。或者,你可以自己创造。

如果您的solc可执行文件不在标准位置,您可以使用-SOLC标志为solc可执行文件指定一个定制的路径。

1 $ geth-SOLC/usr/local/bin/SOLC

或者你可以在执行过程中通过控制台设置这个选项:

1234 admin . setsolc('/usr/local/bin/SOLC ')SOLC,solidity编译器命令行接口版本:0.2.2-02bb315d/。-Darwin/appleclang/JIT链接到libethereum-1.2.0-8007cef0/。-Darwin/apple clang/JIT path:/usr/local/bin/solc

编译一个简单的契约

1 source=' contract test { function multiple(uinta)returns(uintd){ return a* 7;

这个契约提供了一个单一的方法multiply,用正整数A调用,返回a * 7。

你要在geth JS控制台用eth.compile.solidity()编译solidity代码:

12345678910112131415161718192021222242526272930 contract=eth . compile . solidity(source)。test { code:' 605280600 c 6000396000 f 30060000357 c 01000000000000000000000000000000信息:{ language: 'Solidity 'languageVersion: '0 'compilerVersion: '0.9.13 '遵守定义:[{ constant: false,inputs:[{ 0} }' }}

注意:编译器可用于任何通过RPC连接到geth的Dapp,因此也可用于浏览器中的web3.js。

接下来的例子将向你展示如何通过JSON-RPC结合geth使用编译器。

12 $ geth-datadir ~/eth/-log level 6-logtostderr=true-RPC-RPC port 8100-RPC corsdomain ' * '-mine console 2 ~/eth/eth . log $ curl-xpost-data ' { ' JSON RPC '' 2.0 '' method'' eth _ compilesolidity '' params' ['contracttest {

单源编译器的输出会给你契约对象,每个对象代表一个单独的契约。eth.compile.solidity的实际返回值是契约名到契约对象的映射。由于合约名称为test,eth.pile.Solidity (Source)。Test会给出一个测试契约对,覆盖以下字段:以太坊虚拟机字节码Info由

Code编译的附加元数据从编译器源代码语言契约语言(solidity,Serpent,LLL)LanguageVersion契约语言版本编译器Version用于编译这个契约的solidity编译器版本。abiDefinition应用程序的二进制接口定义了userDoc用户的NatSpec文档。developerDoc开发者的NatSpec文档。

编译器输出的直接结构(代码和信尚力财经小编2022息)反映了两种非常不同的部署路径。编译后的以太坊虚拟机代码和一个契约创建事务被发送到块,剩下的(info)将理想地生活在去中心化的云上,公开验证的元数据将在区块链上执行代码。

如果您的源包含多个合同,则输出将包括每个合同的条目,并且可以使用合同名称作为属性名称来检索相应的合同信息对象。可以通过检测当前GlobalRegistrar代码来尝试:

1 contracts=eth . pile . solidity(global registrar src)

创建和部署合同

注:用online Solidity实时编译器或者Mix IDE程序会更容易完成。

1234 var primary address=eth . accounts[0]var ABI=[{ constant:false,inputs: [{ name: 'a 'Type:' uint 256 ' }]var my contract=eth。合约(ABI)风险值合约=我的合约。新的(arg1,arg2,{from:主地址,data: evmbytecode frompreview

所有二进制数据都以十六进制格式序列化。十六进制字符串总是有一个十六进制前缀0x。

注意:注意arg1,arg2,…是契约构造函数参数,以防它带参数。如果契约不需要构造函数参数,可以忽略它们。

值得指出的是,这一步需要你付出。 一旦交易成功进入区块,您的账户余额(您作为发送方放入from字段)将根据以太坊虚拟机的gas规则被扣除。一段时间后,你的事务会出现在一个区块中,并确保它所带来的状态是共识。你的合同现在存在于区块链。以异步方式做同样的事尚力财经小编2022情看起来是这样的:

123mycontract。新([arg1,arg2,] {from:主账户,data: evmcode},function (err,contract) {if(!err contract.address)控制台. log(contract . address);});

与契约交互

12 var multiply 7=eth . contract(contract . info . abid definition);var myMultiply7=Multiply7.at(地址);

现在,在ABI中指定的所有函数调用在契约实例中都可用了。您可以通过两种方式之一调用这些协定实例上的方法。

1234 mymultiply 7。倍增。sendTransaction (3,{ from:address })'0x 12345 ' my multiply 7。倍增。call (3) 21

用send transaction调用时,通过发送事务来执行函数调用。发送需要很高的费用,而且通话将被永久记录在区块链里。以这种方式进行的调用的返回值是一个事务哈希表。

调用时,函数在以太坊虚拟机本地执行,函数返回值随函数一起返回。以这种方式进行的呼叫不会在区块链中被记录,因此它不会改变合约的内部状态。这种调用方法称为常量函数调用。通过这种方式拨打电话不需要支付以太坊的费用。

如果你只对返回值感兴趣,那么你应该使用call。如果只关心契约状态的副作用,应该使用sendTransaction。

上面的例子不会有副作用,所以sendTransaction只会燃烧气体,增加宇宙熵。

合同元数据

1234//获取合同地址的合同信息进行手动验证var info=admin . getcontraction info(address)//lookup,fetch,decodevar source=info.sourceVarabidef=info。abid definition

这项工作的潜在机制是:

合同信息被可公开访问的URIs上传到一个可识别的地方,任何人只要知道合同地址就能查出它是什么URI

这些要求只有通过两步区块链注册才能实现。第一步是在名为HashReg的契约中用内容哈希表注册契约代码(哈希表)。第二步是在UrlHint契约中用内容哈希表注册一个url。这些登记合同是边疆版的一部分,已经涉及宅基地。

你需要知道契约地址才能查询url并获得实际的契约元数据包,这样,用这一机制就足够了。

如果你是个尽职的合约创建者,请遵循以下步骤:

将合约本身部署到区块链获取合约信息json文件将合约信息json文件部署到你选择的任意url注册代码散表 –>内容散表 –> url

JS API通过提供助手把这个过程变得非常容易。 调用admin.register从合约中提取信息,在指定文件中写出json序列,运算文件的内容散表,最终将这个内容散表注册到合约代码散表。一旦将那个文件部署到任意url,你就能用admin.registerUrl来注册url 和你区块链上的内容散表(注意一旦固定的内容选址模式被用作文件商店,url-hint不再必要了。)

深入浅出谈谈智能合约:编译、创建和部署合约-第1张图片-欧交易所

12345678910111213141516171819source = "contract test { function multiply(uint a) returns(uint d) { return a * 7; } }" // compile with solccontract = eth.compile.solidity(source).test// create contract objectvar MyContract = eth.contract(contract.info.abiDefinition)// extracts info from contract, save the json serialisation in the given file, contenthash = admin.saveInfo(contract.info, "~/dapps/shared/contracts/test/info.json")// send off the contract to the blockchainMyContract.new({from: primaryAccount, data: contract.code}, function(error, contract){ if(!error && contract.address) { // calculates the content hash and registers it with the code hash in `HashReg` // it uses address to send the transaction. // returns the content hash that we use to register a url admin.register(primaryAccount, contract.address, contenthash) // here you deploy ~/dapps/shared/contracts/test/info.json to a url admin.registerUrl(primaryAccount, hash, url) }});

测试合约和交易

1geth --datadir ~/dapps/testing/00/ --port 30310 --rpcport 8110 --networkid 4567890 --nodiscover -

提交交易之前,你需要创建私有测试链。参阅测试网络。

123456// create account. will prompt for passwordpersonal.newAccount();// name your primary account, will often use itprimary = eth.accounts[0];// check your balance (denominated in ether)balance = web3.fromWei(eth.getBalance(primary), "ether");12345678910// assume an existing unlocked primary accountprimary = eth.accounts[0];// mine 10 blocks to generate ether// starting minerminer.start(4);// sleep for 10 blocks (this can take quite some time).admin.sleepBlocks(10);// then stop mining (just not to burn heat in vain)miner.stop();balance = web3.fromWei(eth.getBalance(primary), "ether");

创建交易之后,你可以用接下来的命令来强制运行:

123miner.start(1);admin.sleepBlocks(1);miner.stop();

你可以用以下命令查看即将发生的交易:

123456// shows transaction pooltxpool.status// number of pending txseth.getBlockTransactionCount("pending");// print all pending txseth.getBlock("pending", true).transactions

如果你提交合约创建交易,可以检查想要的代码是否实际上嵌入到当前的区块链:

1234txhash = eth.sendTansaction({from:primary, data: code})//... miningcontractaddress = eth.getTransactionReceipt(txhash);eth.getCode(contractaddress)

感谢朝夕团队Azure, Bob参与《Ethereum Homestead Documentation》的翻译和校验。

汪晓明

HPB芯链创始人,专栏作家。十余年金融大数据、区块链技术开发经验,曾参与创建银联大数据。主创区块链教学视频节目《明说》30多期,编写了《以太坊官网文档中文版》,并作为主要作者编写了《区块链开发指南》,在中国区块链社区以ID“蓝莲花”知名。

标签: admin

抱歉,评论功能暂时关闭!

微信号已复制,请打开微信添加咨询详情!