区块链学习(2) 智能合约部署到以太坊私有链并交互(mac版)

创建私有链

私有链的创建在上一篇文章有提到,请直接戳这里.

合约代码编写

合约代码是用的solidity语言写的。solidity语言跟java语言类似,所以会java的来写solidity,还是很方便的。这里我把solidity英文官网和中文文档都列出来了,然后找了一个例子直接拿来用了,一个简单的乘法。有更多需求的请自行查阅文档。
新建一个文件test.sol,在文件中如下编写:

pragma solidity ^0.4.0;
contract test {
   /// @notice Will multiply `a` by 7.
   function multiply(uint a) returns(uint d) {
       return a * 7;
   }
}

合约代码的编译

编译问题搞了很久,网上有说用solc --bin test.sol,暂时还不知道生成二进制码后怎么玩。也有说将test.sol文件中代码压缩(即将换行符和空格去掉),生成一串字符串source,然后在eth环境中调用eth.complie.solidity(source),但geth从1.6版本之后就将此命令删除了,所以会报

Error: The method eth_compileSolidity does not exist/is not available
    at web3.js:3143:20
    at web3.js:6347:15
    at web3.js:5081:36
    at :1:1

我现在的做法是,使用Remix在线工具编译。具体做法是:
1. 在浏览器中打开Remix工具,网址为:http://remix.ethereum.org/;
2. 点击左上角+,新生成一个文件test.sol;
3. 将之前在本地写的test.sol中的代码拷贝到此文件中,如图所示
区块链学习(2) 智能合约部署到以太坊私有链并交互(mac版)_第1张图片
4. 点击compile -> start to compile,下面会有一些警告,不用管它,然后点击Details按钮,拷贝json数据
区块链学习(2) 智能合约部署到以太坊私有链并交互(mac版)_第2张图片
json数据形式如下:

[{"constant":false,"inputs":[],"name":"getStr","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"a","type":"uint256"}],"name":"multiply","outputs":[{"name":"d","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"}]

此json格式的东东就是我们编译后的数据了。

部署合约代码到私有链

注意:在这一步之前,一定要创建私有链,并且假设你已经进入到Geth JS控制台了。
具体部署过程如下:

获取bin信息,即上述获取的json格式的数据
> abi = [{"constant":false,"inputs":[],"name":"getStr","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"a","type":"uint256"}],"name":"multiply","outputs":[{"name":"d","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"}]
[{
    constant: false,
    inputs: [],
    name: "getStr",
    outputs: [{
        name: "",
        type: "string"
    }],
    payable: false,
    stateMutability: "nonpayable",
    type: "function"
}, {
    constant: false,
    inputs: [{
        name: "a",
        type: "uint256"
    }],
    name: "multiply",
    outputs: [{
        name: "d",
        type: "uint256"
    }],
    payable: false,
    stateMutability: "nonpayable",
    type: "function"
}]
//创建合约。
> multiplyContract = eth.contract(abi)
{
  abi: [{
      constant: false,
      inputs: [],
      name: "getStr",
      outputs: [{...}],
      payable: false,
      stateMutability: "nonpayable",
      type: "function"
  }, {
      constant: false,
      inputs: [{...}],
      name: "multiply",
      outputs: [{...}],
      payable: false,
      stateMutability: "nonpayable",
      type: "function"
  }],
  eth: {
    accounts: ["0x099dc8286e3a6239e414a9faf0e478204ace0f67", "0x4568984f7c13b5f0f22c1f05a1b958375aa3996d"],
    blockNumber: 58,
    coinbase: "0x099dc8286e3a6239e414a9faf0e478204ace0f67",
    compile: {
      lll: function(),
      serpent: function(),
      solidity: function()
    },
    defaultAccount: undefined,
    defaultBlock: "latest",
    gasPrice: 18000000000,
    hashrate: 0,
    mining: false,
    pendingTransactions: [],
    protocolVersion: "0x3f",
    syncing: false,
    call: function(),
    contract: function(abi),
    estimateGas: function(),
    filter: function(options, callback, filterCreationErrorCallback),
    getAccounts: function(callback),
    getBalance: function(),
    getBlock: function(),
    getBlockNumber: function(callback),
    getBlockTransactionCount: function(),
    getBlockUncleCount: function(),
    getCode: function(),
    getCoinbase: function(callback),
    getCompilers: function(),
    getGasPrice: function(callback),
    getHashrate: function(callback),
    getMining: function(callback),
    getPendingTransactions: function(callback),
    getProtocolVersion: function(callback),
    getRawTransaction: function(),
    getRawTransactionFromBlock: function(),
    getStorageAt: function(),
    getSyncing: function(callback),
    getTransaction: function(),
    getTransactionCount: function(),
    getTransactionFromBlock: function(),
    getTransactionReceipt: function(),
    getUncle: function(),
    getWork: function(),
    iban: function(iban),
    icapNamereg: function(),
    isSyncing: function(callback),
    namereg: function(),
    resend: function(),
    sendIBANTransaction: function(),
    sendRawTransaction: function(),
    sendTransaction: function(),
    sign: function(),
    signTransaction: function(),
    submitTransaction: function(),
    submitWork: function()
  },
  at: function(address, callback),
  getData: function(),
  new: function()
}
//解锁账户
> personal.unlockAccount(eth.accounts[0])
Unlock account 0x099dc8286e3a6239e414a9faf0e478204ace0f67
Passphrase: 
true
//部署合约。data为上述编译得到的数据,在下面截图可以看到
> multiply = multiplyContract.new({from:eth.coinbase,data:"0x6060604052341561000f57600080fd5b6101a68061001e6000396000f30060606040526004361061004c576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063b8c9e4ed14610051578063c6888fa1146100df575b600080fd5b341561005c57600080fd5b610064610116565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100a4578082015181840152602081019050610089565b50505050905090810190601f1680156100d15780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156100ea57600080fd5b6101006004808035906020019091905050610159565b6040518082815260200191505060405180910390f35b61011e610166565b6040805190810160405280600781526020017f77656970696e6700000000000000000000000000000000000000000000000000815250905090565b6000600782029050919050565b6020604051908101604052806000815250905600a165627a7a72305820b115e32f8a7d822f631e49ec067bd3ca718ea68acf864b7bff16afdfd32737f60029"})
INFO [03-09|17:06:17] Submitted contract creation              fullhash=0x2caf080fff22adde98e0a4b220600740a76711edde8cf15a772262cf01592744 contract=0x800e7b3e2D9173E6645D2367075a19482cC1d87b
{
  abi: [{
      constant: false,
      inputs: [],
      name: "getStr",
      outputs: [{...}],
      payable: false,
      stateMutability: "nonpayable",
      type: "function"
  }, {
      constant: false,
      inputs: [{...}],
      name: "multiply",
      outputs: [{...}],
      payable: false,
      stateMutability: "nonpayable",
      type: "function"
  }],
  address: undefined,
  transactionHash: "0x2caf080fff22adde98e0a4b220600740a76711edde8cf15a772262cf01592744"
}
//我们知道部署合约的过程实际也是由创建合约的账户发送的一笔交易(即eth.coinbase账户)。需要挖矿进行确认。
> miner.start();admin.sleepBlocks(1);miner.stop();
true

区块链学习(2) 智能合约部署到以太坊私有链并交互(mac版)_第3张图片
至此合约已经存在于区块链中,可以查看区块信息获取合约的地址和交易hash。

与合约交互

//获取合约对象
> MyContract = eth.contract(abi)
{
  abi: [{
      constant: false,
      inputs: [],
      name: "getStr",
      outputs: [{...}],
      payable: false,
      stateMutability: "nonpayable",
      type: "function"
  }, {
      constant: false,
      inputs: [{...}],
      name: "multiply",
      outputs: [{...}],
      payable: false,
      stateMutability: "nonpayable",
      type: "function"
  }],
  eth: {
    accounts: ["0x099dc8286e3a6239e414a9faf0e478204ace0f67", "0x4568984f7c13b5f0f22c1f05a1b958375aa3996d"],
    blockNumber: 60,
    coinbase: "0x099dc8286e3a6239e414a9faf0e478204ace0f67",
    compile: {
      lll: function(),
      serpent: function(),
      solidity: function()
    },
    defaultAccount: undefined,
    defaultBlock: "latest",
    gasPrice: 18000000000,
    hashrate: 0,
    mining: false,
    pendingTransactions: [],
    protocolVersion: "0x3f",
    syncing: false,
    call: function(),
    contract: function(abi),
    estimateGas: function(),
    filter: function(options, callback, filterCreationErrorCallback),
    getAccounts: function(callback),
    getBalance: function(),
    getBlock: function(),
    getBlockNumber: function(callback),
    getBlockTransactionCount: function(),
    getBlockUncleCount: function(),
    getCode: function(),
    getCoinbase: function(callback),
    getCompilers: function(),
    getGasPrice: function(callback),
    getHashrate: function(callback),
    getMining: function(callback),
    getPendingTransactions: function(callback),
    getProtocolVersion: function(callback),
    getRawTransaction: function(),
    getRawTransactionFromBlock: function(),
    getStorageAt: function(),
    getSyncing: function(callback),
    getTransaction: function(),
    getTransactionCount: function(),
    getTransactionFromBlock: function(),
    getTransactionReceipt: function(),
    getUncle: function(),
    getWork: function(),
    iban: function(iban),
    icapNamereg: function(),
    isSyncing: function(callback),
    namereg: function(),
    resend: function(),
    sendIBANTransaction: function(),
    sendRawTransaction: function(),
    sendTransaction: function(),
    sign: function(),
    signTransaction: function(),
    submitTransaction: function(),
    submitWork: function()
  },
  at: function(address, callback),
  getData: function(),
  new: function()
}
//实例化合约
> myContract = MyContract.at(multiply.address)
{
  abi: [{
      constant: false,
      inputs: [],
      name: "getStr",
      outputs: [{...}],
      payable: false,
      stateMutability: "nonpayable",
      type: "function"
  }, {
      constant: false,
      inputs: [{...}],
      name: "multiply",
      outputs: [{...}],
      payable: false,
      stateMutability: "nonpayable",
      type: "function"
  }],
  address: undefined,
  transactionHash: null,
  allEvents: function(),
  getStr: function(),
  multiply: function()
}
//调用合约
> myContract.multiply.call(5)
35

这里有一个小问题,我在调用myContract.multiply.call(5)方式时,有时候输出为0,而不是正确的值,还没找到具体原因,有点蛋疼。后面找到原因了我再补上,或者有童鞋发现原因了也可以提一下。

参考文章:
http://blog.csdn.net/Blossomps/article/details/59542586

你可能感兴趣的:(区块链)