Nuxtで、簡単なDapps作った

やったこと

ethereumの送金をできるだけのシンプルなDappsを作ってみた
慣れてるNuxtを使った。

いろいろ触るので、いつ動かなくなるかわからないけどURL。
https://keisukeponpoko.github.io/web3/

アプリケーション側

初期設定

nuxtをinstallするとかの部分は割愛。

インストール - Nuxt.js

プラグイン作成

/plugin/web3.js を作成。
初期時に、web3 objectのinjectと、addressや、ethereum残金をstoreに入れてみた。

参考:
Breaking Change: No Longer Injecting Web3 – MetaMask – Medium
MetaMaskのアドレスをgetAccountsで取得する

import Web3 from 'web3';

export default async function({ store }, inject) {
  let web3;
  if (window.ethereum) {
    web3 = new Web3(window.ethereum);
    await ethereum.enable();
  } else if (window.web3) {
    web3 = new Web3(window.web3.currentProvider);
  } else {
    console.log(
      'Non-Ethereum browser detected. You should consider trying MetaMask!'
    );
    return;
  }

  inject('web3', web3);

  if (web3 !== null) {
    web3.eth.getAccounts((error, accounts) => {
      if (error) return;
      let user_account = accounts[0];
      if (typeof user_account !== 'undefined') {
        store.commit('setAccount', user_account);
        web3.eth.getBalance(user_account, function(err, balance) {
          if (!err) {
            store.commit('setBalance', balance);
          }
        });
      } else {
        alert('ログインして下さい');
      }
    });
  }
}

nuxt.config.js にも追加

  plugins: ['~/plugins/web3.js'],

Store追加

/store/index.js に追加

export const state = () => ({
  account: '',
  balance: 0
});

export const getters = {
  account: state => state.account,
  balance: state => state.balance
};

export const mutations = {
  setAccount(state, account) {
    state.account = account;
  },
  setBalance(state, balance) {
    state.balance = balance;
  }
};

export const actions = {};

Pages作成

/pages/index.vue を編集

<template>
  <div>
    <div>account: {{ account }}</div>
    <div>balance: {{ balance }}</div>
    <button @click="send">Send Ether</button>
  </div>
</template>

<script>
export default {
  computed: {
    account() {
      return this.$store.getters['account'];
    },
    balance() {
      return this.$store.getters['balance'];
    }
  },
  methods: {
    send() {
      if (this.$web3 === undefined) return;
      console.log(this.$web3);

      this.$web3.eth
        .sendTransaction({
          from: this.account,
          to: '0x0C6390A4F8bE143d3905aFA1BcCcacC44f335794',
          value: 10
        })
        .on('receipt', console.log);
    }
  }
};
</script>

ブラウザ側

PCなら、MetaMaskをChrome拡張で入れる。
モバイルなら、Trust Wallet とかの、ウォレット機能付DAppsブラウザでページを開く。
実際に送金したかったら、Ropstenとかのテストネット使って、下のサイトとかで、ethereumをもらうと楽。
Ropsten Ethereum Faucet

あんま関係ないけど、githubに公開

参考:
Nuxt.jsで作ったWebサイトをささっとGithub Pagesに公開する - Qiita
GitHub Pages へデプロイ - Nuxt.js

nuxt.config.js に以下を追加

const routerBase =
  process.env.DEPLOY_ENV === 'GH_PAGES'
    ? {
        router: {
          base: '/<repository name>/'
        }
      }
    : {};

export default {
  ...routerBase,
}

package.jsonに以下を追加

  "scripts": {
    "gh:generate": "DEPLOY_ENV=GH_PAGES nuxt generate",
    "gh:push": "git subtree push --prefix dist/ origin gh-pages"
  },

ターミナルで以下を実行

$ yarn gh:generate
$ git add --all
$ git commit -m "commit"
$ yarn gh:push

あとは、github pagesの対象ブランチを gh-pages に変えちゃえばOK!!
.gitignore に dist を指定している場合、うまく行かないので注意。

完成!

こんな感じに表示されるはず。
f:id:okadak1990:20190429025952p:plain

DAppsでの秘密鍵管理調査

やりたいこと

MCH(My Crypto Heroes)のようなDAppsが、どうやって秘密鍵の管理等を行っているか調査してみた。

PC & ブラウザ

Walletとして、MetaMaskを利用。
MetaMaskで生成したアドレスに対して、取引所を利用して、etherを振り込む。
そうした後、ゲーム内でEtheriumを使ってて、GUM(ゲーム内通貨)を購入できる。

MetaMaskを有効化すると、web3 objectがインジェクトされるので、普通に、web3.js使ってwebアプリを開発すればいいっぽい。
MetaMask を使用した Web3 の初期化 - Qiita

モバイル & ブラウザ

Go Walletや、Trust Walletといったウォレット機能付きモバイルブラウザを利用する。
上記のウォレットで、PCの時のMetaMaskと同じことができる。

この記事見るとわかりやすい。
https://makionaire.com/dapps-introduction/

モバイルブラウザでもweb3.js使ってアプリ開発しとけば、動くんじゃないかなと思うんだけど、要調査。

モバイル & アプリ

ここに関しては想像が入ってます。 違ったら教えてください!

ウォレット機能付きモバイルブラウザであるtokenPocketさんという会社?が提供しているらしい。
Dappsもトークンも。イーサリアムを、あなたのポケットに。

Webview 使ってる気がする。
教えて!Webviewって何?ネイティブと何が違うの? | 株式会社ランチェスター

秘密鍵は、こんな感じで端末に保存しているんじゃないかなと思う。
What is an Ethereum keystore file? – Julien M – Medium

技術的には、ウォレット機能付いたブラウザアプリを作って、さらにモバイル向けのWEBアプリ作ったって感じ?
MCHは、ブラウザアプリをtokenPocketさんが、WEBアプリをMCHを作ってるdoublejump.tokyoさんが分担して作ったと考えると分かりやすそう。

まとめ

DApps使いたい場合は、ウォレット機能付きモバイルブラウザが必要っぽい。
もちろん秘密鍵を毎回入力してもらえれば問題ないけど、それは面倒だし、サーバ保存はセキュリティや法律的に厳しい。
なので、ウォレット機能付きモバイルブラウザ and メタマスク連携できる形でサービスを作って行くのが基本なんだなーって感じ。

例えば、日本だと、go wallet が、app store みたいな感じになって、ここからユーザはゲームとかサービス探して、開発者はここに新しいアプリを載せて、みんなに知ってもらうみたいな世界観なのかなーって思った。
で、大きくなったら、webviewでネイティブアプリ化していって、もっとUI必要だよねってなったら、Walletごとネイティブで、開発するみたいな。
GO!WALLET (ゴーウォレット) | DApps・ブロックチェーンゲームに対応したクリプトウォレットアプリ

小規模WEB系ベンチャーで働いてきて考えたこと

概要

後一年で30になるので、仕事やプライベートに対しての現状の考え方をまとめてみた。 あと、退職理由と転職理由は、その時悩んでたことを表してるのでそれも書いた。
完全に自分語りかつ長いので、苦手な方はスルーしてください。

退職理由と転職理由

1社目

お金もなかったし、研究も終わってたしで、広島の院中退して、東京で、WEB制作会社に就職した。
単純にこの時は、お金を自分の手でいっぱい稼ぎたかったから、稼ぐなら営業!更に言えば起業!と思って営業志望で受けてた。
けど制作側の方が向いてるってことで、そっちで採用されることになって、リスティング広告運用とか、WEBページの改修とかを主にやってた。
この時初めてプログラミングを覚えて、いろいろ勉強した。

この会社では結果が出て、それが評価されたので給料どんどん上がったけど、実際に自分の専門性が何かわからなくて、そこに当時は悩んでた。
その時に、唯一の後輩が、この会社で働いても誰のためになってるかわからないから、他の会社に転職して、自分も妙に納得してしまい転職することにした。

2社目

転職先として、プログラミングをしっかり学べて、なおかつ事業の目的をしっかり謳ってるところを探して、とあるIT企業の40人ぐらいの社内子会社に就職した。
お金に関しては、結果出せたら、また給料上がるだろと思って、度外視してたので結構下がった。

先輩にプログラミングのことやチームでの開発の仕方や設計などをしっかり教えてもらえたし、ビジョンに関しては凄く大切にしてる企業で、あとめっちゃホワイトだし、1on1とかの制度もしっかりしてて、凄く勉強になった。そして働いている人がみんなコミュニケーション取れてて、いい人ばかりで働きやすかった。

ただ、働いて1年ぐらいたつと、学べることが少なくなってきて、以下のことを思うようになった。

  • 自分で設計からサービス作ってみたいが、案件自体が少ないし、先輩から優先だから、当分来なそうだった。
  • じゃあ自分で、一から関わってサービス立ち上げようとしたけど、事業性のあるアイデアがでず、許可が下りなかった。
  • 施策は基本ディレクターや外部コンサルが立てて、それを実装するのが仕事になっていて、前職とのギャップが大きかった。
  • 最高評価はもらえても、諸々の理由により、年収が増えなかった。
  • 親会社からのプレッシャーで、売上重視にならざるを得なく、ビジョン大事といっているのに矛盾が生じているのではという声があった(ここに関しては、この指摘が正しいのかどうか分からなかった)

3社目

社内のディレクターさんが参加してたので、一緒にWEBエキスパートドラフトに登録してみた。
すると、今いる会社にオファーをもらった。

転職理由は以下の通り。

  • 技術選定や、設計から自分が中心となって、既存WEBサイトのリニューアルをさせてもらえる。
  • 給料も増える。
  • ベンチャー企業は、ビジョン第一で動いているのではないかと思って、それがどんな感じなのかを体験したかった。
  • チームで動いていて、自分で施策立案もどんどんできるということだった。

今ここで働いているが、想定通りだったことと、想定通りではなかったことがある。

想定通りだったこと

  • 自分が中心となってリニューアルができた。NuxtやRails、Docker、ECSといったやったことのない技術に触れることができた。
  • 給料も増えた。

想定通りではなかったこと

  • 親会社がいなくても、出資者はいるわけで、ビジョン実現大事!プロダクト最優先!ユーザー最優先!みたいなことは、ありえなかった。
  • 全てのステークホルダーに対して、価値を提供していこうという点で売上は大事だし、その点では目指すところは、前の会社と一緒だった。というか、どの営利企業もそうだろうなと思った。
  • チームで動いて施策立案していくということだったが、効率性を求めると、外部コンサルが提案する施策中心になった。例えば、WEBサイトだったら、主目的は集客だから、SEOコンサルに任せる方向にいっちゃうんだなーって思った。

達成したいこと

自分の達成したいことは、以下である

睡眠欲と食欲を満足させる

ここは今まで通りいきたい。怖いのは結婚や子供が生まれることだけど、そこまでにお金を貯める。
強いて言えば、新宿とか渋谷とかのランチの店がいっぱいあるところで働きたいと思うことはある...
千駄ヶ谷はおしゃれな店が多くて、お昼の選択肢が少ないし、1000円超える店が多い...

お金をある程度稼ぎたい

結婚や子育ても考えて、エンジニアとして年800万円ぐらいは稼げるようになりたい。
もっと多いといいけど、お金使うところは、昼のランチ代と漫画買うぐらいだから、あんまいらない。
今の市場感が維持されれば、このままできることを増やしていくことで問題なく達成できそう。

仕事で数値の見える結果を出したい。

去年までは、自分で施策立案して、自分で実装して、自分のコントロールできる範囲内で、結果を出したいと思っていた。
ただ、今回、初めてプロダクトの数値改善でない仕事を行なって、自分で数値改善施策なんて出さなかったけど、そこまで不満を感じなかった。
あと、前職の時から、薄々自分以外がやった方がうまくいくことってたくさんあるし、自分も実装に集中した方がいいプロダクトできるなって感じていた。
結果を出したいのは、せっかく仕事をするなら楽しく仕事をして、達成感を味わって、承認欲求も満たしたいからで、それに携われるんなら、自分一人でやらなくても満足できるんだなってなった。
一個思っているのは、報酬がもらえないと、結果を評価されないって気持ちになるから、結局金銭報酬を求めることになりそうだけど。

もっと勉強したい

一度勉強を始めたら、楽しくて、満足するまでできるけど、始めるまでに時間がかかるようになった。
特に会社で使う技術は、寝る間も惜しんで勉強できるのに、自分の趣味で勉強することは、暇な時間にしかできない。
会社で新技術が必要になる => 勉強する => うまく実装できる => 結果が出る => 次も自分に依頼される ってループを作っていきたい。
とりあえず、今は土曜日にブロックチェーン関連のお手伝いをして、勉強できてるのでここは深めていく。
機会学習とかアルゴリズムとか、セキュリティとかもっと知りたいことあるのに、手がつけられてない...

今後どうしていくべきか

会社選び

必須条件として、

  • 働き方がある程度自由な会社。飲み会の次の日とかはしっかり寝たいから、フレックスは必須。
  • すごい忙しいわけではなくて、ある程度給料はもらえる(狙える)会社。
  • 結果と報酬が結びついている(年功序列じゃない)会社。

で、望む条件として、

  • 楽しそうな技術を使ってる
  • やったことのないことを仕事でやらせてもらえる

これらを重視するべきだと思う。

ビジョンとか、エンジニアの裁量とかは、どの会社もしっかりしてると思うので、そこは考えないでいい気がする。

そして、その条件から見ると、現時点で退職する必要はなさそう。

日々の生活

土曜日以外も勉強する習慣をつけて、その内容をブログに書くようにする。
これで、知識欲求と、誰かが見てくれれば承認欲求の獲得につながる!!

仕事について

まずは、会社から求められていることをもっと明確に聞く癖をつけないといけない。
自分で動こうにも、経営層の頭の中を全て理解できているわけではなく、何が正しいのかの判断が難しい。
あと、こっちがどうしたいかをはっきり提示しないと、会社もどこにアサインするか上手く判断できないとは思ってるけど、1on1がないと話す機会もないしで、コミュニケーションロスを感じるなと思った。

技術面に関しては、強引な実装が来た時の「これできますか?」の質問に、x日かかりますが、技術負債が残ってしまうので、仕様をこのようにできませんか?というのが、一番最初に出て来てしまっている。
これを、技術負債を残さない方法をしっかり考え、この方法だとx日、簡単な方法だとx日かかります。仕様を変えると、x日になります。というように、企画者に選択肢とそれの背景をしっかり答えられるように、経験や深く考える技術をつけていきたい。

あとは、やったことがあることを増やしていって、実装速度を早くしたり、手札を増やしたりしていきたい。

まとめ

いろんな人のブログ読んで、みなさんが何を考えているか参考になるなって思って、自分も書いてみたところ考えていることが整理されて、次やることがシンプルになったので良かった。

とりあえず、仕事面ではコミュニケーションをもっと密にすることを意識して、プライベートでは楽しい範囲で勉強する!

TestnetでToken発行

やったこと

ERC223 と ERC20に対応したToken作成して、Ropstenテストネットに、Tokenをあげた。 その後、そのTokenを他の人のアドレスに送金した。

Token作成

まず、Tokenを作成した。

こちらをみながらERC20系に必要なfunctionを利用。 https://github.com/OpenZeppelin/openzeppelin-solidity

ただ、これをそのまま実装しては、ERC223に対応できない。
そのため、有名なNANJ TOKEN を参考にした。

ERC223系では、

  • transferFrom
  • approve
  • allowance

とそれに紐づくイベントが削除されている代わりに、

  • transfer(address to, uint value, bytes memory data)

とそれに紐づくイベントが追加されている。 ERC223に沿った形で実装する必要がある。

ERC20の送金失敗の課題解決に挑戦するERC223

また、ERC20系で定義していたtransferは、上記サイトにあるように、Contract Address への送金した場合、そのTokenが失われないようにする必要がある。

NANJ TOKENは、他にも

  • frozenAccount
    • 指定したアカウントでは取引できないようにする
  • lockupAccount
    • 指定したカウントは指定された間ロックされる
  • mint
    • 新しくTokenを発行し、総供給量を増やす。
    • openzeppelin-solidityの、ERC20.solにもあるから、ほぼERC20系のデフォルト機能なのかも。
  • burn
    • Tokenを削除し、総供給量を減らす。
    • openzeppelin-solidityの、ERC20.solにもあるから、ほぼERC20系のデフォルト機能なのかも。
  • distributeAirdrop
    • 一括でユーザーにTokenを送金する。
  • collectTokens
    • 一括でユーザーからTokenを回収する。

がある。

今回は、こちらを参考にさせていろいろ機能を入れてみた。

Contractを、作成する際に、solidity 5.0系で作ったのだが、NANJ TOKEN をコピーしただけでは、上手く動かないので注意。

Localで確認

truffleとganacheをインストールして、ganacheを立ち上げる。

Truffle Suite | Documentation | Truffle | Truffle Quickstart

truffle.configに、以下を記述すると、ganacheにアクセスできるはず。

networks: {
   development: {
     host: "localhost", 
     port: 7545,
     network_id: "*",
    },

で、作ったContractを配置して、migrationフォルダ内に、

// 2_deploy_contracts.js
var MyToken = artifacts.require("./MyToken.sol");

module.exports = function(deployer) {
  return deployer.deploy(
    MyToken
  );
};

と書いて、以下コマンドを実行。

$ truffle development // truffleのコンソールを起動
> migrate // migrationフォルダのプログラムを実行して、Contractをデプロイ
> let instance = await ContractName.deployed() // deployしたContractを取得。
> instance.name() // Contractのnameメソッドが呼ばれ、TokenNameが取得できる!!

これで、localで確認終わったので、testnetへあげて見る

Testnetへデプロイ

truffleからもデプロイ可能だと思うが、geth立ち上げて、tastnetと同期してという作業が面倒だったので、remixを利用した。

Remix - Solidity IDE

トークン作ってみよう! - 誰にでも簡単なトークンの作り方|高瀬俊明 | ブロックチェーンの日々|note

上記記事がわかりやすすぎるので、説明は省略します。この記事通りに、TokenをDeployする。

そうすると、etherscan上に今発行したTokenを確認できる。

終わったら、metamaskとか使って、送金してしまえば終了!!

感想

一通り、Token発行までの流れが理解でき、Ethereum Tokenの仕様もだいたい理解できた。 Railsを使って、Walletを作る方法もわかったので、満足!

Shining Wizzard with ECS

概要

tech.toreta.in

こちらのサイトにあるシャイニングウィザードをECS環境で行おうとしたメモ 本家のシャイニングウィザードは、github の webhookを受け取って、シャイニングウィザードが実施されるけど、そこはまだ作ってなくて、一旦Localから叩くようにしてる。

シャイニングウィザードって?

開発時に、現在開発中のブランチの内容を、ディレクターさんとかにチェックしてほしいってことが良くある。
このとき、stagingとかdevelop ブランチにあげて、確認してもらうと、その確認が終わるまで、他の人がリリースできない。
自分のlocalを直接みてもらうこともできるけど、それはそれで自分が他ブランチで作業できず、いろいろ面倒。
そのため、github pushで、確認環境を自動生成しようというのがシャイニングウィザード

EC2の時は、先輩が作ったシャイニングウィザードを使ってたけど、ECS環境に変わったので自分で作ってみた。

やったこと

ECRとECSを利用しているのを前提とする。

1. Dockerファイルを作成

// 既にECRにあるイメージを利用することで、yarn install を早くする
FROM {Dev環境で使ってるImageのECR上のURL}
RUN apk update && apk add git

// .git フォルダをgithubからcloneする。
RUN git clone --no-checkout https://{User名}:{GithubToken}@github.com/{レポジトリ名} gittmp
RUN cp -r gittmp/.git .
RUN git reset --hard HEAD

// Branch Nameは外から渡す
ARG BRANCH_NAME

# この時点以降で、キャッシュを効かせないためにdummyfileをADD(必要か微妙)
ADD dummyfile /data/

// fetchしてbranch情報を最新に
RUN git fetch

// 対象ブランチをチェックアウト
RUN git checkout -b ${BRANCH_NAME} origin/${BRANCH_NAME}

// アプリケーションを起動
RUN yarn install
RUN yarn run build
CMD yarn run start

2. Shell ファイルを作成

#!/bin/bash

BRANCH_RAW_NAME="$1"
if [ "$1" == "" ]; then
  BRANCH_RAW_NAME=$(git symbolic-ref --short HEAD)
fi

AWS_ACCOUNT_ID={ECRとかECSの頭についてるID}
APP_NAME={アプリケーションの名前}
BRANCH_NAME=`echo ${BRANCH_RAW_NAME} | sed -e 's/#//g' -e 's/\//_/g'`
CLUSTER_NAME=`echo ${APP_NAME}_${BRANCH_NAME} | sed 's/_/-/g'`

echo "${BRANCH_RAW_NAME} shining wizzard start"

echo 'Create Docker Image'

# Dockerログイン
$(aws ecr get-login --no-include-email --region ap-northeast-1)

# docker Build時に、キャッシュ利用をやめさせるために追加
touch dummyfile

# Docker Buildして、push! Imageはいらないので削除。
AWS_IMAGE_NAME=${AWS_ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com/{ECRのフォルダ名}:${BRANCH_NAME}
docker build . -t ${AWS_IMAGE_NAME} -f Dockerfile_nuxt --build-arg BRANCH_NAME=${BRANCH_RAW_NAME}
docker push ${AWS_IMAGE_NAME}
docker rmi ${AWS_IMAGE_NAME}

echo 'ECS Task Create'
# ECSタスク追加
NET_CONFIG="awsvpcConfiguration={subnets=[{subnet}],securityGroups=[{securitygroup}],assignPublicIp=ENABLED}"
VPC=[{VPC}]
ROLE={ROLE}

echo 'Check Task Definition'
TASK_DEFINITION_ARN=$(aws ecs describe-task-definition --task-definition ${CLUSTER_NAME} --query='taskDefinition.taskDefinitionArn')
if [ "$TASK_DEFINITION_ARN" == "" ]; then
  echo 'Create Task Definition'

  # Task Definition 作成
  TASK_DEFINITION= {ECSのタスク定義をJSON形式で挿入}
fi

echo 'Check Cluster'
CLUSTER_STATUS=$(aws ecs describe-clusters --clusters ${CLUSTER_NAME} --query='clusters[].status')
CLUSTER_STATUS=`echo $CLUSTER_STATUS | tr '\n' ' ' | sed -e "s/ //g" -e "s/\"//g" -e "s/\[//g" -e "s/\]//g"`

// Clusterが存在するかチェック
if [ "$CLUSTER_STATUS" == "ACTIVE" ]; then
  // Clusterが既にあるなら、タスクもあるよねってことで古いタスクはストップ
  echo 'Old Task STOP'
  OLD_TASK_ID=$(aws ecs list-tasks --cluster ${CLUSTER_NAME} --query='taskArns[0]')
  OLD_TASK_ID=`echo $OLD_TASK_ID | sed "s/\"//g"`
  STOP_TASK_INFO=$(aws ecs stop-task --cluster ${CLUSTER_NAME} --task $OLD_TASK_ID)
else
  # cloudwatch logs groupを作成しておく
  aws logs create-log-group --log-group-name /ecs/${CLUSTER_NAME}
  aws logs put-retention-policy --log-group-name /ecs/${CLUSTER_NAME} --retention-in-days 30

  # ECSのクラスターとか作成
  echo 'ECS Cluster create'
  aws ecs create-cluster --cluster-name ${CLUSTER_NAME}

  echo 'Task Definition create'
  aws ecs register-task-definition --family ${CLUSTER_NAME} --task-role-arn ${ROLE} --execution-role-arn=${ROLE} --network-mode awsvpc --container-definitions ${TASK_DEFINITION} --requires-compatibilities FARGATE --cpu 512 --memory 1024
fi

echo 'New Task Run'
RUN_TASK_INFO=$(aws ecs run-task --cluster ${CLUSTER_NAME} --task-definition arn:aws:ecs:ap-northeast-1:${AWS_ACCOUNT_ID}:task-definition/${CLUSTER_NAME} --network-configuration ${NET_CONFIG} --launch-type FARGATE)

TASK_ID=$(aws ecs list-tasks --cluster ${CLUSTER_NAME} --query='taskArns[0]')
TASK_ID=`echo $TASK_ID | sed "s/\"//g"`

echo 'タスクが生成されるまで待機'
sleep 60

NETWORK_INTERFACE_ID=$(aws ecs describe-tasks --cluster ${CLUSTER_NAME} --tasks ${TASK_ID} --query='tasks[].attachments[].details[?name==`networkInterfaceId`].value[]')
NETWORK_INTERFACE_ID=`echo $NETWORK_INTERFACE_ID | sed -e "s/\[ \"//g" -e "s/\" \]//g"`

IP_INFO=$(aws ec2 describe-network-interfaces --network-interface-ids ${NETWORK_INTERFACE_ID} --query='NetworkInterfaces[].Association[]')

printf "\e[33m IP情報 \e[m"
printf "\e[1;31m ${IP_INFO} \e[m"
// ちなみに削除コマンドもここに
// task definitionは一個しかないはずなので、一個だけDeregister
aws ecs deregister-task-definition --task-definition arn:aws:ecs:ap-northeast-1:${AWS_ACCOUNT_ID}:task-definition/${CLUSTER_NAME}:1

# Taskは常に一個しかないはずなので、一個TaskをSTOP
OLD_TASK_ID=$(aws ecs list-tasks --cluster ${CLUSTER_NAME} --query='taskArns[0]')
OLD_TASK_ID=`echo $OLD_TASK_ID | sed "s/\"//g"`
aws ecs stop-task --cluster ${CLUSTER_NAME} --task $OLD_TASK_ID

# クラスターを削除
aws ecs delete-cluster --cluster ${CLUSTER_NAME}

# ロググループも削除
aws logs delete-log-group --log-group-name /ecs/${CLUSTER_NAME}

printf "\e[33m 削除完了しました \e[m"

3.実行

上のshellファイルを自分の環境に合わせて修正して、実行すればうまく行くはず。

ざっくり流れ

DockerFile上で対象ブランチの変更を取得して、それを利用してDocker buildして、ECR上にDocker push。
ECSのClusterやTask定義、cloudwatchのlog groupを作成して、ECSのTaskを生成。
上記設定だったら、IPアドレスが振られるので、それを表示!

もっとシャイニングウィザードに近づけるために

  1. Github push で更新。delete で task削除を行えるようにする。
  2. Route53とIPアドレスを紐づけて、更新してもURLが変わらないようにする。

注意

shellファイル書くの初めてだったので、変なところとかあったらすいません。
terraform とか https://github.com/aws/amazon-ecs-agent で作った方が楽なのかも。
Dockerの部分は、実際はLocalのものをDocker buildして、pushしちゃった方が楽です!
(今回は、一つのコマンドで、Backend APIRailsと、Frontend の Nuxt を行いたかったから、こういう特殊な方法を取りました!)

感想

aws ecs cli をがっつり触るのは初めてだったけど、めっちゃ便利だった。
あと、先輩に流れのアドバイスをもらったぐらいで、作業自体は、自分の力で簡単にできた。

Etherium Coin 調査

概要

Tokenにどのような機能があったらいいか、NANJCOINを参考に調べました。

NANJCOINについては、こちらの記事が勉強になりました。
NANJCOINのコードについて、NANJのエンジニア†つっちー†さんが解説してくれました!そもそもERCとは?

NANJCOINのコードです! https://etherscan.io/address/0xffe02ee4c69edf1b340fcad64fbd6b37a7b9e265#code

中身

Library

SafeMath

四則演算するとき、値のオーバーフローや、アンダーフローに対応するためのライブラリ

詳しい説明は、こちらの記事がわかりやすいのでおすすめ!
SafeMath.solを読んでみました

openzeppelin の ソース
openzeppelin-solidity/SafeMath.sol at master · OpenZeppelin/openzeppelin-solidity · GitHub

Contract

Ownable

コントラクトを作った人しか実行できない関数を作るために利用する

詳しい説明は、こちらの記事がわかりやすいのでおすすめ! 【Solidity基礎】OpenZeppelinのOwnableについて - ブロックチェーンエンジニアとして生きる

openzeppelin の ソース
openzeppelin-solidity/Ownable.sol at master · OpenZeppelin/openzeppelin-solidity · GitHub
上記ソースには、renounceOwnership という関数が追加されていて、これを使うとownerの権限がなくなって、より非中央集権に近づくようにできる

ERC20

この記事がわかりやすいです。 ERC20トークンで実装すべきメソッドとイベントの解説 - ブロックチェーンエンジニアとして生きる

関数としては、

  • name
  • symbol
  • decimal
  • totalSupply
  • balanceOf
  • transfer
  • transferFrom
  • approve
  • allowance

イベント(これを実行するとログが残る)は、

  • Transfer
  • Approval

name, symbol, decimal についての一般的な実装はこちらに
openzeppelin-solidity/ERC20Detailed.sol at master · OpenZeppelin/openzeppelin-solidity · GitHub

それ以外の一般的な実装はこちらに(BurnとMintの実装も入ってました) openzeppelin-solidity/ERC20.sol at master · OpenZeppelin/openzeppelin-solidity · GitHub

ERC223

ERC20の関数には、欠点がありそこを解消したのがERC223だそうです。 詳しくは、下の記事がわかりやすかったです。
EthereumのERC20 Tokenの問題点を解決したERC223 Tokenとは? - ブロックチェーンエンジニアとして生きる

NANJCOINは、ERC223の規格を採用しているようです。
ERC223規格を採用することで、発行量を増やしたり、減らしたり、Tokenの回収ができたりするようです。
ただ、それだとERC20に対応してる取引所で取引できないので、ERC20とも互換性を持つよう作られているとのことです。
(approveとか、transferFromとかがERC223だと削除されてます)

その他

NANJCOINに入ってるその他の機能には、(違ったらすいません)

  • DistributionAirdrop
    • 一括で指定したアカウントにToken配布?
  • FrozenAccount
    • アカウント凍結?
  • LockupAccount
    • 一定時間までアカウントをロック?
  • collectTokens
    • 一括で指定したアカウントからTokenを回収?

がありそう?

Ethereum Wallet 調査

Ethereum の Wallet のセキュリティをどう担保するか

Wallet とは暗号通貨を、保持、送受信する機能を持つもの。
いくつか種類があり、Walletの認証に用いる鍵を管理する手法が異なっている。

ウォレットの種類

トランザクションをどう扱うか

ルノード型

全てのブロックとトランザクションを取得して検証する。
全部のトランザクションを持ってるので、容量がめっちゃ必要。
Ethereum だと1TBの容量が必要らしい

SPVクライアント(Light Client)

自分に関するトランザクションを取得して検証する。
ブロックヘッダーのみを保持するので、容量が少なくて済む。
Ethereumでは、Light Clientは現在開発中っぽい。

Light client protocol · ethereum/wiki Wiki · GitHub

APIクライアント(Remote Client)

ルノードをREST API等を経由して利用する。

送金に必要な秘密鍵をどう管理するか

サーバで持つ場合

事業者が責任を持つ。
そのため、事業者のサーバが落ちたら利用できないし、事業者側がハックされたときどうしようもできない。
ユーザ的には管理は楽。

クライアントで持つ場合

事業者が鍵を管理する必要がないので、セキュリティ要件が低くなる。
一方で、ユーザはバックアップとかしとかないと、なくしたら二度とアクセス(利用)できないなど、気にすることが増える。

持ち方にはいくつかある。 - クライアントウォレット:スマホとかPCに持つ。 - ハードウェアウォレット:専用の機器を利用する。財布みたいなもの。 - ペーパーウォレット:紙に持つ

参考: DroidKaigi 2019 - いかにしてビットコインを扱うか / ゆいき (@yuikijp) [JA] - YouTube

サーバ側で鍵を管理する

サーバ側で鍵を管理する場合、セキュリティをしっかりと担保する必要がある。
どう言った技術を利用するべきか

注釈

サーバ側での管理をすると、サービス事業者が許可しないと取引を行えない。 ということは、中央による管理となるから、ブロックチェーンの思想に合ってない気もする。

Multi Sig

簡単にいうと、例えば、鍵を3つに分けて、分けた鍵が2つ揃わないと、鍵として利用できないようにするということ。 ユーザ側が2つ、事業者側が1つもつようにすると、ユーザは自分だけで取引可能。事業者側だけでは取引できない。 一方で、ユーザ側が鍵を1つ盗まれても、事業者側の鍵と一緒に使わないと取引できないので安心。

詳しくはこちら! Multisig(マルチシグ)って何? - ビットコインダンジョン2.0

Ethereumでの実装

Ethereumでは、Multisigを実装するために、Contractを作成している。
List of MultiSig Wallet Smart contracts on Ethereum

それを作成するためには、Contractに精通した技術者がいないとセキュリティ担保が難しそう。
Gnosis MultiSig Wallet(ノーシス・マルチシグ・ウォレット)とセキュリティへのコミットメント

LGPLライセンスだったから、下記のContractを真似すれば実装はできそうだけど、知識がなさすぎて怖い。 GitHub - gnosis/MultiSigWallet: Allows multiple parties to agree on transactions before execution.

二段階認証

実装したのでまとめた Rails & Mongoid で二段階認証実装 - okadak1990’s blog

感想

一旦調べた感じ、MultisigをEthereumで用いるには、知識が必要で、下手に実装した場合セキュリティホールになりそう。
クライアントに持たせる形にするか、二段階認証とかで最低限の担保をしてサーバー側で持たせるかが現実的なところかと思う。
ブロックチェーンの思想的には、動画にあった通りクライアントに持ってもらった方がいいと思う。
ただ、金額が少量な場合(サービスの初期段階)は、サーバー側で持つ方針の方が、管理コストをユーザーが払わないで済むという点から良いのかなとも思う。
難しい...