以太坊智能合约的创建和部署

以太坊智能合约 jason 2046℃ 1评论

上篇文章讲到了源码安装go-ethereum,下面我们将智能合约的创建和部署
1 创建test文件夹,同时在test下新建我们的创世区块文件genesis.json

$ pwd
/usr/local/geth
$ sudo mkdir test
$ cd test
$ sudo vim genesis.json

2 genesis.json的内容

{
  "config": {
        "chainId": 10,
        "homesteadBlock": 0,
        "eip155Block": 0,
        "eip158Block": 0
    },
  "coinbase"   : "0x0000000000000000000000000000000000000000",
  "difficulty" : "0x20000",
  "extraData"  : "",
  "gasLimit"   : "0x8000000",
  "nonce"      : "0x0000000000000042",
  "mixhash"    : "0x0000000000000000000000000000000000000000000000000000000000000000",
  "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000",
  "timestamp"  : "0x00",
  "alloc": {}
}

3 初始化创世区块

$ sudo /home/jason/go/src/github.com/ethereum/go-ethereum/build/bin/geth init ./genesis.json --datadir "./chain"

WARN [11-07|10:17:11] No etherbase set and no accounts found as default
INFO [11-07|10:17:11] Allocated cache and file handles         database=/Users/lion/my_project/_eth/test_truffle_geth/chain/geth/chaindata cache=16 handles=16
INFO [11-07|10:17:11] Writing custom genesis block
INFO [11-07|10:17:11] Successfully wrote genesis state         database=chaindata                                                          hash=ecf271…5269d6
INFO [11-07|10:17:11] Allocated cache and file handles         database=/Users/lion/my_project/_eth/test_truffle_geth/chain/geth/lightchaindata cache=16 handles=16
INFO [11-07|10:17:11] Writing custom genesis block
INFO [11-07|10:17:11] Successfully wrote genesis state         database=lightchaindata                                                          hash=ecf271…5269d6

4 使用 RPC 方式运行 Geth

$ sudo /home/jason/go/src/github.com/ethereum/go-ethereum/build/bin/geth --identity "mshk.top etherum" --rpcaddr 0.0.0.0 --rpc --rpcport 8545 --maxpeers 2 --rpcapi "db,eth,net,web3,debug" --networkid 100 --datadir "./chain" --nodiscover

WARN [11-07|10:21:56] No etherbase set and no accounts found as default
INFO [11-07|10:21:56] Starting peer-to-peer node               instance="Geth/mshk.top etherum/v1.7.2-stable-1db4ecdc/darwin-amd64/go1.9.1"
INFO [11-07|10:21:56] Allocated cache and file handles         database=/Users/lion/my_project/_eth/test_truffle_geth/chain/geth/chaindata cache=128 handles=1024
WARN [11-07|10:21:56] Upgrading database to use lookup entries
INFO [11-07|10:21:56] Initialised chain configuration          config="{ChainID: 10 Homestead: 0 DAO:  DAOSupport: false EIP150:  EIP155: 0 EIP158: 0 Byzantium:  Engine: unknown}"
INFO [11-07|10:21:56] Disk storage enabled for ethash caches   dir=/Users/lion/my_project/_eth/test_truffle_geth/chain/geth/ethash count=3
INFO [11-07|10:21:56] Disk storage enabled for ethash DAGs     dir=/Users/lion/.ethash                                             count=2
INFO [11-07|10:21:56] Initialising Ethereum protocol           versions="[63 62]" network=100
INFO [11-07|10:21:56] Database deduplication successful        deduped=0
INFO [11-07|10:21:56] Loaded most recent local header          number=0 hash=ecf271…5269d6 td=131072
INFO [11-07|10:21:56] Loaded most recent local full block      number=0 hash=ecf271…5269d6 td=131072
INFO [11-07|10:21:56] Loaded most recent local fast block      number=0 hash=ecf271…5269d6 td=131072
INFO [11-07|10:21:56] Regenerated local transaction journal    transactions=0 accounts=0
INFO [11-07|10:21:56] Starting P2P networking
INFO [11-07|10:21:56] RLPx listener up                         self="enode://eee1025474554baf3d42dc72fb6f13df8246b5ed879ca6a7764d3147c422ca2d10eba1dc6a9e609d3535794668d1e064548550683a8c34cfefbcf879b9cbaf2b@[::]:30303?discport=0"
INFO [11-07|10:21:56] IPC endpoint opened: /Users/lion/my_project/_eth/test_truffle_geth/chain/geth.ipc
INFO [11-07|10:21:56] HTTP endpoint opened: http://0.0.0.0:8545
INFO [11-07|10:21:56] Mapped network port                      proto=tcp extport=30303 intport=30303 interface=NAT-PMP(10.0.0.1)

5 rpc方式启动geth以后,会一直停止在那里,没有办法在geth中进行任何输入。
打开新的命令框。
浏览一下我们刚才创建区块链数据的文件夹,会发现有一个geth.ipc文件。

$ ll /usr/local/geth/test/chain
total 0
drwxr-xr-x  7 lion  staff  224 Nov  7 10:21 geth
srw-------  1 lion  staff    0 Nov  7 10:21 geth.ipc
drwx------  2 lion  staff   64 Nov  7 10:17 keystore
然后进入geth 控制台
$ sudo /home/jason/go/src/github.com/ethereum/go-ethereum/build/bin/geth attach ipc://usr/local/geth/test/chain/geth.ipc
Welcome to the Geth JavaScript console!

instance: Geth/mshk.top etherum/v1.8.2-stable-1db4ecdc/darwin-amd64/go1.9.4
modules: admin:1.0 debug:1.0 eth:1.0 miner:1.0 net:1.0 personal:1.0 rpc:1.0 txpool:1.0 web3:1.0
>

6 下面我们创建个账户 开始挖矿

$ web3.personal.newAccount("jason")
"0x95f77e9711d19e69ed57dbae6e92a86901bdc97c"
$ personal.unlockAccount(eth.accounts[0], "jason", 15000)
$ miner.start()
过一会后查看下帐户地址的余额,将帐户地址赋值给变量acc0,可以看到里面有了以太币:
$ acc0 = web3.eth.accounts[0]
"0x95f77e9711d19e69ed57dbae6e92a86901bdc97c"
$ web3.eth.getBalance(acc0)
235000000000000000000

7 进入主题,创建合约,然后部署、编译,最后调用

$ pwd
/usr/local/geth/test/
$ sudo mkdir test_truffle
初始化一个项目 
$ sudo truffle init 

Downloading...
Unpacking...
Setting up...
Unbox successful. Sweet!
Commands:
  Compile:        truffle compile
  Migrate:        truffle migrate
  Test contracts: truffle test

完成后,你将拥有如下目录:
* contracts 智能合约目录
* migrations 发布脚本目录
* test 存放测试文件
* truffle.js Truffle的配置文件

8 创建一个 Hello_World.top 的合约并编译,在contracts目录中新建一个Hello_World_top.sol文件,代码如下:

pragma solidity ^0.4.17;

contract Hello_World_top {

  //say hello jason.top
  function say() public pure returns (string) {
    return "Hello jason.top";
  }

  //print name
  function print(string name) public pure returns (string) {
    return name;
  }
}

9 编辑migrations/1_initial_migration.js部署脚本,将我们刚才创建的Hello_World_top.sol文件设置到发布配置文件中,内容如下:

var Migrations = artifacts.require("./Migrations.sol");
var Hello_World_top = artifacts.require("./Hello_World_top.sol");
module.exports = function(deployer) {
  deployer.deploy(Migrations);
  deployer.deploy(Hello_World_top);
};

10 编译合约 Hello_World_top.sol编译后的文件是./build/contracts/Hello_World_top.json中,后面在部署到geth中,我们会用到。

$ truffle compile
Compiling ./contracts/Hello_World_top.sol...
Compiling ./contracts/Migrations.sol...
Writing artifacts to ./build/contracts

11 部署智能合约

编辑truffle.js配置文件,设置我们稍后要部署智能合约的位置,内容如下:

module.exports = {
    networks: {
        development: {
          host: "localhost",
          port: 8545,
          network_id: "*"
        }
    }
};

接下来执行部署

truffle migrate

这个命令会执行所有migrations目录下的js文件。如果之前执行过truffle migrate命令,再次执行,只会部署新的js文件,如果没有新的js文件,不会起任何作用。如果使用–reset参数,则会重新的执行所有脚本的部署。
如果要部署到指定的网络,可以使用–network参数,例如:

truffle migrate --network live

多个网络的配置格式如下:

networks: {
  development: {
    host: "localhost",
    port: 8545,
    network_id: "*" // match any network
  },
  live: {
    host: "178.25.19.88", // Random IP for example purposes (do not use)
    port: 80,
    network_id: 1,        // Ethereum public network
    // optional config values:
    // gas  Gas limit used for deploys. Default is 4712388
    // gasPrice Gas price used for deploys. Default is 100000000000 (100 Shannon).
    // from - default address to use for any transaction Truffle makes during migrations
    // provider - web3 provider instance Truffle should use to talk to the Ethereum network.
    //          - if specified, host and port are ignored.
  }
}

12 在geth中部署合约

这时,我们就要用到刚刚编译后的Hello_World_top.json文件了,打开https://www.bejson.com网址,把abi部分取出并进行json转义。然后在geth中输入以下内容,将json转义后的内容,赋值给mshk_abi变量:

> mshk_abi=JSON.parse('[{\"constant\":true,\"inputs\":[],\"name\":\"say\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"pure\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"name\",\"type\":\"string\"}],\"name\":\"print\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"pure\",\"type\":\"function\"}]')

会得到下面的返回值:

[{
    constant: true,
    inputs: [{
        name: "name",
        type: "string"
    }],
    name: "print",
    outputs: [{
        name: "",
        type: "string"
    }],
    payable: false,
    stateMutability: "pure",
    type: "function"
}, {
    constant: true,
    inputs: [],
    name: "say",
    outputs: [{
        name: "",
        type: "string"
    }],
    payable: false,
    stateMutability: "pure",
    type: "function"
}]

找到Hello_World_top.json文件中的bytecode部分,然后在geth中,将值赋值给mshk_bytecode变量,在geth中输入以下内容:

mshk_bytecode="0x6060604052341561000f57600080fd5b6102488061001e6000396000f30060606040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806311114af114610051578063954ab4b214610127575b600080fd5b341561005c57600080fd5b6100ac600480803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050919050506101b5565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100ec5780820151818401526020810190506100d1565b50505050905090810190601f1680156101195780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561013257600080fd5b61013a6101c5565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561017a57808201518184015260208101905061015f565b50505050905090810190601f1680156101a75780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6101bd610208565b819050919050565b6101cd610208565b6040805190810160405280600e81526020017f48656c6c6f206d73686b2e746f70000000000000000000000000000000000000815250905090565b6020604051908101604052806000815250905600a165627a7a72305820aa448d81e0f4bf12f805920c9cefd0d3cc6f053d87dd8547663721256179ebcd0029"

评估下创建合约需要的手续费是207296gas:

$ web3.eth.estimateGas({data: mshk_bytecode})
  207296

此时解锁账户 并开启挖矿 进行合约的部署

personal.unlockAccount(eth.accounts[0], "jason", 15000)
miner.start()
mshk_Contract = web3.eth.contract(mshk_abi);
mshk_hello = mshk_Contract.new({from:acc0, data:mshk_bytecode, gas:300000}, function(e, contract){
if(!e) {
       if(!contract.address) {
         console.log("Contract transaction send: TransactionHash: " + contract.transactionHash + " waiting to be mined...");
       } else {
         console.log("Contract mined! Address: " + contract.address);
         console.log(contract);
       }
     }
 });

会看到成功信息

$ Contract mined! Address: 0x1d055281899007cbe6865a48d0a79239dac8e486
[object Object]

13 测试部署的合约

$ mshk_hello.say()
"Hello mshk.top"
$ mshk_hello.print("Hello https://mshk.top")
"Hello https://mshk.top"

转载请注明:Jason博客 » 以太坊智能合约的创建和部署

喜欢 (5)or分享 (0)
发表我的评论
取消评论
表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

记载着一个程序员的编码历程