咸鱼

咸鱼是以盐腌渍后,晒干的鱼

0%

1.2、基于Geth部署合约

智能合约,我理解它就是程序机器码,可以在区块链上执行的代码,好比 C语言的*.o 文件,Java的 *.class 文件。

  1. 启动 私有链,我们的程序(合约)就跑在这条私有链上。

    1
    $ geth --datadir data0 --networkid 1108 --nodiscover console
  2. 查看挖矿账户

    1
    2
    > web3.eth.coinbase 
    "0x5400ca57071e4d804e1d5f7c14f63a70fa90d541"
  3. 编写solidity代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    pragma solidity ^0.4.0;

    contract HelloWorld {

    function test(uint a) constant returns(uint d){

    return a * 8;
    }
    }
  4. 编译为字节码和abi

    在线编译compile - Start To compile -> Details

    bytecode 只要 object 的值,abi 全部拷贝。

    注:Details -> web3Deploy有部署的示例,但我们自己手动来一遍。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    # bytecode
    6060604052341561000f57600080fd5b60b98061001d6000396000f300606060405260043610603f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806329e99f07146044575b600080fd5b3415604e57600080fd5b606a600480360381019080803590602001909291905050506080565b6040518082815260200191505060405180910390f35b60006008820290509190505600a165627a7a7230582079ee88ca1fe7e781407b09bc2c5497dcabc538d6930265a54386d2b71b0cd7510029

    # abi
    [
    {
    "constant": true,
    "inputs": [
    {
    "name": "a",
    "type": "uint256"
    }
    ],
    "name": "test",
    "outputs": [
    {
    "name": "d",
    "type": "uint256"
    }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
    }
    ]
    # abi转义
    [{\"constant\":true,\"inputs\":[{\"name\":\"a\",\"type\":\"uint256\"}],\"name\":\"test\",\"outputs\":[{\"name\":\"d\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}]
  5. 创建合约对象

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    # 赋值为本地变量。
    # 因为是十六进制,加上 0x 赋值给 bytecode
    >
    > bytecode = '0x6060604052341561000f57600080fd5b60b98061001d6000396000f300606060405260043610603f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806329e99f07146044575b600080fd5b3415604e57600080fd5b606a600480360381019080803590602001909291905050506080565b6040518082815260200191505060405180910390f35b60006008820290509190505600a165627a7a7230582079ee88ca1fe7e781407b09bc2c5497dcabc538d6930265a54386d2b71b0cd7510029'
    >
    # abi要解析为对象。
    > var abi = JSON.parse('[{\"constant\":true,\"inputs\":[{\"name\":\"a\",\"type\":\"uint256\"}],\"name\":\"test\",\"outputs\":[{\"name\":\"d\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}]')
    >
    > var helloWorldContract = web3.eth.contract(abi)
    undefined
  6. 预估部署合约的手续费

    1
    2
    3
    4
    5
    6
    > eth.estimateGas({data: bytecode})
    102074
    # 查看余额,如果账户的余额不够,先挖矿。
    > account1 = web3.eth.coinbase
    > web3.eth.getBalance(account1)
    600000000000000000000
  7. 部署

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    # 解锁
    > personal.unlockAccount(account1, '123456')
    true
    # 部署,gas 是手续费
    > var helloWorldContractInstance = helloWorldContract.new({data: bytecode ,gas: 2000000, from: account1})
    # 或者带上一个回调函数function,用于打印日志
    > var helloWorldContractInstance = helloWorldContract.new(
    {
    data: bytecode,
    gas: 2000000,
    from: account1
    }, function (e, contract){
    console.log(e, contract);
    if (typeof contract.address !== 'undefined') {
    console.log('Contract mined! address: ' + contract.address + ' transactionHash: ' + contract.transactionHash);
    }
    })

    # log看到,合约已经创建
    INFO [03-30|20:50:12] Submitted contract creation fullhash=0x583c5c0e6f8c2225cd8411b1ba0a58304505aea929d6c9cd1c0773c952657416 contract=0x05E4898E94785523c6C5AcBa4324B529B5197Bcf
    null [object Object]
    undefined
  8. 合约等待挖矿,开始挖矿

    合约需要有节点在挖矿才能部署成功,所以我们先启动挖矿。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    > miner.start()
    INFO [03-30|20:51:30] Updated mining threads threads=0
    INFO [03-30|20:51:30] Transaction pool price threshold updated price=18000000000
    null
    # 这里等待一会
    > INFO [03-30|20:51:30] Starting mining operation
    INFO [03-30|20:51:30] Commit new mining work number=195 txs=1 uncles=0 elapsed=998.832µs
    INFO [03-30|20:51:46] Successfully sealed new block number=195 hash=d60b89…65bffe
    INFO [03-30|20:51:46] 🔗 block reached canonical chain number=190 hash=4159ba…196761
    INFO [03-30|20:51:46] 🔨 mined potential block number=195 hash=d60b89…65bffe
    INFO [03-30|20:51:46] Commit new mining work number=196 txs=0 uncles=0 elapsed=7.087ms
    null [object Object]
    Contract mined! address: 0x05e4898e94785523c6c5acba4324b529b5197bcf transactionHash: 0x583c5c0e6f8c2225cd8411b1ba0a58304505aea929d6c9cd1c0773c952657416
    INFO [03-30|20:51:55] Successfully sealed new block number=196 hash=f6a947…15b0a4
    INFO [03-30|20:51:55] 🔗 block reached canonical chain number=191 hash=c95b93…bdd2a6
    INFO [03-30|20:51:55] 🔨 mined potential block number=196 hash=f6a947…15b0a4
    INFO [03-30|20:51:55] Commit new mining work number=197 txs=0 uncles=0 elapsed=2.289ms
    # 只要挖矿成功了,就可以停止了
    > miner.stop()
    true
  9. 检查部署结果和调用合约方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    > helloWorldContractInstance.address
    "0x05e4898e94785523c6c5acba4324b529b5197bcf"
    >
    > eth.getCode(helloWorldContractInstance.address)
    "0x606060405260043610603f576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806329e99f07146044575b600080fd5b3415604e57600080fd5b606a600480360381019080803590602001909291905050506080565b6040518082815260200191505060405180910390f35b60006008820290509190505600a165627a7a7230582079ee88ca1fe7e781407b09bc2c5497dcabc538d6930265a54386d2b71b0cd7510029"
    >
    >
    > helloWorldContractInstance.test(4)
    32
  10. OK