Solidity智能合约开发技术与实战-以太坊测试网络_第1页
Solidity智能合约开发技术与实战-以太坊测试网络_第2页
Solidity智能合约开发技术与实战-以太坊测试网络_第3页
Solidity智能合约开发技术与实战-以太坊测试网络_第4页
Solidity智能合约开发技术与实战-以太坊测试网络_第5页
已阅读5页,还剩75页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

以太坊Solidity智能合约开发教程

以太坊测试网络学前提示在以太坊网络中部署和运行DApp都需要支付Gas,与在Remix或私有链中运行智能合约不同,上线后,开发者就需要真枪实弹地支付以太币了。一旦程序有bug,可能就意味着实际的损失。而在私有链中测试DApp会遇到一些与实际环境不一致的情况。以太坊和一些第三方厂商都提供了一些非常接近真实环境的以太坊测试网络,可以将DApp部署在测试网络中测试完成以太坊交易的情况。知识要点9.1主网络和测试网络9.2通过Infura节点集群连接以太坊网络9.3在测试网络中完成以太坊交易9.1主网络和测试网络1.Ropsten2.Kovan3.Rinkeby4.Goerli1.RopstenRopsten是以太坊官方提供的测试网络,采用PoW共识机制。Ropsten网络挖矿的难度很低,但是挖出的以太币没有任何价值,仅供开发和测试使用。也可以免费申请Ropsten网络的以太币。Ropsten可以说是很接近主网的测试网络。2.KovanKovan是Parity公司发起的一个测试网络。它采用PoA(ProofofAuthority,权威证明)共识算法。PoA约定:仅由若干个权威节点来生成区块,其他节点无权生成。这样也就省去了挖矿的时间。尽管有些垄断的感觉,但是测试网络中的以太币没有任何价值,权威节点纯属义务劳动。谁又会反对呢。因为是Parity公司发起的测试网络,所以只有Parity钱包客户端可以使用这个网络。3.RinkebyRinkeby也是以太坊官方推出的测试网络,采用PoA共识算法。4.Goerli基于Ethereum2.0的支持多种客户端的测试网络。由第三方团队Chainsafe推出,是以太坊基金会资助的项目。也采用PoA共识算法。

9.1.2获取测试币获取各种测试币的方法基本都可以分为如下2种:(1)在以太坊钱包中获取。(2)在测试网络的官网或其他第三方网站获取。通过以太坊钱包MetaMask申请Ropsten测试币获取测试币的页面单击“获取Ether”按钮,会打开获取测试币的页面。账号3接收到测试币9.2通过Infura节点集群连接以太坊网络Infura是一个托管的以太坊节点集群,可以免费将智能合约部署在Infura节点集群上,而无需自己搭建用于测试的以太坊节点。可以选择通过Infura接入以太坊主网或测试网络。无论是测试还是部署上线,通过Infura节点集群连接以太坊网络都是很方便的选择。9.2.1注册Infura账户Infura官网首页注册Infura账号后收到的激活邮件单击“注册”按钮,根据提示输入邮箱和密码,即可注册Infura账户。提交后注册邮箱中会收到一封激活邮件。9.2.2通过Infura连接到以太坊网络1.连接到以太坊网络的URL访问如下的URL,可以查看infura的技术文档:https://infura.io/docs在左侧导航栏中选择ChooseaNetwork,可以查看Infura支持的以太坊网络信息。infura支持的以太坊网络网络连接方式连接网络的URL主网(Mainnet)基于HTTPS的JSON-RPChttps://mainnet.infura.io/v3/YOUR-PROJECT-ID基于WebSocket的JSON-RPCwss://mainnet.infura.io/ws/v3/YOUR-PROJECT-IDRopsten基于HTTPS的JSON-RPChttps://ropsten.infura.io/v3/YOUR-PROJECT-ID基于WebSocket的JSON-RPCwss://ropsten.infura.io/ws/v3/YOUR-PROJECT-IDKovan基于HTTPS的JSON-RPChttps://kovan.infura.io/v3/YOUR-PROJECT-ID基于WebSocket的JSON-RPCwss://kovan.infura.io/ws/v3/YOUR-PROJECT-IDRinkeby基于HTTPS的JSON-RPChttps://rinkeby.infura.io/v3/YOUR-PROJECT-ID基于WebSocket的JSON-RPCwss://rinkeby.infura.io/ws/v3/YOUR-PROJECT-IDGoerli基于HTTPS的JSON-RPChttps://goerli.infura.io/v3/YOUR-PROJECT-ID基于WebSocket的JSON-RPCwss://goerli.infura.io/ws/v3/YOUR-PROJECT-IDIPFSIPFS网关https://ipfs.infura.io/ipfs/IPFSAPIhttps://ipfs.infura.io:5001/api/2.创建Infura项目单击左侧菜单中的ETHEREUM图标,打开连接以太坊网络的页面。创建新项目对话框单击CREATEAPROJECT按钮弹出创建新项目对话框。在项目详情页中,可以查看或设置如下属性·设置项目名。·查看项目ID和项目密钥。·选择连接的网络,查看连接URL。·设置是否所有请求都需要使用项目密钥(Requireprojectsecretforallrequests复选框);·设置JWT公钥,以及是否所有请求都需要提供JWT公钥(RequireJWTforallrequests复选框),本书不展开介绍通过JWT进行身份验证的方法。·项目每秒可以发送的请求数,0表示不限制。·项目每天可以发送的请求数,0表示不限制。·设置允许的User-Agent(ALLOWLISTUSERAGENTS)。例如,给移动app设置一个自定义的User-Agent,然后在Infura项目中设置指定的User-Agent才可以发送请求。·设置允许访问的合约地址(ALLOWLISTCONTRACTADDRESSES)。·允许的HTTP访问源(ALLOWLISTORIGINS)。

允许访问的API方法(ALLOWLISTAPIREQUESTMETHOD)。项目详情页设置连接网络的端点(ENDPOINTS)3.连接到以太坊网络在Web3.js中通过Infura连接以太坊网络的方法如下:varWeb3=require("web3");varweb3=newWeb3(Web3.givenProvider||连接网络的端点URL)例如,在前面创建的myproj项目中,连接Ropsten网络的端点URL如下https://ropsten.infura.io/v3/fbc7d11878344e39b5be9296da1a3521通过infura连接Ropsten测试网络的方法如下:varWeb3=reqire("web3");varweb3=newWeb3(Web3.givenProvider||'https://ropsten.infura.io/v3/fbc7d11878344e39b5be9296da1a3521')9.2.3项目ID和项目密钥1.通过项目ID标识身份2.项目密钥1.通过项目ID标识身份在所有通过infura发起的以太坊API请求中都必须提供一个有效的项目ID。本节下面的内容也是基于项目ID实现身份验证,从而保证项目的安全。2.项目密钥设置infura项目密钥设置所有的infura请求都提供项目密钥通过如下格式的URL,获取配置数据curl--user:<项目密钥>https://<network>.infura.io/v3/<项目ID><具体命令和参数>根据实际情况替换网络标识、项目ID和项目密钥,例如:curl--user:c61bf19af71b43f98f8a062f26f1a0d5\https://ropsten.infura.io/v3/fbc7d11878344e39b5be9296da1a3521【例9-1】(1)在/usr/local/目录下创建子目录infura,并在该目录下执行npminit命令初始化Node项目。根据提示信息输入项目信息,使项目的配置文件package.js代码如下:{"name":"infura","version":"1.0.0","description":"使用infura项目ID和项目密钥连接Ropsten测试网络创建Web3对象的方法","main":"index.js","scripts":{"dev":"nodeindex.js","test":"echo\"Error:notestspecified\"&&exit1"},"author":"","license":"ISC"}(2)在infura目录下创建index.jsvarWeb3=require("web3");varweb3=newWeb3(Web3.givenProvider||'https://:c61bf19af71b43f98f8a062xxxxxxxxx@ropsten.infura.io/v3/fbc7d11878344e39b5be92xxxxxxxxxx')console.log(web3);安装Web3.js(3)在infura目录下执行如下命令,安装Web3.js。

npminstallweb3@^0.20.0--save安装成功后,会在package.js中生成如下代码"dependencies":{"web3":"^0.20.7"}例9-1的运行结果9.2.4白名单在很多情况下需要从浏览器或其他第三方客户端应用发送请求。但是浏览器或第三方客户端应用并不能保证项目密钥的安全。使用白名单(allowlist)可以防止第三方应用从其他网站使用你的项目ID。如果项目没有启用白名单,则会接受所有来源的请求。白名单包含的项目如下

ALLOWLISTCONTRACTADDRESSES:设置用此项目ID只能访问指定地址的合约。

ALLOWLISTUSERAGENTS:设置允许连接的UserAgent。UserAgent是一个特殊的字符串,服务器可以通过UserAgent识别客户端使用的操作系统及版本、CPU类型、浏览器及版本、浏览器渲染引擎、浏览器语言、浏览器插件等。

ALLOWLISTORIGINS:ORIGINS是POST请求头中包含的一个可选字段,用于标识请求的最初来源。ALLOWLISTORIGINS设置可以发送请求的域名,例如。

ALLOWLISTAPIREQUESTMETHOD:设置请求允许调用的API方法,例如eth_getBlockNumber。可以从下拉框中选择允许的方法。一个设置白名单的例子假定公司example开发了一个名为shop的dapp,则可以在ALLOWLISTUSERAGENTS中添加com.example.shopapp(假定是shop网站的域名),在ALLOWLISTORIGINS中添加(需要在DApp中发送请求时设置)。这样就可以允许从网站和app中使用项目ID访问infura网络。9.2.5部署智能合约到Ropsten网络可以利用Truffle的hdwallet-provider组件将智能合约部署到Ropsten网络。hdwallet-provider组件是一个启用了硬件钱包的Web3提供器(provider)。安装hdwallet-provider组件npminstalltruffle-hdwallet-provider修改Truffle项目的配置文件truffle-config.js,代码如下//定义HDWalletProvider对象varHDWalletProvider=require("truffle-hdwallet-provider");//提供助记词(mnemonic)来生成你的账户varmnemonic="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";//添加Ropsten测试网络定义module.exports={networks:{ropsten:{provider:function(){//定义以太坊节点https://ropsten.infura.io/your-api-keyreturnnewHDWalletProvider(mnemonic,"https://ropsten.infura.io/v3/fbc7d11878344e39b5be9296da1a3521",0,1);},network_id:"*",gas:3012388,gasPrice:30000000000}}};在测试网络Ropsten中部署合约MetaCointrufflemigrate--networkropsten如果一切正常,则执行结果如下Compilingyourcontracts...===========================……contractaddress:0x96e10b02CC76544787dEC0134b8Ed2372EDCfb62>blocknumber:9831458>blocktimestamp:1615692728>------------------------------------->Totalcost:0.01152333ETH……….

Summary=======>Totaldeployments:3>Finalcost:0.01648758ETH

9.3在测试网络中完成以太坊交易9.3.1以太坊交易过程9.3.2通过ethereumjs-tx实现与以太坊的交易9.3.3完整的交易实例9.3.1以太坊交易过程1.构建交易对象在发起交易之前,首先要构建交易对象。交易对象的结构可以参照6.3.6节中例6-11理解。2.签署交易为了证明交易是指定账户发起的,在发送交易前,需要使用指定账户的私钥对交易对象进行签名。如果浏览器中安装了MetaMask钱包,则MetaMask会将账户私钥存储在本地浏览器中,只有账户的主人才能访问私钥。在浏览器中发起交易时,MetaMask会自动使用私钥对交易对象进行签名。可以使用9.3.2节介绍的ethereumjs-tx库对交易对象进行签名。3.节点验证前端程序在对交易数据完成签名后,会将签名后的交易数据发送至以太坊节点。由节点对签名数据进行验证。检查签名及数据的有效性。4.广播交易

spring:profiles:active:dev

---spring:profiles:proapplication:name:config-clientcloud:config:uri:02:9005label:masterprofile:pro

5.矿工节点接受交易矿工是交易过程中的关键角色,因为是矿工最终将交易数据打包在区块中的。在众多交易中,矿工会根据交易提供的gasPrice来选择优先记账的交易,价格越高的交易越会被优先处理。因此在发起交易时设置适当高出标准的gasPrice是很重要的,这将使交易被优先处理。6.矿工挖矿成功并全网广播矿工接受交易后会将其打包在挖出的区块中。一个区块中可以容纳的交易是有限的,每个区块都有一个gasLimit。区块中包含交易的Gas总和不能超过gasLimit。打包好的区块会被添加到区块链上,矿工会将其全网广播。7.节点同步新区块全网节点在接收到新区块后,会对矿工的挖矿结果进行验算。通过后,将新区块添加到自己的区块链中。节点接受了新的区块,就意味着接受区块中的所有交易。9.3.2通过ethereumjs-tx实现与以太坊的交易ethereumjs-tx是Web3.js中用于实现以太坊交易的JavaScript库。1.对交易对象进行签名2.构建原始交易对象3.执行交易1.对交易对象进行签名安装ethereumjs-tx库。cnpminstallethereumjs-tx在项目中安装ethereumjs-tx(1)创建项目目录例如在/usr/local/目录下创建transfer子目录,作为项目目录。(2)初始化项目在/usr/local/transfer目录下执行npminit命令初始化项目,安装提示输入项目的基本信息,初始化项目。生成的package.json文件内容如下{"name":"transfer","version":"1.0.0","description":"","main":"index.js","scripts":{"test":"echo\"Error:notestspecified\"&&exit1"},"author":"","license":"ISC","dependencies":{"ethereumjs-tx":"^2.1.2"}}(3)在项目中安装ethereumjs-tx在项目目录下执行下面的命令可以在项目中安装ethereumjs-tx。cnpminstallethereumjs-tx--save安装完成后,查看的package.json文件内容,可以看到ethereumjs-tx的版本信息"dependencies":{"ethereumjs-tx":"^2.1.2"}2.构建原始交易对象首先需要构建原始交易对象。原始交易对象包含如下字段·Nonce:记录发起交易的账户已执行交易总数。·gasPrice:Gas的价格,单位为wei。GasPrice越高,会越优先被矿工打包。·gasLimit:Gas的上限,可以防止因为程序的bug(比如陷入死循环一直发起交易)而耗尽账户里的所有余额用于支付Gas。设置gasLimit后,交易执行完毕后,超出部分会返还至交易账户。·to:接受交易金额的账户地址。·value:交易的金额。·data:如果交易是发送以太币,则data为空;如果是部署合约,则data为合约的字节码。一个原始交易对象的示例varrawTx={nonce:'0x00',gasPrice:'0x09184e72a000',gasLimit:'0x2710',to:'0x0000000000000000000000000000000000000000',value:'0x00',data:'0x7f7465737432000000000000000000000000000000000000000000000000000000600057'}从账户account1向账户account2转账0.1ETH的原始交易对象代码web3.eth.getTransactionCount(account1,(err,txCount)=>{consttxObject={nonce:web3.utils.toHex(txCount),to:account2,value:web3.utils.toHex(web3.utils.toWei('0.1','ether')),gasLimit:web3.utils.toHex(21000),gasPrice:web3.utils.toHex(web3.utils.toWei('10','gwei'))}})3.执行交易(1)使用私钥对交易对象进行签名。(2)广播交易。(1)使用私钥对交易对象进行签名。·将原始交易对象转换为Tx对象,方法如下:consttx=newTx(txObject);·准备好发起交易的账户,找到账户的私钥。并使用私钥对交易对象进行签名,方法如下:tx.sign(<私钥>)(2)广播交易·将交易对象序列化后将其转换为16进制字符串,为广播交易做好准备。代码如下:constserializedTx=tx.serialize()constraw='0x'+serializedTx.toString('hex')·调用web3.eth.sendSignedTransaction()函数将16进制签名字符串发送到以太坊网络中,代码如下:web3.eth.sendSignedTransaction(raw,(err,txHash)=>{console.log('txHash:',txHash)})9.3.3完整的交易实例【例9-2】参照下面的步骤演示通过ethereumjs-tx实现与以太坊交易的方法。1.确定交易的网络,选择交易的账号2.准备账户对应的私钥3.安装web3组件4.在App.js中编写程序,实现交易1.确定交易的网络,选择交易的账号这里选择测试网络Ropsten发起交易。参照8.3.4节介绍的方法使用MetaMask钱包连接到测试网络Ropsten,选择2个账户,如果需要就创建一个新账户。这里假定账户1的地址为0x32985d709D7FC4d5F40148592f967578Cb9ec1D5,账户2的地址为0xc07C9bF8f2E83E9E15aEf2a6727E2dC64b447Aea。在本例中会用到这两个账户进行交易。在MetaMask钱包查看并记录账户1和账户2的余额。如果余额为0,可以参照9.1.2获取测试币。2.准备账户对应的私钥输入MetaCoin密码查看账户的私钥将私钥设置为环境变量exportPRIVATE_KEY_1='b75e2bcaec74857cf9bb6636d66a04784dxxxxxxxxxxxxxxx'$exportPRIVATE_KEY_2='ac0adfdbaeb0770a479e79aac78779d82fxxxxxxxxxxxxxxx'在程序中可以通过如下代码引用账户私钥constprivateKey1=process.env.PRIVATE_KEY_1constprivateKey2=process.env.PRIVATE_KEY_2要想使用私钥对交易进行签名,则需要通过如下代码将其转换成二进制数据字符串constprivateKey1=Buffer.from(process.env.PRIVATE_KEY_1)constprivateKey1=Buffer.from(process.env.PRIVATE_KEY_2)3.安装web3组件在/usr/local/transfer目录下执行如下命令安装web3组件:cnpminstallweb3--save在package.json中dependencies节的代码"dependencies":{"ethereumjs-tx":"^2.1.2","web3":"^1.3.5"}4.在App.js中编写程序,实现交易varTx=require('ethereumjs-tx').TransactionconstWeb3=require('web3')//注意替换为自己的infura项目ID和项目密钥constweb3=newWeb3('https://:c61bf19af71b43f98f8a062f26f1a0d5@ropsten.infura.io/v3/fbc7d11878344e39b5be9296da1a3521')//设置账户地址constaccount1='0x32985d709D7FC4d5F40148592f967578Cb9ec1D5';constaccount2='0xc07C9bF8f2E83E9E15aEf2a6727E2dC64b447Aea';//从环境变量中获取账户对应的私钥constpk1=process.env.PRIVATE_KEY_1;constpk2=process.env.PRIVATE_KEY_2;console.log(pk1);console.log(pk2);//将私钥转换为二进制字符串constprivateKey1=Buffer.from(pk1,'hex')constprivateKey2=Buffer.from(pk2,'hex')var_from=account1;web3.eth.getTransactionCount(_from,(err,txcount)=>{vartxObject={nonce:web3.utils.toHex(txcount),gasPrice:web3.utils.toHex(web3.utils.toWei('10','gwei')),gasLimit:web3.utils.toHex(21000),to:account2,//'0xc07C9bF8f2E83E9E15aEf2a6727E2dC64b447Aea',value:web3.utils.toHex(web3.utils.toWei('

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论