以太坊私网建立 、合约编译、部署

素颜马尾好姑娘i 2021-11-29 12:58 429阅读 0赞

一、为什么用到私有链?

在以太坊的共有链上部署智能合约、发起交易需要花费以太币。而通过修改配置,可以在本机搭建一套以太坊私有链,因为与公有链没关系,既不用同步公有链庞大的数据,也不用花钱购买以太币,很好地满足了智能合约开发和测试的要求,开发好的智能合约也可以很容易地切换接口部署到以太坊公有链上。

二、开源工具和语言

1、brewMacOS包管理器

拷贝下面的命令到终端,然后回车。

  1. /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

2、install Go compiler

  1. liyuechun:Downloads yuechunli$ brew install go

3、geth运行以太坊节点

下载Source code (tar.gz)

  1. liyuechun:Downloads yuechunli$ cd go-ethereum-1.5.9
  2. liyuechun:go-ethereum-1.5.9 yuechunli$ pwd
  3. /Users/liyuechun/Downloads/go-ethereum-1.5.9
  4. liyuechun:go-ethereum-1.5.9 yuechunli$ make geth

4、Solidity以太坊智能合约语言

  1. brew update
  2. brew upgrade
  3. brew tap ethereum/ethereum
  4. brew install solidity
  5. brew linkapps solidity

备注:安装时间可能有点长,请耐心等待…
备注:安装时间可能有点长,请耐心等待…
备注:安装时间可能有点长,请耐心等待…

如果碰见下面的错误,请移步:http://blog.csdn.net/Sico2Sico/article/details/71082130

  1. The GitHub credentials in the macOS keychain may be invalid.
  2. Clear them with:
  3. printf "protocol=https\nhost=github.com\n" | git credential-osxkeychain erase
  4. Or create a personal access token:
  5. https://github.com/settings/tokens/new?scopes=gist,public_repo&description=Homebrew

三、建立私链

1. 创建一个文件夹来存储你的私链数据

  1. liyuechun:1015 yuechunli$ mkdir privatechain
  2. liyuechun:1015 yuechunli$ pwd
  3. /Users/liyuechun/Desktop/1015
  4. liyuechun:1015 yuechunli$ ls
  5. privatechain
  6. liyuechun:1015 yuechunli$

2. 使用geth来加载

  1. geth --networkid 123 --dev --datadir data1 --rpc --rpcaddr 192.168.1.5 --rpcport 8989 --port 3000

各选项含义如下:

  • --identity:指定节点 ID;
  • --rpc:表示开启 HTTP-RPC 服务;
  • --rpcaddr:HTTP-RPC 服务ip地址;
  • --rpcport:指定 HTTP-RPC 服务监听端口号(默认为 8545);
  • --datadir:指定区块链数据的存储位置;
  • --port:指定和其他节点连接所用的端口号(默认为 30303);
  • --nodiscover:关闭节点发现机制,防止加入有同样初始配置的陌生节点。

执行上面的命令,你应该能看到下面的信息:

INFO [10-15|03:14:50] IPC endpoint opened: /Users/liyuechun/Desktop/1015/privchain/geth.ipc
INFO [10-15|03:14:50] HTTP endpoint opened: http://127.0.0.1:8545

如果你切换到privchain文件夹里面,你会看到geth, geth.ipc, 和 keystore

  1. liyuechun:1015 yuechunli$ cd data1/
  2. liyuechun:data1 yuechunli$ ls
  3. geth geth.ipc keystore
  4. liyuechun:data1 yuechunli$
  • 保持节点的运行,不要关闭终端,重新打开一个终端,使用geth attach连接节点,并且打开geth console

    liyuechun:privchain yuechunli$ geth attach ipc:/Users/liyuechun/Desktop/1015/privchain/geth.ipc
    Welcome to the Geth JavaScript console!

    instance: Geth/v1.7.1-stable-05101641/darwin-amd64/go1.9.1
    modules: admin:1.0 debug:1.0 eth:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 shh:1.0 txpool:1.0 web3:1.0

    >

这是一个交互式的 JavaScript 执行环境,在这里面可以执行 JavaScript 代码,其中 > 是命令提示符。在这个环境里也内置了一些用来操作以太坊的 JavaScript 对象,可以直接使用这些对象。这些对象主要包括:

  • eth:包含一些跟操作区块链相关的方法;
  • net:包含一些查看p2p网络状态的方法;
  • admin:包含一些与管理节点相关的方法;
  • miner:包含启动&停止挖矿的一些方法;
  • personal:主要包含一些管理账户的方法;
  • txpool:包含一些查看交易内存池的方法;
  • web3:包含了以上对象,还包含一些单位换算的方法。

3. 相关api命令

查看账户

  1. > personal.listAccounts
  2. []
  3. >

创建账户

  1. > personal.newAccount('liyuechun')
  2. "0xb6d7d842e7dc9016fa6900a183b2be26fc90b2d8"
  3. >

PS:里面的liyuechun是你账户的密码,输入你自己喜欢的密码。

查看账户

  1. > personal.listAccounts
  2. ["0xb6d7d842e7dc9016fa6900a183b2be26fc90b2d8"]
  3. >

4. web3命令

https://ethereumbuilders.gitbooks.io/guide/content/en/ethereum_javascript_api.html

  1. > web3.eth.coinbase
  2. "0xb6d7d842e7dc9016fa6900a183b2be26fc90b2d8"
  3. >

5. 编写智能合约代码

  1. pragma solidity ^0.4.18;
  2. contract test {
  3. function multiply(uint a) returns(uint d){
  4. return a * 7;
  5. }
  6. }

6. 获取智能合约字节码和abi

代码拷贝到https://remix.ethereum.org,编译,然后拷贝字节码和ABI。

  • 字节码

    6060604052341561000f57600080fd5b5b60ab8061001e6000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063c6888fa114603d575b600080fd5b3415604757600080fd5b605b60048080359060200190919050506071565b6040518082815260200191505060405180910390f35b60006007820290505b9190505600a165627a7a7230582067d7c851e14e862886b6f53dad6825135557fb3a4b691350c94ea5b80605f6770029

  • ABI

    [
    {

    1. "constant": true,
    2. "inputs": [
    3. {
    4. "name": "a",
    5. "type": "uint256"
    6. }
    7. ],
    8. "name": "multiply",
    9. "outputs": [
    10. {
    11. "name": "d",
    12. "type": "uint256"
    13. }
    14. ],
    15. "payable": false,
    16. "type": "function",
    17. "stateMutability": "view"

    }
    ]

7. 在bejson中转义成字符串

http://www.bejson.com

  1. [{\"constant\":true,\"inputs\":[{\"name\":\"a\",\"type\":\"uint256\"}],\"name\":\"multiply\",\"outputs\":[{\"name\":\"d\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\",\"stateMutability\":\"view\"}]

7. 通过abi创建合约对象

  1. > var abi = JSON.parse('[{\"constant\":true,\"inputs\":[{\"name\":\"a\",\"type\":\"uint256\"}],\"name\":\"multiply\",\"outputs\":[{\"name\":\"d\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\",\"stateMutability\":\"view\"}]')
  2. > myContract = web3.eth.contract(abi)
  3. {
  4. abi: [{
  5. constant: false,
  6. inputs: [{...}],
  7. name: "multiply",
  8. outputs: [{...}],
  9. payable: false,
  10. type: "function"
  11. }],
  12. eth: {
  13. accounts: ["0x2abf46d8b0d940cdeedd55872bc0648add40227d"],
  14. blockNumber: 384,
  15. coinbase: "0x2abf46d8b0d940cdeedd55872bc0648add40227d",
  16. compile: {
  17. lll: function(),
  18. serpent: function(),
  19. solidity: function()
  20. },
  21. defaultAccount: undefined,
  22. defaultBlock: "latest",
  23. gasPrice: 0,
  24. hashrate: 0,
  25. mining: false,
  26. pendingTransactions: [],
  27. protocolVersion: "0x3f",
  28. syncing: false,
  29. call: function(),
  30. contract: function(abi),
  31. estimateGas: function(),
  32. filter: function(fil, callback),
  33. getAccounts: function(callback),
  34. getBalance: function(),
  35. getBlock: function(),
  36. getBlockNumber: function(callback),
  37. getBlockTransactionCount: function(),
  38. getBlockUncleCount: function(),
  39. getCode: function(),
  40. getCoinbase: function(callback),
  41. getCompilers: function(),
  42. getGasPrice: function(callback),
  43. getHashrate: function(callback),
  44. getMining: function(callback),
  45. getPendingTransactions: function(callback),
  46. getProtocolVersion: function(callback),
  47. getRawTransaction: function(),
  48. getRawTransactionFromBlock: function(),
  49. getStorageAt: function(),
  50. getSyncing: function(callback),
  51. getTransaction: function(),
  52. getTransactionCount: function(),
  53. getTransactionFromBlock: function(),
  54. getTransactionReceipt: function(),
  55. getUncle: function(),
  56. getWork: function(),
  57. iban: function(iban),
  58. icapNamereg: function(),
  59. isSyncing: function(callback),
  60. namereg: function(),
  61. resend: function(),
  62. sendIBANTransaction: function(),
  63. sendRawTransaction: function(),
  64. sendTransaction: function(),
  65. sign: function(),
  66. signTransaction: function(),
  67. submitTransaction: function(),
  68. submitWork: function()
  69. },
  70. at: function(address, callback),
  71. getData: function(),
  72. new: function()
  73. }

8. 检查coinbase账号余额

  1. > account1 = web3.eth.coinbase
  2. "0x2abf46d8b0d940cdeedd55872bc0648add40227d"
  3. > web3.eth.getBalance(account1)
  4. 0
  5. >

如果余额大于0,继续,否则,开始挖矿。

  1. > miner.start();
  2. null
  3. >

挖矿过程中,切换到节点终端,你会发现一直在挖矿。

d1afaed768f585a2.gif 挖矿

如果你觉得差不多了,可以运行下面的命令停止挖矿。

  1. miner.stop();

9. 停止挖矿,并且查余额

  1. > miner.start();
  2. null
  3. > miner.stop();
  4. true
  5. > web3.eth.getBalance(account1)
  6. 1.152e+21
  7. >

10. 解锁coinbase账号,我们通过coinbase账号来付费部署合约

liyuechun: 换成你的密码。

  1. > personal.unlockAccount(account1, 'liyuechun')
  2. true
  3. >

11. 预估手续费

  1. > bytecode = "6060604052341561000f57600080fd5b5b60ab8061001e6000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063c6888fa114603d575b600080fd5b3415604757600080fd5b605b60048080359060200190919050506071565b6040518082815260200191505060405180910390f35b60006007820290505b9190505600a165627a7a7230582067d7c851e14e862886b6f53dad6825135557fb3a4b691350c94ea5b80605f6770029"
  2. "6060604052341561000f57600080fd5b5b60ab8061001e6000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063c6888fa114603d575b600080fd5b3415604757600080fd5b605b60048080359060200190919050506071565b6040518082815260200191505060405180910390f35b60006007820290505b9190505600a165627a7a7230582067d7c851e14e862886b6f53dad6825135557fb3a4b691350c94ea5b80605f6770029"
  3. > web3.eth.estimateGas({data: bytecode})
  4. Error: invalid argument 0: json: cannot unmarshal hex string without 0x prefix into Go struct field CallArgs.data of type hexutil.Bytes
  5. at web3.js:3104:20
  6. at web3.js:6191:15
  7. at web3.js:5004:36
  8. at <anonymous>:1:1
  9. > bytecode = "0x6060604052341561000f57600080fd5b5b60ab8061001e6000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063c6888fa114603d575b600080fd5b3415604757600080fd5b605b60048080359060200190919050506071565b6040518082815260200191505060405180910390f35b60006007820290505b9190505600a165627a7a7230582067d7c851e14e862886b6f53dad6825135557fb3a4b691350c94ea5b80605f6770029"
  10. "0x6060604052341561000f57600080fd5b5b60ab8061001e6000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063c6888fa114603d575b600080fd5b3415604757600080fd5b605b60048080359060200190919050506071565b6040518082815260200191505060405180910390f35b60006007820290505b9190505600a165627a7a7230582067d7c851e14e862886b6f53dad6825135557fb3a4b691350c94ea5b80605f6770029"
  11. > web3.eth.estimateGas({data: bytecode})
  12. 98391
  13. >

备注:字节码前面需要添加0x。手续费大概为98391``gas

12. 部署合约,为了方便理解,设置一个回调函数

  1. > contractInstance = contract.new({data: bytecode, gas: 1000000, from: account1}, function(e, contract){
  2. if(!e){
  3. if(!contract.address){
  4. console.log("Contract transaction send: Transaction Hash: "+contract.transactionHash+" waiting to be mined...");
  5. }else{
  6. console.log("Contract mined! Address: "+contract.address);
  7. console.log(contract);
  8. }
  9. }else{
  10. console.log(e)
  11. }
  12. })
  13. Contract transaction send: Transaction Hash: 0x5e2aebbf400d71a32e807dc3f11f1053b6ee3b2a81435ed8ace2fa54eebb9f3d waiting to be mined...
  14. {
  15. abi: [{
  16. constant: false,
  17. inputs: [{...}],
  18. name: "multiply",
  19. outputs: [{...}],
  20. payable: false,
  21. type: "function"
  22. }],
  23. address: undefined,
  24. transactionHash: "0x5e2aebbf400d71a32e807dc3f11f1053b6ee3b2a81435ed8ace2fa54eebb9f3d"
  25. }
  26. >

13. 你的合约等待挖矿,开始挖矿,等一会儿,停止

  1. > miner.start()
  2. null
  3. > Contract mined! Address: 0xbf8b24283f2516360d3a4ba1db0df78ae74689db
  4. [object Object]
  5. > miner.stop()
  6. true
  7. >

d92f2aba95a72198.png image

14. 检查合约是否部署成功

  1. > eth.getCode(contractInstance.address)
  2. "0x60606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063c6888fa114603d575b600080fd5b3415604757600080fd5b605b60048080359060200190919050506071565b6040518082815260200191505060405180910390f35b60006007820290505b9190505600a165627a7a7230582067d7c851e14e862886b6f53dad6825135557fb3a4b691350c94ea5b80605f6770029"
  3. >

15. 调用合约方法

  1. > contractInstance.multiply(6)
  2. 42
  3. >

PS: 这里添加call的原因是因为multiply函数没有添加constant

  1. pragma solidity ^0.4.4;
  2. contract test {
  3. function multiply(uint a) returns(uint d){
  4. return a * 7;
  5. }
  6. }

Over Game!!!!

转载于:https://www.cnblogs.com/lvdongjie/p/11207406.html

发表评论

表情:
评论列表 (有 0 条评论,429人围观)

还没有评论,来说两句吧...

相关阅读

    相关 智能合约 简介

    以太坊是一个分布式的计算平台。它会生成一个名为Ether的加密货币。程序员可以在以太坊区块链上写下“智能合约”,这些以太坊智能合约会根据代码自动执行。 以太坊是什么?