前回はこちら。スマートコントラクト開発の準備をする
vi HelloWorldOrg.sol
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;
}
}
改行文字を削除
cat HelloWorldOrg.sol | tr -d '\n' > HelloWorld.sol
文字列を出力
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; }}
コンソール接続
geth attach rpc:http://localhost:8545
変数に上記の文字列を代入
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; }}'
コンパイル
sourceCompiled = eth.compile.solidity(source)
{
/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とは、コントラクトの外部仕様のことです。コントラクトに含まれるメソッドと引数、戻り値についての情報で、コントラクトにアクセスする際に必要な情報のひとつです
contractAbiDefinition = sourceCompiled['/tmp/geth-compile-solidity839881623:HelloWorld'].info.abiDefinition
[{
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"
}]
コントラクトオブジェクトを作成
sourceCompiledContract = eth.contract(contractAbiDefinition)
{
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()
}
変数に代入
_greeting = "Hello, World 2017/12/28"
personal.unlockAccount(eth.accounts[0])
newは、ブロックチェーン上へ新しくコントラクトをデプロイするための命令です。
contract = sourceCompiledContract.new(_greeting, {from:eth.accounts[0], data: sourceCompiled['/tmp/geth-compile-solidity839881623:HelloWorld'].code, gas: '4700000'})
{
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を確認します。
確認する
contract
アドレスが書き込まれています。
address: "0x43d59369f150532271629fbe4874cd3db353ad06"
メソッドを実行します。
contract.say.call()
"Hello, World 2017/12/28"
メソッドの実行方法には2つあります。
メソッド名 | 説明 |
---|---|
sendTransaction | ブロックチェーンの状態を変化させるときに使用します。ここで「状態を変化させる」とは、新しくデー タを書き込んだり、既に存在するデータを更新することを指します。これらは、ブロックチェーンのブロックを作成することで実現されるため、手数料(Gas)が発生します。ここでsendTransactionは、Etherの送金でも使用しました。Etherの送金も、残高(=状態)を変化させたと考えてください。 |
call | ブロックチェーンからデータを取得するときに使用します。ブロックの作成は必要ありませんので、手数料は発生しません。例えば、残高の取得メソッドなどで使用します。残高は、既に存在するデータから求められますので、新たにデータを書き込む必要はありません。 |
personal.unlockAccount(eth.accounts[0])
contract.setGreeting.sendTransaction("Hello, Ethereum!", {from:eth. accounts[0], gas:1000000})
contract.setGreeting.sendTransaction("Hello, Ethereum!", {from:eth. accounts[0], gas:1000000})
"0xe53164fcfd0d04b429f3253b5407474574980b3dbd3f4f4f5d279459e1ac4f33"
マイニングをしばらく待つ必要があります。しばらくは、以前のままですが、途中で変わりました。
> 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!"
既存のコントラクトにアクセスしてみます。
別ターミナルを立ち上げます。
geth attach rpc:http://localhost:8545
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; }}'
sourceCompiled = eth.compile.solidity(source)
contractAbiDefinition = sourceCompiled['/tmp/geth-compile-solidity707514890:HelloWorld'].info.abiDefinition
上記のアドレスをアタッチ
contract = eth.contract(contractAbiDefinition).at("0x43d59369f150532271629fbe4874cd3db353ad06")
contract.say.call()
> 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!"