Rso's Jotter

日々の開発の知見のメモやその他雑記

"ビットコインは終わった" という言説について

仮想通貨関連の話題として、 ビットコインは終わった という言説、主張をたまに見かけます。 そしてビットコインが2017年に加熱する以前から仮想通貨、ブロックチェーンに興味をもって触っていた人にとって見れば、 その言説に何か違和感を感じるような人もいるかと思います。

そこでビットコインは何が終わった、何が終わっていないのか、を考えてみました。

ビットコイン終わった 派の主張

ビットコインが「終わった」という主張の例として、書籍 After Bitcoinを挙げてみます。 この本の帯には、こう書かれています。

ビットコインは「終わった」。 ブロックチェーンは「これから本番」。

この本は2017年10月に発行されており、その時はちょうどビットコインの価格が1BTC70万程度の時期でした。 そのあと2017年12月の1BTC200万を突破する直前の時期で、ビットコインはバブルなのかという声が聞こえる一方で、 ビットコインやアルトコインが軒並み値上がりしている時期でした。

この高騰の渦の中で、ビットコインが決済システムとして以下の欠点があることを冷静に指摘しています。

  • 脆弱性: ビットコインを管理するシステムが脆弱であり、保管も課題があるため、流出のリスクが伴う
  • 偏在性: クジラと呼ばれる大口保有者が全体の大半を保有している
  • 非通貨: 通貨としてビットコインを使用しているユーザはごくわずか
  • 投機性: 投機的な価格変動があまりに激しい
  • 集中性: 前取引の大半が中国元を占める
  • 崩壊性: 半減期によるマイニング報酬の減少や、政府の介入リスクが伴う

上記のように、通貨、決済システムとして弱点があり、使えるレベルではないのでは、という主張を行っています。

実際、2018年度には投機熱がかなり高まったため、2017年12月には1BTC230万円超えを記録したものの、現在は約1BTC40万円ほどで、約6分の1ほどに下落しています。

ビットコイン終わっていない 派の主張

ビットコインはもともと サトシ・ナカモト氏の論文 で中央管理者が不在の状況で不可逆な価値の取引を実現するシステム として提唱され、現在のビットコインはそれを実現しています。

ビットコインが稼働し始めてから現在に至るまで、この 管理者不在で価値の取引を実現する という目的は達成されており、欠陥が見つかったわけではありません。 むしろこれだけ多くの人に注目を集めた状態でも、仕組みそのものに欠陥が見つからなかったことは、よりこの仕組みが強固なものと証明されたという考え方もできるかもしれません。

またビットコインは一種の "価値の保存形態" としての地位を確立しており、いわゆる金に近いような性質を持ちます。 金は希少であり、金属的に特殊な性質も持つものとして、中央銀行の情勢の影響を受けにくい資産として認識されていますが、ビットコインも発行量が限定されており、 数学的に特殊な性質持つものとして扱うことができます。この管理者不在で価値を保てるという仕組みが一定程度認められているため、資産としても価値があるとも言えます。

2018年度に下落自体は確かに起こりましたが、2017年1月の1BTC15万に比べてれば、現在はそれよりも遥かに高く、単純に投機熱が高まって冷めただけのこととも見えます。

両者の主張まとめ

とりあえず私が思う両者の主張を書いてみましたが、2017年度の加熱期以前から興味を持っている方は、後者よりなのではないでしょうか。

ビットコイン終わったと思っている人は、ビットコインが現在の金融システムをすげ替えてしまう素晴らしい仕組みで、もっとビットコインによる決済が身近になると 考えていた人が、それが当面実現されないと感じたのではと考えます。After Bitcoinの著者もビットコインはそんな優れた決済システムではないよと指摘しており、その意味で "終わった" という言葉を使用しているのかと推察します。

その一方で、もともと管理者不在の価値の取引の仕組みとして着目している人にとっては、現在は一歩一歩課題をクリアしている段階で、外野が勝手に夢見て幻滅しているのは構わないが、 本質は何も終わっていない、と考えてるのかなと思います。

JavascriptのPromiseコード間違い探し

Javascriptのコードをレビューしていたら以下のような少々ツッコミどころのあるコードを見つけましたのでメモしておきます。 内容は一部サマっていますが、以下のようなコードです。

function asyncFunction() {
  return new Promise((resolve, reject) => {

    //本当は別の非同期処理
    setTimeout(function () {
      resolve('非同期処理完了');
    }, 3000);

  }).then( (result) => {
    // 成功した処理
    console.log(result)
    return true;
  }).catch( (_err) => {
    //失敗した処理
    console.error(_err)
    return false
  });
}

//メイン処理
if(asyncFunction()){
   console.log("正常終了処理")
}else{
   console.log("異常終了処理")
}

やりたい処理の意図は以下です。

  • メイン処理でPromise を使った非同期処理を行う関数asyncFunctionを呼び出している。
  • その呼び出し結果に応じて、呼び出し元がその関数呼び出しが正常か異常か判断しようとしている。

ということがやりたかったのですが、さてこのコードはどこがおかしいでしょうか。

一見すると(?)普通に動くように見えるかもしれませんが、同期処理と非同期処理の理解が混在していることが伺えます。 おかしなところを一言で言うと、以下の部分でasyncFunctionはtrue/falseを返さない。と言うことになります。

  if(asyncFunction()){

Promiseのthenのなかで return true とかかくとそのまま trueが帰ってくるように錯覚したと思うのですが、 Promise.then() 内で return したら Promiseオブジェクトが返されます . なので たとえ上記のasyncFunctionがrejectされたとしても、 ifの判定はelseの方に行きません。

MDN のサイトにもPromise.thenの戻り値について以下のように記載されています。

then メソッドは Promise を返すので、メソッドチェーンができます。 関数が then にハンドラーとして渡されると Promise を返します。同じ Promise がメソッドチェーンの次の then に現れます。

上記はasyncFunction の結果を受けてから 呼び出し元で処理を実行したい意図があったかもしれませんが、非同期処理となるために想定された順序で実行されません。

ですのでありきたりな解決策ですが、正しくは呼び出し元でも thenを使いましょう、と言うことになります。

function asyncFunction() {
  return new Promise((resolve, reject) => {
    console.log("promise start")

    //本当は別の非同期処理
    setTimeout(function () {
      resolve('非同期処理完了');
    }, 3000);

  }).then( (result) => {
    // 成功した処理
    console.log(result)
    return true;
  }).catch( (_err) => {
    //失敗した処理
    console.error(_err)
    return false
  });
}

//thenとcatchに変更
asyncFunction().then( () => {
   console.log("正常終了処理")
}).catch( () => {
   console.log("異常終了処理")
})

これで正しくasyncFunctionの結果を待ってから後続処理が実行されました。これでおっけーでしょうか。 実はまだもう一つ問題があります。 asyncFunction内でcatchしてそのままreturnしているものをもう一度catchしようとしています。 catchメソッド内で単純にreturnした場合、 それは resolve扱いになるので、 asyncFunction呼び出し後の "異常終了処理"は実行されません。

なので対策としては、 2回もcatchを入れるのをやめるか、どうしても2段にしたいのであれば、 1つ目のcatchのなかで rejectを呼んでやる必要があります。

function asyncFunction() {
  return new Promise((resolve, reject) => {
    console.log("promise start")

    //本当は別の非同期処理
    setTimeout(function () {
      resolve('非同期処理完了');
    }, 3000);

  }).then( (result) => {
    // 成功した処理
    console.log(result)
    return true;
  })
  .catch( (_err) => {
    //失敗した処理
    console.error(_err )
    // rejectに変更
    reject(false) //どうしても外側でもcatch処理行いたい
  });
}

asyncFunction().then( () => {
   console.log("正常終了処理")
}).catch( () => {
   console.log("異常終了処理")
})

これでエラー時は2つ目もcatch処理を実行させることができました。

ちょっと例のコードが実施の処理を省略しているので分かりづらかったですが、 非同期の処理とPromiseの仕様を理解する上で良いミス(題材)だと思ったので、記載しました。

ブロックチェーンアセットがゲームの考え方を変えると思う

最近、ブロックチェーンを使用して動いているDAppsのゲームである、My Crypto Heroes で遊んでみたので、その所感を記載しておこうと思います。

My Crypto Heros とは

www.mycryptoheroes.net ざっくりいうとイーサリアムのブロックチェーンを使用するゲームで、ゲーム内で獲得したアセット(キャラクターや武器[エクステンション]など) がイーサリアムネットワーク上でやり取りすることができるのが特徴です。

2019年3月3日時点では、 DappsRadar によると、My Crypto Heroesが イーサリアムベースのDAppsでは取引量1位になっています。*1

f:id:rso:20190303220930p:plain
DappsRadar

My Crypto Heroesのゲーム内のアセットはERC721という規格に準拠しており、ERC721に準拠したトークンを売買できるサービスを使用すれば、ゲーム内で獲得したアセットを売買することができます。

また現在, My Crypto Heroesでは OpeanSea というERC721トークンの取引所で売買可能です。

opensea.io

ブロックチェーンアセットが与える影響

ゲームを通じて自分のキャラクターを強化し、レアアイテムを集めてバトルに勝つという点では一見すると他のスマホゲームと同じなのですが、上記で記載したようにゲーム内で獲得したアセットが、イーサリアム上のネットワークで取引可能になることで、以下のような違いがあると思います。

  • (事実上の)換金が公式に認められている。今までの国内のほとんどのゲームは、ゲーム内のでアイテムを現金への換金することを禁止しています(一部の海外のゲームは認められています)が、このゲームは 獲得したアセットが 仮想通貨(イーサリアム)に変換できることを認めています。

  • ゲームのアセットが規格化され、それを売買できる取引所が独立していることで、ゲーム開発側はERC721に準拠することでイーサリアムの売買プラットフォームとブロックチェーンの永続性を享受することができ、アセット売買もゲーム独自の方法でなく、取引所の取引方法に標準化されます。

このようなアセットの標準化と取引所が分離されることにより、よりゲームに対して、投資・投機的な観点で取引が進むのではないかと予想しています。

取引で簡単にアセットが取引できるため、ゲームを実際にプレイしない人でも、ゲームが期待できそう、将来的に人気が出ると予想される場合、初期の場合からアセットを購入しようというインセンティブが働きます。

実際の例として、 以下のアセットは直近 6.7ETH(約10万円) で売買が成立していますが、このアセットはもともとプレセールで 0.1ETHから売買が開始されていました。 当時と今ではイーサリアムの価格も違いますが、単純なイーサリアムベースの比較ですと数十倍に上がっています。これはゲームプレイ人口だけでなく、投資・投機的観点から購入している人が一定層いるのではないかと考えます。 opensea.io

また、ゲームをプレイする人も自分が苦労して獲得したアセットに価値がつくことでよりインセンティブが上がり、初期のゲームでも積極的に参加するようになると考えられます。

このようにゲームのアセットとそれを交換できるプラットフォームが結びつくことで、アセットの流動性が飛躍的に向上し、ゲームの業界に投資マネーが流れ込み金融市場マーケットが形成され、投資に近い感覚を持ってプレイするようになるのではないかと考えます。

ブロックチェーンゲームがまだ浸透していない理由

上記のように、ブロックチェーンゲームがもっと浸透すれば 今までにないゲームの潮流が現れてくると思いますが、現状はそれほど浸透していません。以下の理由からまだそれほど流行っていないのだろうと考えています。

  • 参入障壁が高い。ブロックチェーンゲームをプレイするには、 Metamaskなどのウォレットを入れて、イーサリアムなどの仮想通貨を入手する必要があります。もともと仮想通貨をトレードしていた人はできるかと思いますが、ストアで検索してインストールするだけの他のアプリに比べると、かなり障壁が高いと思われます。
  • 大量のトランザクションを捌けない。 現在イーサリアムの処理能力は課題となっており現在改良の話が議論されていますが、一般で使用されているスマホゲームのような大量のトランザクションを高速で捌くというのは現在できません。このような理由から、 My Crypto Heroesもイーサリアムのチェーンを使用するのはアセットの取引など、最小限にとどめているものと考えられます。
  • 鍵の管理が難しく、セキュリティリスクが高い。ブロックチェーン技術が以下に改ざんに強く信頼性が高くとも、トークンの持ち主であることを証明する鍵の管理は個人に依存しています。鍵の紛失、漏洩すればトークンは二度と取り戻せません。特に投資家サイドからの視点では、資産が失われるリスクが高いとなかなか参入できないのではないかと考えられます。

ブロックチェーン技術自体がまだまだ発展途上であり、これらの技術的問題はいずれ解消すると考えています。 その時は、ブロックチェーン上でアセットを管理するのが当たり前のような時代になっているのかもしれません。

*1:イーサリアムに限らなければ、現在 取引量ベースではEOSベースのギャンブル系ゲームアプリの方が多くなっています。

3分間シェル芸クッキング: 締切まで 後X営業日です をターミナル起動時に表示する

ふと実装したくなったプチ処理をシェルでサクッと実施するメモしておきます。

本日は, ちょっと先の期日の締切(プロジェクト完了日とか上期終了日など) まで何営業日あるんだろう、それを 毎日表示することができたら便利かも?と思ったので、それをシェルでサクッと作ったらどうなるかをご紹介しようと思います。

仕様としては以下の通りです。

  • 指定した期日まで、本日から数えて後何営業日(土日祝除く) をターミナル起動時に表示する。
  • 指定した期日は頻繁に変更にされる想定ではないので、ハードコードしても良いとする。

また仕様ではないですが、

  • 出来るだけサクッと作成できる方法を選択する

として、上記を作ってみようと思います。

まず祝日の判定ですが、RubyやJSなど使えば祝日判定ライブラリがあるのですが、それらをインストールしたり、日付から祝日かどうかを毎回判定するもの処理が大変なので、今年の祝日リストをサクッとExcelなどで作ります。祝日は内閣府のページ などを参照して引っ張ってきます。 今回は 日付,曜日,祝日かどうか をCSVに書きました。

作成したCSVは、以下のような内容になります。

.calendar.csv · GitHub

上記のファイルをダウンロードして, .calendar.csv としてホームディレクトリに保存します。

これで下準備は完了で、いよいよシェルによる調理を行います。 色々やり方はあり、 sedawk でももちろんできるのですが、これらに馴染みのない人には謎文字列の羅列に見えがちという欠点がありますので、今回は皆さまに馴染みのある grep を使うパターンでやりたいと思います。

で、早速ですが実際のシェルを以下に示します。 締め切りは 上半期の終わり (2019-06-30) を入れています。自分は .zshrc に記載していますが、 bashの人は .bashrc に記載すれば大丈夫です。

today=`date +%Y-%m-%d`
eigyo_bi=`grep ${today} -A 1000 .calendar.csv | grep -B 1000 "2019-06-30" | grep -v "[土日祝]" | wc -l | tr -d " "`
echo "##########################"
echo "今期の営業日はあと ${eigyo_bi}日です"
echo "##########################"

これだけで終わりです。設定した後にシェルを立ち上げると以下のような表示がされると思います。

f:id:rso:20190225221609p:plain

以上です! が、ちょっとだけ処理の内容を説明しておきます。

today=date +%Y-%m-%d

これは シェル変数today に本日の日付を所定のフォーマットにして格納しています。 例えば本日の投稿日 で在れば "2019-02-25" という文字列が入ります。

grep ${today} -A 1000 .calendar.csv

これは .calendar.csv の 本日の日付以降1000行を表示しています。 grep -A -1 でも似たような挙動になるようなのですが、ドキュメントに載っていなかったので、適当に1000行としています。

grep -B 1000 "2019-06-30"

さらに、締切の期日 "2019-06-30" 以前の1000行を表示します。これで本日 ~ 締切までの日付一覧が抜粋されている状態となります。

grep -v "[土日祝]"

さらに、土日祝 の文字列のいずれかにマッチした行を省いています -v は grep でマッチしていない行のみ出力するオプションで、頻出です。

wc -l | tr -d " "

最後に残った行数をカウントしてやれば、営業日の数となります。wc -l は先頭にスペースが含まれた状態で出力されるので、 tr -d " " で不要なスペースを除いて、完成です。

とまあざっくりですがこんな感じです。毎回ログイン時に表示されるのは良くないとか、カレンダーを毎年作らないといけないとか、締め切りがハードコードなのは 如何なものか.. というのはもちろんありますが、とりあえずやりたいと思った処理を 10分ぐらいで作れた(ほとんど CSV作成) のでまあこんなもんかなと思います。

もっとこうしたらカッコよくできる、みたいなのがありましたらブログ、Twitterなどでご紹介ください。

RPAが嫌いなエンジニアが多い理由

システム開発者のみならず、PCなどで事務作業を行なっている人はRPAという言葉を 最近よく聞くかと思います。

RPAとは Robotic Process Automation(ロボティック・プロセス・オートメーション) の略で、 主にPCを使用したデスクワークを自動化して効率化することを指します。

数年前からこのワード自体は耳にしていたのですが、近年ニュースでRPAによる効率化の事例やら、 RPA用のツール導入の話をよく耳にするようになりました。

RPAの導入事例として、例えば以下のようなニュースがあります。

innovation.mufg.jp

www.itmedia.co.jp

他にも検索したらいくらでも出てきますが、大手の金融機関が事例としてよく挙がっています。

また、RPAのツールとして、以下のようなツールが有名です。

www.uipath.com

rpa-technologies.com

winactor.com

RPAを推進する理由としては、定型的な作業はロボットにやらせて効率化し、 より知的な作業をヒトがやるということが大抵挙げられています。

RPAが嫌いな理由

上記のRPAを推進して効率化すること自体はなんら悪いことではないのですが、 RPAツールがあまり好きではない、関わりたくないと言うエンジニアが一定数います(皆がそう言うわけではないですが)。

私もRPAの話を聞くたびに何かモヤっとするものがあり(RPAによる効率化推進自体は悪いと思っているわけでは無い)、 このRPAツールおよびその推進活動が好きになれない理由を周りのエンジニアの言っていることを含めて少し考えてみました。 私が思うに、以下のような理由があるのではないかと思います。

  • 実態としてはExcelマクロやUWSC のような 昔からあるようなPCからの操作を覚えさせて自動実行する仕組みなのに、自動化プログラムをロボットと称してあたかも最新の技術のように謳っていること。
  • APIがあればもっと簡単に自動化することが可能なのに、APIが無いが故に古いシステムの古いUIの挙動に合わせた実装を強制されること。
  • コード記述不要のGUIのみで開発可能、と謳っているところがほとんどだが、エラーハンドリングなど考慮するとGUIのみでの開発がとても煩雑になること。

私が思うに、本当にプログラムで自動化したいなあら、API を用意すべきだと思います。GUIは人がアクセスするのに適したインターフェースであり、プログラムがアクセスするために適したインターフェースはAPIです (Application Programming Interfaceと言いますし) 。人の操作するインターフェースに対して、無理やり自動化を当てはめているのがRPAで、エンジニア目線で見ると無理をして自動化しているように見えます。なのでRPAの適応対象は APIが存在しなくて、追加開発するには規模が大きすぎるシステムであり、古いシステムが対象となり、エンジニアは古いシステムにあまり関わりたくありません。 Money Forward とか freee のシステムをRPAで効率化と言う話は聞きません。なぜならAPIを使う方がよっぽど楽だからです。

また、コード記述が大抵不要で、GUIで開発できるものが多いですが、どうしてもGUIの開発では表現できる範囲が限定されてしまいます。 PoCなどの検証レベルでは十分に使えるのですが、実運用となると、エラーハンドリングで大抵悩まされます。入力レコードが誤っていたものが入ってきたりとか、システムの応答が遅い/返ってこなかった場合など、これのエラー処理を共通化して処理する仕組みがなかったりなど、泥臭い実装を強いられるようになります。

一言で言うと

上記いくつか考えてみましたが、エンジニアが敬遠する理由を一言で言うと、 古いシステムのツケを無理やり清算するような泥臭い仕組みなので触りたくない上に、最新の技術っぽく喧伝しているところが気に食わない と言った感じなんでしょうか。