- ブロックチェーンでこれが出来る!
- スマートコントラクト言語のセキュリティの仕組み①
- スマートコントラクトで資産を作ってみる
- トランザクションは普通のユーザーには難しいかも
- トランザクションを実行するとリソースがPathに保存される
- 最新ブロックチェーンFlowのトランザクションはとっても簡単
- Linear Typesとは何か
- スマートコントラクト言語のセキュリティの仕組み②
- 最新ブロックチェーンの情報取得は無料でJavaScriptでとっても簡単
- ブロックチェーンゲームのデモビデオ
- Playground攻略でスマートコントラクトの雛形を作成する!
- 後はfclという専用のライブラリでトランザクションかscriptを実行するだけ
ブロックチェーンでこれが出来る!
スマートコントラクト言語のセキュリティの仕組み1
アカウントとは日本語で口座という意味で、ブロックチェーンではユーザー一つ一つが持つものもアカウントと言います。そこにNFTやコインなどの資産を紐解けます。Linear Typeを資産(Resource)が性質として持っているSui, Aptos, Flowの3つのブロックチェーンは、資産が文字通りアカウント間で動きます。
(ストレージはアカウント毎に用意されています)
これを知ったら次の技術は間違いなくブロックチェーンだと思っちゃいますよね。特にFlowブロックチェーンはGo言語で出来てるため誰にとっても書きやすく(easy to write)、シードフレーズのような詐欺の温床になるようなものが無く安全で、世界中の人がデジタル資産として猫の帽子を持つようなブロックチェーンの魅力を味わってほしいという製作者の感性を味わえます。彼はAppleでスティーブ・ジョブズの元でKeynoteを開発していたので、万人が愛する製品の開発を得意としており、その製品は一度味わうとずっと使いたくなる魅力を持っています。
あと、Cadenceが完璧なプログラミング言語なのも凄いですよね。他のブロックチェーン言語とは雲泥の差です。
プロジェクトの安全対策がわかりやすく設計されています!
スマートコントラクトで資産を作ってみる
スマートコントラクトとはコンピュータプログラムです。ビットコインも単なるプログラムですが、これらビットコインに代表されるトークン(日本語だとお札)をアカウント間で条件に従って自動で移動させるプログラムの事をスマートコントラクトと言います。
トークンだけではなく、NFTでも、何か機能を持ったコピー出来ない何かでも、プログラムで移動できます。
NFTも元々は、何か機能を持ったコピー出来ない何か、だったので、工夫次第で次のNFTを作れます。
これ(コピー出来ない何か)を作れるのがSuiやAptosなどLibraから引き継いだMove言語で生み出すリソースであり、Flow BlockchainのCadence言語が生み出すリソースです。(Rust言語にはLinear TypeがBuilt-inで存在するのでそれをFacebookの開発陣は活用したか)
リソースは、NFTにもビットコインのようなトークンにもなれます。また、これら既に価値があるものを動かすものもリソースで作れます。価値は他のリソースに任せてそれを条件に従って移動させるものもリソースです。
だから最初に書いた通り、スマートコントラクトはコンピュータプログラムであり、そこから生み出すリソースは価値があるか、それ自体はないかもしれないがコピー出来ない”もの”なので、所有者に権利を与える”もの”です。そのリソースをゲームプレイヤーとして作れば、トークンでゲーム内通貨を買い、ゲーム内通貨で勝敗を増やしていき、賞金を獲得するといったことが個人で可能なのです。
スマートコントラクト凄いですね!
ではちょっとリソースの記事も見てみませんか?
トランザクションは普通のユーザーには難しいかも
スマートコントラクトの開発は、関数をリソースの内部に定義して、保持したい値をリソースの内部でフィールドとして宣言します。そしてリソースの内部にinit
関数を作ってフィールドに初期値をセットする処理を書きます。(この時init
関数には引数を渡せます)
ユーザーがウォレット経由でトランザクションを実行した時、このリソースを作成して(init
関数が呼ばれます)ユーザーアカウントのストレージに保存します。(アカウントはウォレットが作成し、ストレージはアカウント生成と同時にブロックチェーン内部で作られます)
このトランザクションというのが、かなりITリテラシーを必要としますので、よっぽどでないとユーザーはしません。(お金が取られるかもしれない処理は誰でも慎重になって当然です)
だから、ゲームプレイヤーを作ります!とかゲーム内通貨を買います!ぐらいの時しかユーザーはトランザクションをしたがらないと考えてよく、その為、リソース作成時に実行されるinit
関数には必要な値を目いっぱい引数として最初に全て渡します。(例: 賞金の送金先アドレスなど。そうすることでユーザーが抵抗するトランザクションの回数を減らします。ゲーム内通貨を採用するのもトランザクション回数を減らす為です。ゲーム内通貨であれば運営側のトランザクションで増減が可能だからです。(スマートコントラクトでは運営のことをAdminと言います。スマートコントラクトをデプロイしたアカウントはこうした特権を持つことが普通で、そのスマートコントラクトをデプロイしたアカウントのことをAdminと呼びます。))
ブロックチェーンアプリの根幹部分。なのに分かりやすい。さすが元Apple上級エンジニアが作ったブロックチェーンですね!(トランザクション)
ウォレットアプリで自由度の高い安全性を実現出来る方法が記載されています。👇
例えば、ユーザーがトランザクションに署名して送信する際に使用する(ウォレット)ソフトウェアは、トランザクションを分析し、人間が読める形で説明することができます。「このトランザクションは、AからBに30トークンを転送します。Aの残高は30トークン減少し、Bの残高は30トークン増加します」といった具合にトランザクション実行時にユーザーに注意喚起するウォレットアプリを作る事が出来ます
上記はウォレット側の実装な為トランザクションコードの解析という処理が必要になりますが、これを実装したウォレットは安全さを他ウォレットに対してアピールすることが出来ます
👆 最もセキュリティが敏感な場所なので、Flowのセキュリティについて詳細に書かれています。
トランザクションを実行するとリソースがPathに保存される
ブロックチェーンの強みは承認さえ押してもらったらお金を支払って貰えることです。賞金でもそうですが、返金も簡単です。逆をすればいいだけです。スマートコントラクトをデプロイしたアカウントは管理上しっかりプライベートキーを保存する必要があります。そこで、機能の一部を他のアカウントに移譲する事が出来るので、その機能の一部を受け持ったアカウントを運用アカウントにします。(すぐ下で解説致します)
前置きが少し長くなりましたが、その運用アカウントが承認することで返金処理をします。(それだけでなく、文字通り誰でも出来ます。ビジネスDAppを作ればユーザーがアプリで稼いで返金もユーザーが承認さえ押せば出来る完全分散型アプリを作れます)
このお金の流れは全てのビジネスに活用できるはずです。なぜなら手数料が0で出来るからで、信じられない機会です。
この運用アカウントを安全に、分かりやすく、最初から用意してくれているのがFlowとそのプログラミング言語Cadenceです。作者はAppleの従業員時代から、この直感的に利用できる使いやすさをスティーブ・ジョブズから言われてました。
ユーザーが安心して使えるウォレットを提供する事が得意な会社、Bloctoは昨年日本法人を設立してあり、FlowBlockchainは他には無い有利さを有しています。
☝直感的にトランザクションを実行できるのがこのPathのおかげです。他のブロックチェーンと違い、文字通りリソースをstorageのパスに保存するので、直感的にリソース関数を呼び出せます。
👆 インターフェースでリソースの関数を絞ってpublicパス配下におきます。インターフェースが無いとリソース全体がCapabilityになります。
⇨これはCOF.ninjaでCapabilityを作ってる所です(v1.0でなくて申し訳ないです..)
(この行の1行上は賞金や返金の為のユーザーへの振込口(アドレス)を、リソース作成と同時にスマートコントラクトに保存している所です。ユーザーはトランザクションが多いと抵抗感を感じるのでこのように一度にしています)
インターフェースは、次のようにして型として使用できます。{I}という型は、インターフェースIを実装する全オブジェクトの型になります。この型はこのインターフェースの機能(メンバーおよび関数)にしかアクセスできなくなります。
👆 Version 1.0の新機能です。「AさんにならこのCapability使っていいよ、とトランザクションを実行し、AさんはそのCapabilityを下さい、というトランザクションを実行する」、これだけで運営用アカウントが作れるという、とても直感的になりました。
以前は (以前作ったビジネスDAppのコントラクトのここのように) Private Capabilityを作ってそれに機能群を渡す関数を作る必要があったのですがもう必要ありません。
Cadence v1.0凄い!
最新ブロックチェーンFlowのトランザクションはとっても簡単
https://github.com/temt-ceo/CODE-of-flow/blob/master/aws_lambda/src/index.js
これはCOF.ninjaのAWS Lambdaにアップロードされるzipファイル内のトランザクションコードです(ユーザーがゲーム内通貨を購入するスマートコントラクトのbuy_en関数はユーザーのウォレットからトランザクションしてもらう為、フロントエンドにあります。こちらです)。GraphQL、gRPC同様専用フォーマットを使いますが非常に親近感のある文法です。
どちらもVersion1.0の書き方に書き換えないといけないのですがこのスマートコントラクトが3000行近くもあり諦め..
Linear Typesとは何か
Linear TypesとはFlowとLibra(今のAptosとSui)だけが持つ資産の移動方法です。
最新ブロックチェーンFlowには資産の移動と安全デプロイの為に、Linear Typesが実装されています。
これはイーサリアムが実は資産をコピーできた為、これへの対応を考えた時に導入された、コンピュータサイエンスの一分野です。
Flowを開発していた人は論文を読んでこれをCadenceスマートコントラクト言語に組み込みました。
Cadenceのresource は<-という演算子を使わないと変数等に値を渡せないのですが、この<-演算子が内部でLinear Typesとして働き、値が移ると元の変数からは値が消えます。
Flow Blockchain以外にもLibraを引き継いだAptosとSuiにもLinear Typeがあります(どちらもLibraのMove言語を使用します)
Linear Typesを採用した、Cadence、Move言語はまた、プログラミングコード中でリソースが保管されない状態(イーサリアムでよくあったゴックス状態)になるとそのトランザクションは必ず失敗します。これもLinear Typesの特徴でありその目的です。もしスマートコントラクトにそのようなコードがあるとそのデプロイ自体が失敗しますのでコード監査の負担は非常に軽減します。
スマートコントラクト言語のセキュリティの仕組み2
CadenceのインタフェースはJavaのインタフェースと全く同じであり、「ある機能を実現するクラスが実現するべきメソッドの名前や型といった作法のみを定義するもの」です。(クラスの部分をリソースやStructで置き換えてもらって全く同じ仕様です)
このインタフェース自体も型として利用出来る為(Cadenceではリソース宣言も型なので同じリソースは違うスマートコントラクト内では作れない)、インターセクション型{I} として(鉤括弧で囲みます)リソースの後ろにつけてCapabilityを作ります。Capabilityを作って何するの?というと、1番大事なものとして、リソースのIDを取得します。
あとはぶっちゃけ無くても。。(スマコンに保存した情報を取得したいだけならスマートコントラクト直下の関数を呼び出すだけでOKなのでIDさえとれれば後はディクショナリ型から詳細情報を読み取ればいいからです。)
storageパスに入ってるリソースには本人しかアクセスできない為、最低限id をインタフェースに含めて作成します。それを型としてCapabilityをpublicパスに保存する事でその情報をどこからでも読み取る事が可能です。
どのみちリソースは本人しか移動出来ませんので、そこまで安全に気を配る必要はない気もします
トランザクションは権限が巨大(リソースを移動できる)なので、気にする必要がありますが..
セキュリティ対策をわかりやすく!
👆トランザクションはアカウントに対しあらゆる操作が出来ます故、監査(するシステム)は必要と述べられています。システム対応ですとウォレットレベルの対策が必要です
👆一つのアカウントだけ(Admin)がロジック処理をする必要がある場合は、そのリソースはinit内でしか作成させない、といったはっきり見て分かるコードが好まれます。
これらのCapabilityはどこにでも保存できますが、ユーザーが使用を望まなくなった場合、getControllersメソッドでアカウントからCapabilityコントローラを取得し、それを無効にすることができます
参考になるか分かりませんが、私が作ったスマートコントラクトがこちらにあります。(コードはv1.0のものではありません)
Tickets(ビジネスdApp)
ESports(ゲームdApp)
Ticketsのurlは https://tickets-onchain.com
Esportsに関してはこちらに開発手法が載っています
最新ブロックチェーンの情報取得は無料でjavascriptでとっても簡単
Svelteでブロックチェーン情報を読み込む時はこのファイルを使用します。
Capabilityから情報を取得する時にリソースの後ろにインタフェースを{}で囲ってしていますよね?これがインターチェンジ型という型の一種になります。
Capabilityをpublicパスに保存させる時にこのインターチェンジ型を指定してあるので、このインタフェース内しかアクセスが出来ないというアクセスコントロールがCapabilityを作成する時に出来ています。
また、これはCOF.ninjaのFlutterプロジェクトのwebフォルダの index.html
内で読み込んでいる index.js
です。fcl.jsはES6フォーマットですがこのようにコンパイルすることで普通のindex.htmlでも読み込めます。全ての(2015年以前のでも)htmlからブロックチェーン情報を読み込む事が可能なのです。コンパイルの仕方はこちらに載っています。
どちらもVer1.0になり書き換えないといけないのですがCOF.ninjaのコントラクトが3000行近くあるので..
ブロックチェーンゲームのデモビデオ
実際にゲーム勝利の賞金を受け取る様子が最後の10秒で見れます。
ちなみにどうやって賞金を受け取ったかを判定するか、は簡単で、所持金を1秒おきに見て増えたら賞金Getと判定します。
let account = getAccount(address)
let vaultRef = account.getCapability(/public/flowTokenBalance).borrow<&FlowToken.Vault{FungibleToken.Balance}>()
?? panic("Could not borrow Balance reference to the Vault")
var retArr: [CodeOfFlow.CyberScoreStruct] = []
if player_id != nil {
let cap = getAccount(address).getCapability<&CodeOfFlow.Player{CodeOfFlow.IPlayerPublic}>(CodeOfFlow.PlayerPublicPath).borrow()
?? panic("Doesn't have capability!")
let player_arr = cap.get_players_score()
let playerCyberData = player_arr[0]
playerCyberData.balance = vaultRef.balance
retArr.append(playerCyberData)
if player_arr.length >= 2 {
retArr.append(player_arr[1])
}
return retArr
}
let guestData = CodeOfFlow.CyberScoreStruct(player_name: "Guest")
guestData.balance = vaultRef.balance
retArr.append(guestData)
return retArr
こういうCadenceのコードを書きます。($FLOW所持金だけなら数行、ゲーム内通貨残高も知りたいならこれぐらい書きます。複数情報を取るので配列に入れてます)
{CodeOfFlow.IPlayerPublic}の部分がインターフェースです。インターフェースはエンジニアお馴染みですね。
getAccountはグローバル関数です。Scriptというブロックチェーンの情報取得を行うところで書くとアカウントの情報を取得できます。
あとVersion1.0で少し変更あったので上記は動かないです。
Playground攻略でスマートコントラクトの雛形を作成する!
コードを書かない人でもわかるやり方(Jacob君の2021年のビデオ)
Let’s try!
シンプルに先週紹介したコードでPlayground上で作ります。私も一から作るのは一年ぶりです。Flowのサイトを見てもチンプンカンプンですから、Jacob君のYouTubeを見ます。
@jacobmtuckerで検索。ver1.0だろうがなんだろうが2021年のが1番分かりやすいのでそれを見ます。
彼のチャンネル上で「動画」タブをクリックして「古い順」をクリックして一番上の段の右端に「Learn Cadence (Part 2) - Intro to Smart Contracts」があるのでそれを見ます。YouTubeの検索窓に「Learn Cadence (Part 2)」と入れて検索するだけでも一番上に出ます。
3分目ぐらいから「FlowのPlayground」を使った画面が現れますのでそれを見ながら作業できるように、「FlowのPlayground」で検索して一番上に出たサイトを開きながら見ます。
①3分目でJacob君が言っているようにPlaygroundサイトのコメントを削除します。
②気分を入れるために1行目のコントラクト名をAwesomeCardGameに変えます。
③6分30秒でJacob君が言っているようにdeployボタンを押します。(Macの人はSafariブラウザでやってください。)左端の一番上のアイコンにAwesomeCardGameと表示されます。
④7分目でJacob君が言っているようにScriptの下のGetGreetingをクリックします。赤字になっているところをAwesomeCardGameにコピペで全部置き換えます。
⑤Executeボタンを押します。"Hello, World!”と表示されます。(エミュレータ上ですが初めてブロックチェーンから情報を取得しました🎉)
⑥そのままYouTubeを見てPart3を見ます。
⑦4分目でJacob君が言っているようにTransactionsの下のChangeGreetingをクリックします。赤字になっているところをAwesomeCardGameにコピペで全部置き換えます。
⑧右にポップアップが出てますので「Goodbye, world!」と入れてみてSendボタンを押します。(もしエラーになったらContractsに戻ってデプロイボタンの上に表示される🔺をクリックして0x07にデプロイして、Transactionsもimportの右端を0x07に変えてください。ver1.0になって間もなくなのでリソース足りてないんですね) Cadence log: 0x0000000000000007と表示されます。(エミュレータ上ですが初めてブロックチェーンにトランザクションを実行しました🎉)
⑨⑤に戻って同じようにしてみましょう。(0x07のスマコンに対して⑧を実行したのであれば、importの右端を0x07に変えてください)「Goodbye, world!」と表示されます。エミュレータでなければ世界中でこれが無料で取得できます。(トランザクションは実行者を選べましたが、Scriptsは選べません。誰でも無料で取得できるからです。Flowのリソースが不足しているようですので、誰かコントリビュータを派遣してください)
➓後は自分のやりたいようにやるだけ。2021年の時点でこれが出来たんです。NFTブームのせいでEthereumのずっと後塵を拝しましたが。(あとLukeのせい。彼には気をつけて)
AwesomeCardGameに戻って2行目に
access(self) let playerDeck: {UInt: [UInt16]}
を、13行目のinit(){の下に
self.playerDeck = {}
を書きます。Deployボタンを押します。(上手くいかないなら0x08で試します)
access(all) resource Admin {
access(all) fun save_deck(player_id: UInt, user_deck: [UInt16]) {
if user_deck.length == 30 {
AwesomeCardGame.playerDeck[player_id] = user_deck
}
}
}
というのをどこでもいいので書きます(12行目辺り)
11)以下を3行目に
access(self) let AdminStoragePath: StoragePath
以下を25行目辺り(initの下)に書きます
self.AdminStoragePath = /storage/CodeOfFlowAdmin
self.account.storage.save( <- create Admin(), to: self.AdminStoragePath)
Deployボタンを押してデプロイします。
Transactionsに戻り、今デプロイしたアカウント(と同じ番号を右下の🔺で選択し、またそ)のアドレスをimportの後ろにセットします。
トランザクション全体として以下のように書きます。
import AwesomeCardGame from 0x06
transaction(id: UInt, cards: [UInt16]) {
prepare(acct: auth(BorrowValue) &Account) {
if let om = acct.storage.borrow<&AwesomeCardGame.Admin>(from: /storage/CodeOfFlowAdmin) {
om.save_deck(player_id: id, user_deck: cards)
}
}
execute {
}
}
右にポップアップが出てきますので1と[1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10]
とそれぞれ入力してSendボタンを押します。
これでデッキ保存機能をブロックチェーンに保存できました🎉。
ちなみ[Playgroundのコードは共有できます。こちらをクリックすればこのページに書いたコードを見れます。
後はfclという専用のライブラリでトランザクションかscriptを実行するだけ
因みにGraphQLやgRPCを開発で触った事がある方なら、通信方法が殆ど一緒だ、という感覚に襲われます。GraphQLもgql という専用の言語に対して専用のライブラリでメソッドを呼んで、GraphQLサーバーと通信します。
gRPCもそうですね。専用のフォーマットを用意して専用のライブラリでgRPCサーバーと通信します。Flow Blockchain はこれらモダン技術を使った事がある人にとってはよく知った技術という感覚に襲われます。 cadence言語というフォーマットを使って実行ノードと通信しているだけなのですから。また、いずれも速度が要求される通信であるため、速度要件に合わせた実装がされていると思われ、Flow開発陣の技術力の高さが伺えます。scriptやtransactionのコードをクライアント側に見立て、スマートコントラクトを実行ノード側(サーバー側)に見立ててOKです。
エラーになったらFlowScanでメッセージを確認して、もう一度Playground(CadenceをエミュレートしてくれるWebサイト)でエラーにならない方法を検証します。
情報が少ない時はこの方法が1番早いんです。エミュレータだとFlowScan使えないし..(今はどうか知らない)
(NFTは元々クリプトキティズというゲームの帽子とか鞄でした。ERC-721のコードに例として書かれてあります。因みに2017-2018年頃をYouTubeで検索すると、Deteが学会かワークショップで熱くNFTの意味を説いているのが見つかります。猫の帽子を大の大人が連呼するので、女性から笑いが生まれてます。NFTは今でこそ知られるようになりましたが、最初は1人の男性が猫の帽子に熱く情熱を込めたものだったのです。動画はこちら💁。 この人が世界で初めてブロックチェーンゲームを、NFTを作り、FlowとCadenceを作り、あとAppleのKeynoteを開発してた人です。ブロックチェーン業界のレジェンドです)
ここまで読んだあなたならもう出来るはず、Let’s try!
あとこれ!10/1(火)に出されたブロックチェーンゲーム(aiSports)のスマートコントラクトですがFlowトークンによるリワード配布含めて、ほぼCadence で出来る事全て、 1行も無駄なく書かれててほぼスマコンの教科書 📗
このコントラクト読んでてCadence version1.0って美しいんだなぁって思いました。 Javaに近くなりましたよね。Javaに寄せたかったんだろうか.. 綺麗なコントラクト言語になったと思います。二度とsolidity触りたくなくなる。
ほんとにCadenceで出来る事全てがこのコードに詰め込まれてて凄すぎです。
最後にお願い。Flow BlockchainがGraphQLやgRPCと同じ技術という事はご理解頂けたかと思いますからVer1.0の技術ブログ書いてください。
滑らかなブロックチェーンゲームを作ってみたい、という方にはこちらの本をおすすめします☞
Previous << Cadence Testing Framework
Flow BlockchainのCadence version1.0ドキュメント (Values and Types)