phpパスワード暗号化「password_hash()、password_verify()」簡易ログインフォーム
こんにちはmiyaです。
しばらくプログラミングの勉強をブログにしていませんでした。
今年はぼちぼち再開していきます。
今年最初のテーマとしてphpの簡易ログイン処理を行っていきます。
大学で使用するウェブサービス(ゼミ生向け)を作成していて、メモとして残したいことを記事としていきます。
今回はパスワードをhash関数で暗号化し、ログインフォームを作成しました。
まずはログイン画面としてhtmlのコードです。
※headerやbody、metaなどのタグは省略します。
セッションをスタートさせておきます。
login.php
<?php session_start(); ?> <html> <h3>LOG IN</h3> <p> <form method="post" action="ref.php"> パスワード:<input type="password" name="passwd" > <input type="submit" name="login"> </form> </p> </html>
次にpassword_hash()を使用して、ハッシュ値を生成します。
今回はphpのインタラクティブモードを使用します。
Macの場合ターミナルから php -aコマンドでインタラクティブモードシェルを有効にします。
password_hash関数では第2引数に利用するアルゴリズムのコストを記述しますが、今回はデフォルトを使います。
>php -a Interactive shell >echo password_hash("ここに暗号化したいパスワード", PASSWORD_DEFAULT); $2y$10$u9TjWGFXHmjp4aw1KLwxO.iWKO3e/2uNXLXqnoMYXOFNNNOn867yK
上記のようにハッシュ値が得られました。忘れずにコピーしておきましょう。
ログイン処理を書いていきます。
事前に成功した場合に表示するページ(success.php)と失敗した場合に表示するページ(error.php)を作成しておきます。
ここではpostを利用してinput.phpから入力されたパスワードを受け取って、パスワードが正しいかチェックし処理を分けていきます。
パスワードの確認のためpassword_verify関数を使用します。
password_verify関数では第1引数に入力されたパスワード、そして第2引数にハッシュ化されたパスワードを記述します。
ref.php
<?php if (strtoupper($_SERVER['REQUEST_METHOD'])=="POST"){ $pass=$_POST['passwd']; if (password_verify($pass, "事前に生成したパスワードのhash値")){ header("Location: http://localhost/success.php"); exit(); } } header("Location: http://localhost/error.php"); ?>
以上です!
今年最初の記事なので軽めにしておきます。
次回はデータベース(Mysql)あたりをいじっていこうかなと思います!。
hashに関する記事も書いていきたいと思います!
最後までありがとうございました!
新年明けましておめでとうございます。今後の方針について。
しばらく更新をサボっていました。。。
今年はもう始まって一週間経ってしまいましたが、今やっていることがひと段落したらまた再開したいと思います。
内容としては、現在PHPを勉強しており、並行して暗号技術を1から勉強しています。
そのことをブログにしていけたらなと思います!
今年もよろしくお願いします。
Truffleフレームワークを利用したサンプル「MetaCoin」実装
こんにちはmiyaです、今回もブロックチェーンの話です。
前回までの記事でブロックチェーンを利用した投票アプリを紹介しましたが、
少し前に公式サンプルとして公開されているMetaCoinを利用してコントラクトを実装する勉強をしました。
※初めての方でもわかりやすいように細かい、難しい箇所は省いています。
今回はその際の手順を忘れないように、メモとしてここに記したいと思います。
参考にしていただけたら嬉しいです。
事前にnpmを利用してtruffleをインストールしておいてください。
コマンドは
npm install -g truffle
それでは早速取り掛かりましょう。
まずは適当にフォルダを作成して移動してください。
mkdir metacoin cd metacoin
次にtruffle unboxコマンドを利用してMetaCoinサンプルをローカル環境に展開します。
truffle unbox metacoin
以下のように展開されます。
contractディレクトリにいくつかsolファイルが展開されます。
まずはMetaCoin.solから見ていきましょう。
pragma solidity ^0.4.18; import "./ConvertLib.sol"; contract MetaCoin { //1 mapping (address => uint) balances; //2 event Transfer(address indexed _from, address indexed _to, uint256 _value); //3 constructor() public { balances[tx.origin] = 10000; } //4 function sendCoin(address receiver, uint amount) public returns(bool sufficient) { if (balances[msg.sender] < amount) return false; balances[msg.sender] -= amount; balances[receiver] += amount; emit Transfer(msg.sender, receiver, amount); return true; } //5 function getBalanceInEth(address addr) public view returns(uint){ return ConvertLib.convert(getBalance(addr),2); } //6 function getBalance(address addr) public view returns(uint) { return balances[addr]; } }
一番初めにsolidityのバージョンをpragmaにより宣言しておきます。
二文目では同ディレクトリにあるConvertLib.solを読み込みます。
//1
最初のmapping型のbalancesは保持しているコインの量を保持します。
keyがaddressとなりvalueがuintとなっています。
この変数はブロックチェーン外のstate treeに保存されます。
//2
event型のTransferは送金に関して記録します。
_to(送信先)、_from(送信元)そして、_value(金額)を記録し、追跡が可能にします。
//3
contract Metacoinが展開されたときに一度だけ実行され初期化を行うコントラクタです。
あらかじめ10000コインを//1で宣言したbalances変数に入れます。
今回はコントラクトを最初に作成したアカウントは最初から10000コインを入手することになります。
//4
sendCoin関数では送り先アドレスと送る量(金額)を因数として取ります。
実行アカウントのbalancesを確認し、送金額がbalancesを上回るとfalseを返します。
送金額が適正であれば実行アドレスの残高を減らし、送金先アドレスの残高を増やします。
最後にTransferイベントを実行し、metacoinの増減をログに記録します。
処理が完了するとtrueを返します。
//5,//6
アドレス型のaddrを因数としbalancesの所持するコインの量をuintで返します。
ではコンパイルしてみましょう。
まずはインストールしたtruffle develop環境に入りましょう。
そしてコンパイルをします。
truffle develop >compile
次にデプロイ(ここではマイグレーション)を行います。
>migrate
マイグレーションにが完了すると以下のようなログが表示されます
Using network 'develop'. Running migration: 1_initial_migration.js Deploying Migrations... ... 0xcf319e5f024939440825e162cd34ad29e6cc1b161e1bfb2bad3eb2d8a33035f0 Migrations: 0x8cdaf0cd259887258bc13a92c0a6da92698644c0 Saving successful migration to network... ... 0xd7bc86d31bee32fa3988f1c1eabce403a1b5d570340a3a9cdba53a472ee8c956 Saving artifacts... Running migration: 2_deploy_contracts.js Deploying ConvertLib... ... 0x509de9e5315657a7a7771db66124991bc1e8d746dd4feffb0f855bcc1a1b5693 ConvertLib: 0x345ca3e014aaf5dca488057592ee47305d9b3e10 Linking ConvertLib to MetaCoin Deploying MetaCoin... ... 0xffbebbe0f06d016e9d9bf3d35e5fbcb743dc564dabcc330b117d1e04137bf21b MetaCoin: 0xf25186b5081ff5ce73482ad761db0eb0d25abfbf Saving successful migration to network... ... 0x059cf1bbc372b9348ce487de910358801bbbd1c89182853439bec0afaee6c7db Saving artifacts...
最初の一文はtruffle developというネットワーク(ブロックチェーン)を使用しているという意味です。
MetaCoin: 0xf25186b5081ff5ce73482ad761db0eb0d25abfbf
ここのアドレスがデプロイされたMetaCoinのアドレスです。
このアドレスはこの後使います。
それではデプロイしたMetaCoinを実行して、確認していきましょう。
まずはMetaCoinを適当な変数に入れて呼び出しやすくします。
truffle(develop)> coin = MetaCoin.at("0xf25186b5081ff5ce73482ad761db0eb0d25abfbf")
次にgetBalance()をつかって所持しているコインを確認します。
accounts[0]はtruffleを起動したときに自動で割り当てられるアドレスの1つ目を指します。
accounts[0]がデフォルトで設定されているため、最初にコントラクトを起動してコインを受け取るのはこのアカウントです。
truffle(develop)> coin.getBalance(web3.eth.accounts[0]) BigNumber { s: 1, e: 4, c: [ 10000 ] }
すると上記のように10000コイン所持していることがわかります。
さきほどの//3で指定したコントラクトが動いたということが確認できます。
次に2つ目のアカウントも確認してみましょう。
truffle(develop)> coin.getBalance(web3.eth.accounts[1]) BigNumber { s: 1, e: 0, c: [ 0 ] }
二つ目のアカウントはコインを所持していないことがわかります。
それではアカウント[0]からアカウント[1]に送金を行ってみましょう。
ここでは100コイン送ってみます。
truffle(develop)>coin.sendCoin(web3.eth.accounts[1], 100)
このtruffle developのブロックチェーンではすぐに結果が反映されますが、実際のブロックチェーンではマイニングが行われブロックに取り込まれるまで時間がかかります。
では送金がされたか確認します。
truffle(develop)> coin.getBalance(web3.eth.accounts[0]) BigNumber { s: 1, e: 3, c: [ 9900 ] } truffle(develop)> coin.getBalance(web3.eth.accounts[1]) BigNumber { s: 1, e: 2, c: [ 100 ] }
アカウント[0]はマイナス100コインで9900コイン
アカウント[1]はプラス100コインで100コインとなっています。
無事送金ができました。
最後に所持数を超えるコインを送金したらどうなるでしょうか?
truffle(develop)>coin.sendCoin(web3.eth.accounts[1], 10000)
送金が成功したときと比べると違ったログが表示されると思います。
成功時
{ tx: '0x3e9b29cf4058a9550192186c13514e41082ee9fab869b7d6ac8e2366ee78ba3a', receipt: { transactionHash: '0x3e9b29cf4058a9550192186c13514e41082ee9fab869b7d6ac8e2366ee78ba3a', transactionIndex: 0, blockHash: '0x94d2c7b7f0ea6461fc23fc0eacd5cb615b588270ae1c1e3bdfb4991458f052f9', blockNumber: 6, gasUsed: 50993, cumulativeGasUsed: 50993, contractAddress: null, logs: [ [Object] ], status: '0x01', logsBloom: '0x00000000000000000000000000000000010000000000000000000010000000000000000000000020000000000000000000000000000000000000000000000000000000000000000010000008000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000010000000000000000000010000000000000000000000000000000000000000010000000002000000000000000000000000000000000000002000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' }, logs: [ { logIndex: 0, transactionIndex: 0, transactionHash: '0x3e9b29cf4058a9550192186c13514e41082ee9fab869b7d6ac8e2366ee78ba3a', blockHash: '0x94d2c7b7f0ea6461fc23fc0eacd5cb615b588270ae1c1e3bdfb4991458f052f9', blockNumber: 6, address: '0xf25186b5081ff5ce73482ad761db0eb0d25abfbf', type: 'mined', event: 'Transfer', args: [Object] } ] }
失敗時
{ tx: '0x175c04f4e568c865ef3735bc5ffd041b8e03b7832889ac4f9b7547cecdc2c3da', receipt: { transactionHash: '0x175c04f4e568c865ef3735bc5ffd041b8e03b7832889ac4f9b7547cecdc2c3da', transactionIndex: 0, blockHash: '0x4042286c595000ee58b9114190b01ee9c88550de15a8f24b3aeae85a3ec6e883', blockNumber: 7, gasUsed: 23594, cumulativeGasUsed: 23594, contractAddress: null, logs: [], status: '0x01', logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000' }, logs: [] }
一番最後のlogs:[]の部分がからであることが確認できます。eventは送信されたが、プログラムは実行されなかったという意味です。
一応コインの所持数が変化していないか確認してみましょう。
truffle(develop)> coin.getBalance(web3.eth.accounts[0]) BigNumber { s: 1, e: 3, c: [ 9900 ] } truffle(develop)> coin.getBalance(web3.eth.accounts[1]) BigNumber { s: 1, e: 2, c: [ 100 ] }
以上の手順でMetaCoinを実装することができます。
どうでしたか?すごく簡単ですよね?
今回は公式サンプルとして公開されているMetaCoinの実装を行いました。
ブロックチェーン中級者以上の方には退屈な内容だったかもしれませんが、
最後まで見ていただきありがとうございました。
ビザンチン将軍問題~ブロックチェーン理解への道~
この記事を読んでくださっているということはブロックチェーンに興味があるということですよね。
そんな皆さんには基礎知識であるビザンチン将軍問題(Byzantine Fault Tolerance)について改めて整理していきます。
ブロックチェーンには合意形成アルゴリズムが必要不可欠であり、それらがブロックチェン技術の中核を担っています。
ブロックチェーンの生みの親ともいわれるSatoshi NakamotoもPoWのもつビザンチン将軍問題解決の可能性に関して触れていました。
それでは本題に入ります。
1.二人の将軍問題
ビザンチン将軍問題に入る前にこの議論のもととなる話「The Two Generals Problem」を取り上げます。
次の条件を想定してください
- 二人の将軍がいます
- 一人はリーダー、もう一人はそれに従うフォロワー
- 二人はとある敵陣へ攻め込もうとします
- 敵を倒すには二人が同じ時間に同時に攻撃を仕掛けなければなりません
- 二人は遠く離れた地にいるため伝令をお互いに送って「攻撃する時間」を示しあわなければなりません
- お互いに伝令を送るためには間に位置する敵陣を超えていかなければなりません
以上のことを踏まえてシミュレーションを行います。
- 将軍A(リーダー)は朝の9時に攻撃すると決定し、その旨を 将軍B(フォロワー)に伝えるため伝令兵を送ります
- 伝令を受け取った将軍Bは「了解した」という旨を伝えるべく伝令兵を将軍Aに送ります
- 伝令を受け取った将軍Aは合意が形成されたと考え、9時に攻撃を仕掛けることにしました
さてここで問題です。将軍A,Bは敵を倒すことができたでしょうか?
答えは「どちらともあり得る」です。
なんとも腑に落ちない答えですね。
実はこの答えがまさに合意形成の難しさなのです。
細かく見てみましょう。
「将軍Aが伝令を送り将軍Bが受け取った、将軍Bがさらに伝令を送って将軍Aが受け取った」
一見合意形成がなされたように見えます、しかし実は穴があります。
皆さん次の条件を覚えていますか?
- お互いに伝令を送るためには間に位置する敵陣を超えていかなければなりません
ここで不確実性が生まれてきます。
この不確実性により将軍Bは自分が出した伝令が将軍Aに届いたか「わからないのです」
これが無限にループしていきます。
だいぶ簡単に書きましたがこれが二人の将軍問題と呼ばれるものです。
ここから派生しビザンチン将軍問題というものが生まれてきます。
2.ビザンチン将軍問題
さて本題のビザンチン将軍問題に入ります。
次の条件を想定してください
- 1人の将軍A、3人の中将a、b、cがいます
- 敵軍に攻め込みたいが、全軍で攻撃を仕掛けないと倒すことができない(一人でも撤退した場合は負ける)
- 4人は遠く離れた地にいるため伝令をお互いに送って「攻撃する」か「撤退する」かを示しあわなければなりません
- 将軍は中将にどちらの選択をするか伝令をおくります
- 合意の確認を取るため将軍からの伝令を受け取った中将はほかの中将にさらに伝令を送ります
全員が信頼があり、絶対的に裏切らないといえるならばこの作戦は成功するかもしれません。
しかしここで誰かひとり(ここでは中将a)が「裏切り」を行うと仮定します。
これを踏まえてシミュレーションすると
- 将軍Aは「攻撃する」と中将、a、b、c全員に伝令を送りました。
- 伝令を受け取った将軍たちは合意を確認するため他の中将へ伝令を送ります
- 中将aは中将bに「攻撃する」という旨を送ります
- 中将cがここで「裏切り」を行い、bに「撤退する」という旨を送ります
さてこのままいくとどうなるでしょうか。
正解は
aだけが全員が攻撃を行うと思っており、攻撃した。しかし実はほかの二人は撤退していた。
ということが起こります。
このように悪意を持ったノード(ここでは中将)によって合意形成がうまくされませんでした。
少々省いた部分もありますが概要はこのようなことです。
ビザンチン将軍問題は失敗モデルとして最も難しい問題の部類に入ります。
ブロックチェーンは悪意のあるノードが存在することを仮定して設計され、これを解決する策が講じられています。
というかここがブロックチェーンのキモですね。
Bitcoinのブロックチェーンでは最も長いチェーンが採用されるという形で合意形成がされます。
PoWは合意形成というよりスパムを排除する機能といったほうが正しいです。
しかしブロックチェーンではこの問題が完全に排除されたかといわれると疑問視する声が多々あります。
ブロックチェーンの問題はたくさんありますね。
今回はビザンチン将軍問題を扱いました。
今後もブロックチェーンへの理解を深めるためにこのような記事を投稿していきます!!
最後までご覧いただきありがとうございました!
超簡易 ブロックチェーン(Ethereum)上での匿名投票プログラム解説 ”Easiest voting app with blockchain”Part6 番外編
今回はものすごく短い記事です。
前回までの記事でEthereumを利用した投票Dappsプログラムを開設しました。
前回はCUI上で投票を実現したのですが、あまり実践的ではありません。
そこで私が参考にした元サイトではhtmlが公開され、GUI操作によって投票ができます。
今回は解説というよりあくまで紹介記事です。
参考にした元記事↓
medium.com
今回は元記事で公開している、htmlとjsのコードを紹介します。
前回までの解説記事用に少々コードをいじってあります。
下に紹介するhtmlとjavascript(index.js)のコードをPart1で作成したvoting_appフォルダに保存してください
※当ブログの解説記事Part1からPart5までを実行してから利用ください。コンパイルをして、ganacheブロックチェーン上にローカルホストでデプロイして接続していないと以下のコードは利用できません。インストールからデプロイまでは前記事をご覧ください。
www.miyatech-univ.com
vote.html
<!DOCTYPE html> <html> <head> <title>Hello World Dapp</title> <link href='https://fonts.googleapis.com/css?family=Open+Sans:400,700' rel='stylesheet' type='text/css'> <link href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css' rel='stylesheet' type='text/css'> </head> <body class="container"> <h1>Easiest voting app with blockchain</h1> <div class="table-responsive"> <table class="table table-bordered"> <thead> <tr> <th>Candidate</th> <th>Votes</th> </tr> </thead> <tbody> <tr> <td>Taro</td> <td id="candidate-1"></td> </tr> <tr> <td>Kenji</td> <td id="candidate-2"></td> </tr> <tr> <td>Naoko</td> <td id="candidate-3"></td> </tr> </tbody> </table> </div> <input type="text" id="candidate" /> <a href="#" onclick="voteForCandidate()" class="btn btn-primary">Vote</a> </body> <script src="https://cdn.rawgit.com/ethereum/web3.js/develop/dist/web3.js"></script> <script src="https://code.jquery.com/jquery-3.1.1.slim.min.js"></script> <script src="./index.js"></script> </html>
index.js
web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); abi = JSON.parse('[{"constant":false,"inputs":[{"name":"candidate","type":"bytes32"}],"name":"totalVotesFor","outputs":[{"name":"","type":"uint8"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"candidate","type":"bytes32"}],"name":"validCandidate","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"votesReceived","outputs":[{"name":"","type":"uint8"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"x","type":"bytes32"}],"name":"bytes32ToString","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"candidateList","outputs":[{"name":"","type":"bytes32"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"candidate","type":"bytes32"}],"name":"voteForCandidate","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"contractOwner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"inputs":[{"name":"candidateNames","type":"bytes32[]"}],"payable":false,"type":"constructor"}]') VotingContract = web3.eth.contract(abi); //Part4の記事でnodeコンソール内で指定したcontractInstanceを実行し、アドレスを確認してください。そのアドレス(ブロックチェーンにデプロイした際に発行されたトランザクションid)を以下にcontractinstance = VotingContract.at("ここのアドレスを変更") 変更してください。 contractInstance = VotingContract.at('0x2a9c1d265d06d47e8f7b00ffa987c9185aecf672'); candidates = {"Taro": "candidate-1", "Kenji": "candidate-2", "Naoko": "candidate-3"} function voteForCandidate() { candidateName = $("#candidate").val(); contractInstance.voteForCandidate(candidateName, {from: web3.eth.accounts[0]}, function() { let div_id = candidates[candidateName]; $("#" + div_id).html(contractInstance.totalVotesFor.call(candidateName).toString()); }); } $(document).ready(function() { candidateNames = Object.keys(candidates); for (var i = 0; i < candidateNames.length; i++) { let name = candidateNames[i]; let val = contractInstance.totalVotesFor.call(name).toString() $("#" + candidates[name]).html(val); } });
さてそれではhtmlファイルを開いてみましょう。
※ブラウザはGoogle Chromeをお勧めします。
以下には実際のhtml画像を載せています。
1.まずはhtmlを開きます。
※すでにTaroに投票が1入っていますが、スクリーンショットを取る前にテストで投票してみました、htmlを開いた状態では全員の投票数は0になっています。
2.ではTaroに投票してみましょう
Taroの票が1増えたのが確認できると思います。
次にKenji,Naokoにも同様に投票を行います。
最終的な得票数は
Taro:2
Kenji:1
Naoko:3
となりました。
本当に投票できているかをnodeコンソールから確認してみましょう。
nodeコンソールでの確認については前記事を参照してください。
www.miyatech-univ.com
> contractInstance.totalVotesFor.call("Taro").toString() '2' > contractInstance.totalVotesFor.call("Kenji").toString() '1' > contractInstance.totalVotesFor.call("Naoko").toString() '3'
しっかり投票できていますね。
このようにhtmlを利用してブラウザによる投票も可能になります。
今回使ったのはganache-cli(テストブロックチェーン)ですので、実際のブロックチェーンではありません。
機会があったらgethをつかった実際のブロックチェーンに載せる記事も書きたいと思います。
最後までご覧いただきありがとうございました!!
超簡易 ブロックチェーン(Ethereum)上での匿名投票プログラム解説 ”Easiest voting app with blockchain”Part5
前回までにEthereumを利用した匿名投票プログラムをコーディング、ブロックチェーンへデプロイをしてきました。
今回は前回のデプロイ編の続きになります。
↓前回の記事
www.miyatech-univ.com
投票プログラムをブロックチェーンにのせる行程に関しては前回で完了しました。せっかくプログラムを作ったので使ってみたいですよね!
というか動作確認を行っていませんのでそこも併せて確認していきましょう。
今までの記事通りにやったがエラーが出てきた。という方は共有したいのでコメントしていただけると助かります。
それではNodejsのコンソール内でコントラクトを動かしてみましょう!
5:コントラクト実行
※1、前回同様cdコマンドでvoting_appフォルダに移動してから、さらに別ウィンドウのシェルでganache-cliを起動してから行ってください。
※2、前回の記事と続いています、Part2で書いたコードPart3でコンパイルしてからPart4でデプロイした後にこの記事を読んでください。
>contractInstance.totalVotesFor.call("Taro") BigNumber { s: 1, e: 0, c: [ 0 ] }
前回指定したcontractInstanceからコントラクト内のtotalVotesForを呼び出して。Taroの数値を確認します。
c[0]となっているのが確認できます。
まだ誰からも投票を受けてないので総数が0となっています。
では投票してみましょう。
> contractInstance.voteForCandidate("Taro", {from: web3.eth.accounts[0]}) '0xb6aa941a9958f0b50407caa6f62ada684d74f09d0b7a38f06983a7b38bcf1a91'
ganacheで生成されたテストアカウントのインデックス番号0のアカウントからTaroに投票を行いました。
その下にすぐにhashが表示されます。
これがこのトランザクション(コントラクト実行)のhash値(トランザクションid)になります。
Ethereumではトランザクションが実行されるごとにこのハッシュ値が生成されます。
この値が各トランザクションの証拠となります。この値はイミュータブル(変更不可)です。
ここで一度ganache-cliのウィンドウを見てみましょう。
eth_accounts eth_sendTransaction Transaction: 0xb6aa941a9958f0b50407caa6f62ada684d74f09d0b7a38f06983a7b38bcf1a91 Gas usage: 43411 Block Number: 2 Block Time: Wed May 30 2018 20:48:44 GMT+0900 (東京 (標準時))
どうでしょう、トランザクションidが一致していますよね。
そして使用されたgas、取り込まれたブロックの番号、時間が表示されます。
一番最初のトランザクションなのにBlock Numberが2になっていますね。
これは前回のデプロイした際
deployedContract = VotingContract.new(["Taro","Kenji","Naoko"],{data: byteCode, from: web3.eth.accounts[0], gas: 4700000})
ここでブロックチェーンにデプロイし、コントラクトがブロック1に取り込まれたためです。
では続いて投票してみましょう
> contractInstance.voteForCandidate("Taro", {from: web3.eth.accounts[0]}) '0x1cf83e75f545bbea6904148ffffb28da66bf3dc52225dbf65e280fc6bef2de45' > contractInstance.voteForCandidate("Naoko", {from: web3.eth.accounts[0]}) '0x2a5160dca86a79564d2db06b8c1fd1ead3b8b438449b23050ce1ac4377ef1027'
最後に投票されたか得票数を確認してみましょう。
> contractInstance.totalVotesFor.call("Taro").toString() '2' > contractInstance.totalVotesFor.call("Naoko").toString() '1' > contractInstance.totalVotesFor.call("Kenji").toString() '0'
総数が投票した数だけ変わりましたね。
以上がコントラクトを実際に動かして、投票を行う流れです。
一通り試してみてEthereumの理解が深まったと思います。
※シェル上でコントラクトを動かすのは実用的ではないため次回は参考元サイトのソースをお借りして、html上で投票を行う方法を紹介したいと思います。
今後はSolidityの使い方や、その他ブロックチェーン記事を引き続き書いていきます!
最後までお付き合いいただきありがとうございます!
今後も引き続きよろしくお願いします!
超簡易 ブロックチェーン(Ethereum)上での匿名投票プログラム解説 ”Easiest voting app with blockchain”Part4
今回はついにコントラクトをブロックチェーンにデプロイしていきます!
これまでの記事は下準備+コーディング+コンパイルでした。
区切りをつけて理解していくと簡単に感じますよね。
今後もこのようなスタイルで行こうかと思います。
では早速本題に入っていきましょう!
※1、cdコマンドでvoting_appフォルダに移動してから、さらに別ウィンドウのシェルでganache-cliを起動してから行ってください。
※2、前回の記事と続いています、Part2で書いたコードPart3でコンパイルしてから今回のデプロイを行ってください。
4:デプロイ
デプロイといっても難しいことはありません。ただ変数に重要な個所をストアしていき、ブロックチェーンに組み込む際に必要なデータを指定してあげるだけです、
>abiDefinition = JSON.parse(compiledCode.contracts[":Voting"].interface) >VotingContract = web3.eth.contract(abiDefinition) >byteCode = compiledCode.contracts[":Voting"].bytecode >deployedContract = VotingContract.new(["Taro","Kenji","Naoko"],{data: bytecode, from: web3.eth.accounts[0], gas: 4700000}) >deployedContract.address >contractInstance = VotingContract.at(deployedContract.address)
①abiDefinition:JSON.perseオブジェクトを使用し、。JSONとして前回のコンパイルしたコードをストアします。
②VotingContract:コントラクトオブジェクトを作成します。これはブロックチェーンにデプロイする際、初期化する際に使用します。
③byteCode:ここに前回重要だといったbytecodeをストアしていきます。
④deployedContract:ここのVotingContract.new部分でブロックチェーン上にデプロイします。最初の["Taro","Kenji","Naoko"]は選挙での立候補者をそのまま記述します。その次に来る引数がブロックチェーンにデプロイする際に重要になります。
1.data:コンパイルされてできたバイトコードです。以前から数回出てきていますが、この部分がブロックチェーン上にデプロイされてハッシュ内に入ります。
2、from:ブロックチェーンでは誰がコントラクトをデプロイしたかをトラックし続けます。ここではganacheが生成したテストアカウントの一つ目(インデックス番号0番目)を指定しています。
※実際のブロックチェーン上でアカウントを利用する場合はアカウントのロックを解除できませんので注意してください、今回のテストアカウントは既にアンロック済みなので気にしなくで大丈夫です。
3、gas:Ethereumを知っている方、勉強している方はわかると思いますが。Ethereumではブロックチェーン上でコントラクトを実行する際にEtherを消費します。ここで指定したgasはマイニングを行うマイナーに報酬として支払われます。ここではその報酬金をgasで指定します。
※1.gasが低すぎるとマイナーへの報酬が少なくなり、マイナーは進んでマイニングしません。よってgasを高く指定すると比較的迅速にマイニングされます。またこの限度額はfor、whileの無限ループを利用したgasの異常消費を制限します。
※2.実際にはgasPrice(ETH) x Total Gas Usage = 支払われたETHとなりますので、厳密にはここでのガスはマイナーへ支払われるETHではありません。
⑤deployedContract.address:④でブロックチェーンにデプロイはできました。しかしブロックチェーン上にはたくさんのコントラクトが実行されています。その中から特定のコントラクトを探す際にここで指定するdeployedContract.addressで識別します。つまりアドレスを利用します。
⑥contractInstance:⑤でコントラクトのアドレスを取得したので、それをインスタンスとしてストアします。
次回は実際にデプロイしたコントラクトをを使って投票していきますが、今回出てきたAddressとabiDefinitionが大切な値なので覚えておいてください。
以上でデプロイ編は終了です。
どうでしょうか、思ったより簡単ですよね!
次回はブロックチェーン上に流したコントラクトにメゾッドを利用して、実際に投票を行ってみましょう。
今回も最後までお付き合いいただきありがとうございました。