【TruffleでDapp開発】「truffle unbox pet-shop」を実行すると「Downloading...」で止まる

【はじめに】

イーサリアムを購入してからブロックチェーンに興味を持ち、休みの日はDapp開発の勉強をしています。技術情報を調べていると【Truffle】というイーサリアム開発のフレームワークに出会いました。早速触ってみましたが、インストールでエラーが発生したり環境構築で四苦八苦しています。

【ETHEREUM PET SHOP】

先回、何とかTruffleのインストールが完了したので、公式サイトにあるチュートリアルETHEREUM PET SHOP」をダウンロードしてみました。

【ダウンロード】

Truffleのインストールが完了していると、下記のコマンドで「ETHEREUM PET SHOP」のプロジェクト一式がダウンロードできます。

truffle unbox pet-shop

成功すると下記の様に「Unbox successful. Sweet!」が表示されます。

Downloading...
Unpacking...
Setting up...
Unbox successful. Sweet!

Commands:

  Compile:        truffle compile
  Migrate:        truffle migrate
  Test contracts: truffle test
  Run dev server: npm run dev

私の場合は「Downloading...」で止まり、先に進んでいる様子がありません。。。

【原因】

セキュリティソフトが原因でした。Webのトラフィックを監視する機能を無効にして再度、コマンドを実行すると「Unbox successful. Sweet!」が表示されました。気付いたら簡単な事ですが、なかなか気付けず2~3時間悩んでしまいました。まだまだ先が長い。

【TruffleでDapp開発】Truffleのコマンド「truffle version」でSyntaxError

【はじめに】

イーサリアムを購入してからブロックチェーンに興味を持ち、休みの日はDapp開発の勉強をしています。技術情報を調べていると【Truffle】というイーサリアム開発のフレームワークに出会いました。早速触ってみましたが、インストール時点でエラーが発生しましたので原因と対応方法をまとめておきます。

【Truffleのインストール】

nodeとnpmが使える環境で以下のコマンドを実行します。

npm install -g truffle

【バージョン確認】

以下のコマンドを実行し、Truffleのバージョンが表示すれば正常にインストールされています。

truffle version

正しくインストールされている場合、TruffleとSolidityのバージョンが表示されます。

Truffle v4.1.13 (core: 4.1.13)
Solidity v0.4.24 (solc-js)

私の場合、ここでSyntaxErrorが発生しました。

SyntaxError: Block-scoped declarations (let, const, function, class) not yet supported outside strict mode

【原因と対応方法】

原因と対応方法については、この記事が参考になります。

trueman-developer.blogspot.com

以下のいずれかの方法で対応可能であることが分かりましたので、nodeのバージョンをあげることにしました。Truffleのインストールなのでnodeのバージョンアップしか選択肢がありません。

  1. "use strict"(厳格モード)を使用する
  2. 実行時に起動オプション(--use_strict)をつける
  3. nodeのバージョンをあげる(6.x 以上)

【nodeのバージョンアップ】

上げる前のバージョン:v5.10.1
上げた後のバージョン:v10.8.0

nodeのバージョンは以下のコマンドで確認できます。

node -v

今回はnodeのバージョン管理ツール「nodist」を使いました。以下の記事が参考になります。

webbibouroku.com

手順1

github.com

上記サイトからインストーラーをダウンロードして、nodistのインストールを行います。インストール後は端末を再起動します。

手順2

再起動後、以下のコマンドでnodistのバージョンを確認します。

nodist -v

nodistのバージョンが表示すればインストール完了です。

0.8.8

手順3

nodeのバージョンを指定してインストールを行います。以下のコマンドでインストールできるバージョンが確認できます。

nodist dist

手順4

バージョンを指定してインストールを行います。今回はv10.8.0にしました。

nodist + 10.8.0

手順5

使用するnodeのバージョンに切り替えを行います。nodistはnodeのバージョン管理ツールなので簡単に切り替えができます。

nodist 10.8.0

手順6

正しく切り替わっているか確認します。以下のコマンドでnodeのバージョンを確認します。

node -v

変わっていない。。。

v5.10.1

nodist経由以外でnodeをインストールしている場合、アンインストールする必要がありました。ということで、v5.10.1のnodeをアンインストールします。windowsの設定>アプリと機能からnodeをアンインストールしました。

再度、nodeのバージョンを確認します。

node -v

バージョンがv10.8.0になりました!

v10.8.0

【Truffleのバージョン確認】

Truffleのバージョンを確認します。

truffle version

おぉ、SyntaxErrorではなくTruffleとSolidityのバージョンが表示されました。nodeのバージョンが古すぎたのが原因でしたね。これでTruffleのインストールは完了です。

Truffle v4.1.13 (core: 4.1.13)
Solidity v0.4.24 (solc-js)

【Solidity】OpenZeppelinのOwnableコントラクトとは

【はじめに】

この記事はSolidityを勉強する為にCryptoZombiesで学んだ事を自分用のメモとして書いています。

【CryptoZombiesとは】

Solidityでスマートコントラクトの構築を学習できるサイト
日本語で丁寧に説明してくれるので、プログラミングやったことない人でも学習できる。

cryptozombies.io

【OpenZeppelinのOwnableコントラクトとは】

Lesson3でOpenZeppelinのOwnableコントラクトが出てきました。
Solidityの勉強で重要と思いましたので記事にしておきます。

OpenZeppelinとは?

Ethereum上で安全なスマートコントラクトを実装するためのフレームワーク

github.com

Ownableコントラクトとは?

OpenZeppelinの1つで、コントラクトの実行権限を限定することができる。
実行権限を管理しておかないと誰でも実行できる状態になり悪用される恐れがある。
Ownableコントラクトを継承すれば、コントラクトを作成した人しか実行できないようにすることが可能。

【Ownableコントラクト】

/**
 * @title Ownable
 * @dev The Ownable contract has an owner address, and provides basic authorization control
 * functions, this simplifies the implementation of "user permissions".
 */
contract Ownable {
  address public owner;

  event OwnershipTransferred(
    address indexed previousOwner,
    address indexed newOwner
  );

  /**
   * @dev The Ownable constructor sets the original `owner` of the contract to the sender
   * account.
   */
  constructor() public {
    owner = msg.sender;
  }

  /**
   * @dev Throws if called by any account other than the owner.
   */
  modifier onlyOwner() {
    require(msg.sender == owner);
    _;
  }

  /**
   * @dev Allows the current owner to transfer control of the contract to a newOwner.
   * @param _newOwner The address to transfer ownership to.
   */
  function transferOwnership(address _newOwner) public onlyOwner {
    _transferOwnership(_newOwner);
  }

  /**
   * @dev Transfers control of the contract to a newOwner.
   * @param _newOwner The address to transfer ownership to.
   */
  function _transferOwnership(address _newOwner) internal {
    require(_newOwner != address(0));
    emit OwnershipTransferred(owner, _newOwner);
    owner = _newOwner;
  }
}

constructor

Ownableコントラクトのコンストラク
コントラクト作成時に1度だけ実行されるので、作成者のアドレスをownerに格納することができる。

modifier onlyOwner

onlyOwnerを関数につけることで使用できる。
コントラクトを呼び出したアドレスと作成者のアドレスが同じでない場合、エラーになる。
つまり、作成者以外が呼び出しても実行できなくなる。

transferOwnership

ownerのアドレスを変更することで実行権限を移行することができる。

【まとめ】

OpenZeppelinはSolidityの開発で頻繁に使われているので、自分で作成するよりもセキュリティ面で安心して使用できます。
Ownable以外にも便利なコントラクトがありそうなので、もっと勉強しなければ。

【CryptoZombiesを触ってみた】Lesson2で学んだこと

【CryptoZombiesとは】

Solidityでスマートコントラクトの構築を学習できるサイト
日本語で丁寧に説明してくれるので、プログラミングやったことない人でも学習できる。

cryptozombies.io

【はじめに】

Solidityは未経験ですが、JavaScriptは触ったことがあります。
そんな人が自分用の学習メモとして書いています。

【学んだこと】

  • データ型のmappingとaddress
    • mappingはKVS(Key-Value Store)
    • addressはEthereumのアドレス
'mappingの書き方 Key => Value
mapping (address => uint) public accountBalance;
mapping (uint => string) userIdToName;
  • msg.sender

その関数を呼び出したユーザー(またはスマートコントラクト)のaddressを取得する。

mapping (address => uint) accountBalance;

function setBalance(uint _myBalance) public {
  accountBalance[msg.sender] = _myBalance;
}

function whatIsMyBalance() public view returns (uint) {
  return accountBalance[msg.sender];
}
  • Require

条件を満たさない場合、エラーを投げる。

'挨拶(_greeting)が"Hello"の場合、"Hello!"を返す。
'"Hello"以外の場合、エラーになる。
function sayHello(string _greeting) public returns (string) {
  require(keccak256(_greeting) == keccak256("Hello"));
  return "Hello!";
}
  • 継承
'BabyDogからtype()も実行可能
contract Dog {
  function type() public returns (string) {
    return "puppy";
  }
}

contract BabyDog is Dog {
  function age() public returns (string) {
    return "1 year old";
  }
}
  • Import

別ファイルに定義されているコントラクトをImportで呼び出し、
継承すれば使用可能になる。

import "./someothercontract.sol";

contract newContract is SomeOtherContract {

}
  • 変数のStorageとMemory
    • Storageはブロックチェーン上に永久に格納される。
    • Memoryは関数呼び出し時に消去される。
  • InternalとExternal

関数宣言はprivateやpublicの宣言方法と同じ。
Internalはprivateと同じだが、このコントラクトから継承したコントラクトにもアクセスできる。
Externalはpublicと同じだが、コントラクトの外からだけ呼び出すことができる。
コントラクト内部の別の関数から呼び出すことはできない。

  function eat() internal {
  }

  function drink() external {
  }
  • interface

ブロックチェーン上の他人のコントラクトとやりとりする時に使用する。

'Ethereumのアドレスと電話番号を紐づけるコントラクト
contract PhoneNumber {
  mapping(address => uint) numbers;

  function setNum(uint _num) public {
    numbers[msg.sender] = _num;
  }

  function getNum(address _myAddress) public view returns (uint) {
    return numbers[_myAddress];
  }
}
'別のコントラクトからPhoneNumberのコントラクトを使用したい場合、Interfaceを定義する。
contract PhoneNumberInterface {
  function getNum(address _myAddress) public view returns (uint);
}

contract MyContract {
  address PhoneNumberInterfaceAddress = 0x......;
  PhoneNumberInterface phoneNumberContract = PhoneNumberInterface(PhoneNumberInterfaceAddress);

  function someFunction() public {
    uint num = phoneNumberContract.getNum(msg.sender);
  }
}
  • 複数の返り値

返り値は複数指定することができる。
特定の返り値のみ取得する場合は不要な返り値をブランクにする。

function multipleReturns() internal returns(uint a, uint b, uint c) {
  return (1, 2, 3);
}

function processMultipleReturns() external {
  uint a;
  uint b;
  uint c;
  (a, b, c) = multipleReturns();
}

function getLastReturnValue() external {
  uint c;
  (,,c) = multipleReturns();
}
  • If

JavaScriptと同じ

【できたもの】

ゾンビにクリプトキティを食べさせると進化する。

f:id:takuyafujita:20180729182042j:plain
f:id:takuyafujita:20180729182220j:plain

【CryptoZombiesを触ってみた】Lesson1で学んだこと

【CryptoZombiesとは】

Solidityでスマートコントラクトの構築を学習できるサイト
日本語で丁寧に説明してくれるので、プログラミングやったことない人でも学習できる。

cryptozombies.io

【はじめに】

Solidityは未経験ですが、JavaScriptは触ったことがあります。
そんな人が自分用の学習メモとして書いています。

【学んだこと】

  • contractの書き方、お作法
  • 変数宣言
  • 四則演算

Solidityは指数演算子もサポートしている。

uint x = 5 ** 2; // 5^2 = 25 と同様

※cryptozombies より引用

  • 構造体と配列の操作は他のプログラミングと同じ
  • 関数
    • グローバル変数と区別をつけるために、引数の変数名にアンダースコアをつける。
    • スコープ(public、private)を指定する位置が後ろ
    • privateにする場合は引数同様、関数名にもアンダースコアをつける。
    • 修飾子
      • view:データの読み取り専用で編集できない。
      • pure:アプリ内のデータにアクセスできない。戻り値が関数の引数のみに依存する。
function _generateRandomDna(string _str) private view returns (uint) {
}

※cryptozombies より引用

  • 型のキャスト
  • Event(イベント)

ブロックチェーンで何かが生じたとき、
コントラクトがアプリのフロントエンドに伝えることができる。

event NewZombie(uint zombieId, string name, uint dna);

function _createZombie(string _name, uint _dna) private {
    uint id = zombies.push(Zombie(_name, _dna)) - 1;
    NewZombie(id, _name, _dna); // イベント発生、フロントエンドに通知
} 

※cryptozombies より引用

【できたもの】

ゾンビの名前を入力すると、オリジナルのゾンビを作成してくれる。

f:id:takuyafujita:20180716062638j:plain