スマートコントラクト開発でHello Worldをする（ethereum6）


前回はこちら。[スマートコントラクト開発の準備をする](http://qiita.com/joji/items/325b8f6a21574a715c56 "スマートコントラクト開発の準備をする")

```bash
vi HelloWorldOrg.sol 
```

```solidity:HelloWorldOrg.sol
pragma solidity ^0.4.8;

contract HelloWorld {
    string public greeting;

    function HelloWorld(string _greeting){
        greeting = _greeting;
    }

    function setGreeting(string _greeting){
        greeting = _greeting;
    }

    function say() constant returns (string) {
        return greeting;
    }
}
```

改行文字を削除

```bash
cat HelloWorldOrg.sol | tr -d '\n' > HelloWorld.sol
```

文字列を出力

```bash
cat HelloWorld.sol
```

中身

```
pragma solidity ^0.4.8;contract HelloWorld {    string public greeting;        function HelloWorld(string _greeting){        greeting = _greeting;    }        function setGreeting(string _greeting){        greeting = _greeting;    }        function say() constant returns (string) {        return greeting;    }}
```

コンソール接続

```bash
geth attach rpc:http://localhost:8545
```

変数に上記の文字列を代入

```geth_console
source = 'pragma solidity ^0.4.8;contract HelloWorld {    string public greeting;        function HelloWorld(string _greeting){        greeting = _greeting;    }        function setGreeting(string _greeting){        greeting = _greeting;    }        function say() constant returns (string) {        return greeting;    }}'
```

コンパイル

```geth_console
sourceCompiled = eth.compile.solidity(source)
```

```shell-session
{
  /tmp/geth-compile-solidity839881623:HelloWorld: {
    code: "0x6060604052341561000f57600080fd5b60405161046d38038061046d833981016040528080519091019050600081805161003d929160200190610044565b50506100df565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061008557805160ff19168380011785556100b2565b828001600101855582156100b2579182015b828111156100b2578251825591602001919060010190610097565b506100be9291506100c2565b5090565b6100dc91905b808211156100be57600081556001016100c8565b90565b61037f806100ee6000396000f3006060604052600436106100565763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663954ab4b2811461005b578063a4136862146100e5578063ef690cc014610138575b600080fd5b341561006657600080fd5b61006e61014b565b60405160208082528190810183818151815260200191508051906020019080838360005b838110156100aa578082015183820152602001610092565b50505050905090810190601f1680156100d75780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156100f057600080fd5b61013660046024813581810190830135806020601f820181900481020160405190810160405281815292919060208401838380828437509496506101f495505050505050565b005b341561014357600080fd5b61006e61020b565b6101536102a9565b60008054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156101e95780601f106101be576101008083540402835291602001916101e9565b820191906000526020600020905b8154815290600101906020018083116101cc57829003601f168201915b505050505090505b90565b60008180516102079291602001906102bb565b5050565b60008054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156102a15780601f10610276576101008083540402835291602001916102a1565b820191906000526020600020905b81548152906001019060200180831161028457829003601f168201915b505050505081565b60206040519081016040526000815290565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106102fc57805160ff1916838001178555610329565b82800160010185558215610329579182015b8281111561032957825182559160200191906001019061030e565b50610335929150610339565b5090565b6101f191905b80821115610335576000815560010161033f5600a165627a7a72305820a8a39c563d28ad8d0cb151c7ca5fbc4ff88df5a87dff2369b516cc7c32cfac080029",
    info: {
      abiDefinition: [{...}, {...}, {...}, {...}],
      compilerOptions: "--combined-json bin,abi,userdoc,devdoc --add-std --optimize",
      compilerVersion: "0.4.19",
      developerDoc: {
        methods: {}
      },
      language: "Solidity",
      languageVersion: "0.4.19",
      source: "pragma solidity ^0.4.8;contract HelloWorld {    string public greeting;        function HelloWorld(string _greeting){        greeting = _greeting;    }        function setGreeting(string _greeting){        greeting = _greeting;    }        function say() constant returns (string) {        return greeting;    }}",
      userDoc: {
        methods: {}
      }
    }
  }
}
```

sourceCompiledから、ABI(Application Binary Interface)を取得します。ABIとは、コントラクトの外部仕様のことです。コントラクトに含まれるメソッドと引数、戻り値についての情報で、コントラクトにアクセスする際に必要な情報のひとつです

```geth_console
contractAbiDefinition = sourceCompiled['/tmp/geth-compile-solidity839881623:HelloWorld'].info.abiDefinition
```

```shell-session
[{
    constant: true,
    inputs: [],
    name: "say",
    outputs: [{
        name: "",
        type: "string"
    }],
    payable: false,
    stateMutability: "view",
    type: "function"
}, {
    constant: false,
    inputs: [{
        name: "_greeting",
        type: "string"
    }],
    name: "setGreeting",
    outputs: [],
    payable: false,
    stateMutability: "nonpayable",
    type: "function"
}, {
    constant: true,
    inputs: [],
    name: "greeting",
    outputs: [{
        name: "",
        type: "string"
    }],
    payable: false,
    stateMutability: "view",
    type: "function"
}, {
    inputs: [{
        name: "_greeting",
        type: "string"
    }],
    payable: false,
    stateMutability: "nonpayable",
    type: "constructor"
}]
```

コントラクトオブジェクトを作成

```geth_console
sourceCompiledContract = eth.contract(contractAbiDefinition)
```

```shell-session
{
  abi: [{
      constant: true,
      inputs: [],
      name: "say",
      outputs: [{...}],
      payable: false,
      stateMutability: "view",
      type: "function"
  }, {
      constant: false,
      inputs: [{...}],
      name: "setGreeting",
      outputs: [],
      payable: false,
      stateMutability: "nonpayable",
      type: "function"
  }, {
      constant: true,
      inputs: [],
      name: "greeting",
      outputs: [{...}],
      payable: false,
      stateMutability: "view",
      type: "function"
  }, {
      inputs: [{...}],
      payable: false,
      stateMutability: "nonpayable",
      type: "constructor"
  }],
  eth: {
    accounts: ["0x127a0614d4f606460f3cb7e05f1b9f79fdf9191b", "0x32a39ca8fd074a9c1e49b77b6613ca5287592305", "0x3b1a887c19bd3e39e926121db232f9376f2aebed", "0xe2a98f7bfc8c08fffc8fdfbabc74e80a9ccb0c6f", "0xa7732a8a03be095a4c51dd1174e1dc531b67751b", "0x215f7b161e8708280ab8d31243045b9f3c442855", "0x165df023f3371858c1bd6fe27d6724a5f9ac5ab8"],
    blockNumber: 18119,
    coinbase: "0x127a0614d4f606460f3cb7e05f1b9f79fdf9191b",
    compile: {
      lll: function(),
      serpent: function(),
      solidity: function()
    },
    defaultAccount: undefined,
    defaultBlock: "latest",
    gasPrice: 20000000000,
    hashrate: 68704,
    mining: true,
    pendingTransactions: [],
    syncing: false,
    call: function(),
    contract: function(abi),
    estimateGas: function(),
    filter: function(fil, callback),
    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),
    getNatSpec: function(),
    getPendingTransactions: 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()
}
```

変数に代入

```geth_console
 _greeting = "Hello, World 2017/12/28"
```

```geth_console
personal.unlockAccount(eth.accounts[0])
```

newは、ブロックチェーン上へ新しくコントラクトをデプロイするための命令です。

```geth_console
contract = sourceCompiledContract.new(_greeting, {from:eth.accounts[0], data: sourceCompiled['/tmp/geth-compile-solidity839881623:HelloWorld'].code, gas: '4700000'})
```

```shell-session
{
  abi: [{
      constant: true,
      inputs: [],
      name: "say",
      outputs: [{...}],
      payable: false,
      stateMutability: "view",
      type: "function"
  }, {
      constant: false,
      inputs: [{...}],
      name: "setGreeting",
      outputs: [],
      payable: false,
      stateMutability: "nonpayable",
      type: "function"
  }, {
      constant: true,
      inputs: [],
      name: "greeting",
      outputs: [{...}],
      payable: false,
      stateMutability: "view",
      type: "function"
  }, {
      inputs: [{...}],
      payable: false,
      stateMutability: "nonpayable",
      type: "constructor"
  }],
  address: undefined,
  transactionHash: "0xcc42962aef10a99eb4694f429ac48e6d9f34d22d5a85013172c0b8fe66231c17"
}
```

new直後はまだブロックに書き込まれていないため、address はundefinedになります。マイニングされるのを待ち、contractを確認します。

確認する

```geth_console
contract
```

アドレスが書き込まれています。

```shell-session
address: "0x43d59369f150532271629fbe4874cd3db353ad06"
```

メソッドを実行します。

```geth_console
contract.say.call()
```

```shell-session
"Hello, World 2017/12/28"
```

メソッドの実行方法には２つあります。

|メソッド名|説明|
|:-----------|:------------|
|sendTransaction|ブロックチェーンの状態を変化させるときに使用します。ここで「状態を変化させる」とは、新しくデー タを書き込んだり、既に存在するデータを更新することを指します。これらは、ブロックチェーンのブロックを作成することで実現されるため、手数料(Gas)が発生します。ここでsendTransactionは、Etherの送金でも使用しました。Etherの送金も、残高(=状態)を変化させたと考えてください。|
|call|ブロックチェーンからデータを取得するときに使用します。ブロックの作成は必要ありませんので、手数料は発生しません。例えば、残高の取得メソッドなどで使用します。残高は、既に存在するデータから求められますので、新たにデータを書き込む必要はありません。|


```geth_console
personal.unlockAccount(eth.accounts[0])
```


```geth_console
contract.setGreeting.sendTransaction("Hello, Ethereum!", {from:eth. accounts[0], gas:1000000})
```

contract.setGreeting.sendTransaction("Hello, Ethereum!", {from:eth. accounts[0], gas:1000000})

```geth_console
"0xe53164fcfd0d04b429f3253b5407474574980b3dbd3f4f4f5d279459e1ac4f33"
```

マイニングをしばらく待つ必要があります。しばらくは、以前のままですが、途中で変わりました。

```geth_console
> contract.say.call()
"Hello, World 2017/12/28"
> contract.say.call()
"Hello, World 2017/12/28"
> contract.say.call()
"Hello, World 2017/12/28"
> contract.say.call()
"Hello, Ethereum!"
```

###既存のコントラクトにアクセスしてみます。

別ターミナルを立ち上げます。

```bash
geth attach rpc:http://localhost:8545
```

```bash
source = 'pragma solidity ^0.4.8;contract HelloWorld {    string public greeting;        function HelloWorld(string _greeting){        greeting = _greeting;    }        function setGreeting(string _greeting){        greeting = _greeting;    }        function say() constant returns (string) {        return greeting;    }}'
```

```geth_console
sourceCompiled = eth.compile.solidity(source)
```

```geth_console
contractAbiDefinition = sourceCompiled['/tmp/geth-compile-solidity707514890:HelloWorld'].info.abiDefinition
```

上記のアドレスをアタッチ

```geth_console
contract = eth.contract(contractAbiDefinition).at("0x43d59369f150532271629fbe4874cd3db353ad06")
```

```geth_console
contract.say.call()
```

```shell-session
> contract.say.call()
"Hello, World 2017/12/28"
> contract.say.call()
"Hello, World 2017/12/28"
> contract.say.call()
"Hello, World 2017/12/28"
> contract.say.call()
"Hello, Ethereum!"
```