Substrate / Polkadot
Cosmosと並び、異なるブロックチェーンのインターオペラビリティ(相互運用性)で注目を集めているPolkadotについて、試してみました。
インターオペラビリティは、Substrate というフレームワークで実装されますが、これを体験できるPlaygroundがあります。(Node Templateを使用)
https://docs.substrate.io/playground/
Githubアカウントでログインすると、VisualStudio(?)がWebで現れ、ブロックチェーンが起動します。ターミナルを開き、コンソールコマンドも実行できます。CTL-Cで停止でき下記コマンドで再起動できます。
./target/debug/node-template –dev –ws-external
再起動すると新規作成されるため、ブロックチェーンの更新を保持したい場合は、
./target/debug/node-template –dev –ws-external –base-path=/tmp/<任意>
とします。
メニューからPlayGroundを選択すると、新規タブでUI(DApp)が開きます。
6秒ごとに新規ブロックが作成されていきます。
デフォルトでPlaygroundをエンドポイントとしていますが、これ以外のネットワークにもスイッチできるようです。
開発アカウントと残高があかじめ用意されています。今回テストのため一番下の”Tibit”を追加しAliceから送金してみました。
次に今回やりたかった、ストレージへの保存と参照を動画を参考にトライしてみました。
後で説明しますが、doSomethingというメソッドに値を入力するようなイメージになります。
アカウントを作成するとき(説明を省略しましたが他の例にもれずニーモニックの保存やパスワード作成があります)に使用したパスワードを入力します。(開発アカウントの場合はなし)
次にチェーン状態を確認します。
確認できました。これを実行している箇所が以下になります。
動画では、これをカスタマイズしてタイトルやアカウントIDを保存できるようにしています。その際コードの更新を通知するために以下のバージョン情報をインクリメントするようです。
recent eventsでは、履歴をみることができます。
これは、新規でブロックチェーンを起動しても残っているようです。(Playgroundのセッションを終了すれば消えます)
まだ一部の機能しかさわっていませんが、実際の開発する様子がイメージでき、ツール類がよくできていると感じました。
Polkadotの実験ネットワークにKusamaというものがありますが、水玉(Polkadot)模様のアートで有名なアーティスト草間彌生氏からとられたものだといわれています。Blockchain界隈、日本にゆかりがあるものをよく目にします。もともとBlockchain論文の作者がサトシナカモトなのもそうですが、Cardanoプロジェクトの創始者も日本在住だったと聞いています。そのわりに日本の税制がこの業界に厳しく有能なベンチャーが海外に出てかざるをえない状況は皮肉なものです。Polkadotのパラチェーンを運営するAsterNetworkもその一つです。通貨というものが国家のあり方と密接にかかわっているからでしょう。こういった世の中の動きを見ているとこの業界が今とてもホットだということがよくわかります。
国家のあり方といえば、今週ロシアがウクライナの領土に侵攻しました。武力でNATOよりロシアに友好的な国家にすることが目的のようですが、こういう専制主義的、19,20世紀的なやり方に世界中の大勢の人は抵抗を感じるのではないでしょうか。非難するとともに即時撤退を願います。NFTなど物理的なモノからデジタルなモノに、物理的な領土からメタバースの土地に、会社などの組織からDAO(分散型自律組織)に価値感が移転しつつある非中央集権的なシステムBlockchainが、これだけ盛んになってきているのは、これからの時代を暗示しているからだと思います。ロシア・中国は特にマイニングをはじめとするBlockchainプロジェクトが盛んですが、これも皮肉です。
経済制裁によって取引が制限されると、Bitcoinなどの暗号通貨が使われるともいわれていますが、ウクライナに侵攻した途端、一時的にですが価値が暴落したことがまだリスク資産という位置づけであることのあらわれといわれています。
いずれにしろBlockchainをとりまく環境は、ホットであることは間違いないと考えます。
参考動画
Moralis Web3 Platform
これまでBlockchain自体の投稿が多かったのですが、もう一つ上位に位置するBlockchainを利用したアプリの開発プラットフォームについて、”Build Metaverse Unity Web 3.0 App with C#” というとても気になる動画を見つけたので試してみました。
Unityで作られたMetaverseのプログラムと各種ブロックチェーンを連携するライブラリの使い方の説明がされています。
Metaverseといえばアイテムの売買などでNFTが活用される典型的な例ですが、ここまでライブラリができているのかと、ちょっと驚きました。
ここではゲーム中に表示されるQRコードを読み取り、Walletと連携しています。連携できている証拠としてウォレットアドレスをキャラクタの上に表示します。
手順は、まずmoralis.io のアカウントを作り、接続するサーバの作成やブロックチェーンの選択をします。動画のとおりEthereum メインネットで、TrustWalletを使用して実践しました。
Unity側で必要な情報として、サーバは”Veiw Details”をクリックして、Server URL, Application IDを取得。
ブロックチェーンエンドポイントWeb3 Rpc Node URLは、Speedy Nodesから取得します。
iPhone App TrustWalletの設定から”WalletConnect”を選択し、カメラで上のQRコードを読み取ります。(このQRコードの元になっているのは下記ソースのURL。別のQRコードアプリで確認するとメタマスクの起動を要求された。)
Walletと連携後アドレスが表示されました。
QRコードを生成する部分は以下。
ログインが成功するとアドレス表示。
Unityは、プログラミング教育ブログなどでもよく使っており、C#でDAppが作れることで世界が広がります。
これまでのOSでいうところのクロスプラットフォーム開発が、もうブロックチェーンでも起きているということなのでしょうか、どのチェーンかということを意識せず、DAppが作ることができるようです。
この分野、急速に変化していることを感じます。
Starport / Cosmos
今回は、Cosmosの開発環境Starportについて試してみました。
参考: https://docs.starport.com/guide/hello.html
環境: Go 1.17.6, npm 8.1.2, node 16.13.1/Ubuntu20.4/WSL/Windows 11
インストール
sudo curl https://get.starport.network/starport! | bash
starport scaffold chain github.com/cosmonaut/hello
cd hello
starport chain serve
ひとまず動作確認。(AliceとBobのアドレスとニーモニックひかえる。二回目以降は以下のように表示しない)
参考ページにあるように、POSTでtitleとbodyを返すAPIを作成するためコマンド実行。
starport scaffold query posts –response title,body
コマンドを実行するとソースが自動的に変更・追加されます。(git diffで確認。下記は手動で変更)
x/hello/keeper/grpc_query_posts.go
func (k Keeper) Posts(c context.Context, req *types.QueryPostsRequest) (*types.QueryPostsResponse, error) {
//...
return &types.QueryPostsResponse{Title: "Hello!", Body: "Starport"}, nil
}
x/hello/module.go
import (
"encoding/json"
"fmt"
//..
"context"
...
func (AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) {
types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx))
}
Code language: JavaScript (javascript)
もう一度チェーン立ち上げ、下記URLをブラウザでアクセスします。(チェーンを立ち上げっぱなしでコード変更しても動いた)
http://localhost:1317/cosmonaut/hello/hello/posts
ちなみに下記コマンドでも動作するとありますが、そのような実行モジュールがみあたりませんでした。
hellod q hello posts
http://localhost:1317/ にアクセスしてAPIコンソールからも確認することができます。(それぞれクリックするとパラメータを入力する画面がでてきてリクエストを投げることができる)
ちなみにTendermint Node (http://localhost:26657/)は下記画面。
次に、フロントエンドを立ち上げて、AliceからBobに送金してみます。(下に参考動画: バージョンが違うためかコマンドが若干違うのと、上記の流れで作成しているのでネットワーク接続が動画どおりにできず)
cd vue
npm i
npm run serve
http://localhost:8080
AMOUNT 1 でBobに送金した後の画面。WalletはKeplrでChormoe Extensionのものを使用。(最初に控えたAliceのニーモニックを入力して作成)
次に、先ほどのAPIコンソールで、AliceとBobのBalanceを確認しました。
1 ATOM(?)送金されていることは確認しました。(小数入力できなかった)
この画面で、Cosmos Hubを選択しても何も変化が起きなかったためか、うまく接続できていないのかもしれません。(そのためにWalletの方には残高が反映されていない)
コマンド一つでブロックチェーンを作れてしまうのはなかなか強力なツールです。いろいろとやりたいことがでてきますが、今回はここまでとします。
Solana in Rust & TypeScript
Solanaの開発環境について、動画を参考に動作確認とSolanaのウォレット、Phantomとの連携を試してみました。
https://github.com/solana-labs/example-helloworld
環境: Cargo 1.57.0, node 16.13.1 / WSL / Windows 11
インストール
sh -c “$(curl -sSfL https://release.solana.com/v1.9.5/install)”
export PATH=”/home/k/.local/share/solana/install/active_release/bin:$PATH”
solana config set –url localhost
solana-keygen new -o /home/k/.config/solana/id.json
solana-test-validator
Solana CLIをインストールしてデーモンが立ち上げます。そして別コンソールで、オンチェーンコード(Rust or C。ここではRustを選択)をビルド(SharedObject生成)、これをデプロイして、オフチェーンコードのTypeScriptを実行します。
npm install
npm run build:program-rust
solana program deploy dist/program/helloworld.so
npm run start
デプロイのとき、コインがないとエラーがでるので、エアドロップのコマンドを実行して受け取ります。(とりあえず10 SOL)
solana airdrop 10
これで実行されるのは、main.tsです。処理の詳細はhello_world.tsに記述されています。ここではコンソール実行していますが、TypeScriptで書かれているのでWebにもっていきやすいです。オンチェーンコードとオフチェーンコードがコンソールで一通り動作確認できるのは、使いやすいと感じました。
次に、Phantomウォレットとの連携ですが、ウォレットで秘密キーのimportができないので(ニーモニックのimportは当然できる、秘密キーのexportはできるのに・・なぜ)、ウォレットのニーモニックからキーペアを生成して、ここまでで生成したアカウントに上書きします。
参考
[recover] seed phrase .. でウォレットのニーモニックをコピペします。
ウォレットは、ローカルホストを選択します。ウォレットのアドレス(あれ、Localhostの表示がかぶっている^^ ; )とコンソールコマンドでアドレスが一致していることを確認します。また最近の活動はトランザクションIDなので、下記のようにコードを変更して確認できます。(TX: )
export async function sayHello(): Promise<void> {
console.log('Saying hello to', greetedPubkey.toBase58());
const instruction = new TransactionInstruction({
keys: [{pubkey: greetedPubkey, isSigner: false, isWritable: true}],
programId,
data: Buffer.alloc(0), // All instructions are hellos
});
let tx = await sendAndConfirmTransaction(
connection,
new Transaction().add(instruction),
[payer],
);
console.log("TX: " + tx);
}
Code language: JavaScript (javascript)
このような記事を書くとき、いろいろと試しながらやるため手順が前後してしまい、わかりづらくて・・m(_ _)m
C言語でも記述できてしまうところが拡張性を考えたとき面白いのと、Rust + TypeScript の組み合わせはなかないいと思いました。
参考動画
Blockchain in Rust
ブロックチェーンのしくみをもっと実装ベースで理解したいといろいろ調べていたところ、まさにそのものである学習用のRustを使ったコンパクトに実装されたコードとそのデモ動画があったため試してみました。(Solanaのような新しいブロックチェーン開発で使うRustとはまた別の話。いづれテスト予定)
https://github.com/GeekLaunch/blockchain-rust
参考書籍: 「ビットコインとブロックチェーン」(NTT出版)
参考動画: (最下部にリンク)
block作成、blockchain作成、トランザクション作成の機能がそれぞれモジュール化されており、main.rsファイルでそれらを利用して自由に作ることができるようになっています。
main.rs
use blockchainlib::*;
fn main () {
let difficulty = 0x000fffffffffffffffffffffffffffff;
let mut genesis_block = Block::new(0, now(), vec![0; 32], vec![
Transaction {
inputs: vec![ ],
outputs: vec![
transaction::Output {
to_addr: "Alice".to_owned(),
value: 60,
},
transaction::Output {
to_addr: "Bob".to_owned(),
value: 30,
},
],
},
], difficulty);
genesis_block.mine();
let mut last_hash = genesis_block.hash.clone();
let mut blockchain = Blockchain::new();
blockchain.update_with_block(genesis_block).expect("Failed to add genesis block");
println!("{:?}", blockchain);
let mut h = last_hash.clone();
let mut block = Block::new(1, now(), last_hash, vec![
Transaction {
inputs: vec![ ],
outputs: vec![
transaction::Output {
to_addr: "Min1".to_owned(),
value: 20,
},
],
},
Transaction {
inputs: vec![
blockchain.blocks[0].transactions[0].outputs[0].clone(),
],
outputs: vec![
transaction::Output {
to_addr: "Alice".to_owned(),
value: 40,
},
transaction::Output {
to_addr: "Bob".to_owned(),
value: 10,
},
],
},
], difficulty);
block.mine();
last_hash = block.hash.clone();
blockchain.update_with_block(block).expect("Failed to add block");
println!("{:?}", blockchain);
let mut block2 = Block::new(2, now(), last_hash, vec![
Transaction {
inputs: vec![ ],
outputs: vec![
transaction::Output {
to_addr: "Min2".to_owned(),
value: 30,
},
],
},
Transaction {
inputs: vec![
blockchain.blocks[1].transactions[0].outputs[0].clone(),
],
outputs: vec![
transaction::Output {
to_addr: "Alice".to_owned(),
value: 9,
},
],
},
], difficulty);
block2.mine();
last_hash = block2.hash.clone();
blockchain.update_with_block(block2).expect("Failed to add block");
println!("{:?}", blockchain);
}
Code language: PHP (php)
実行結果
デモとは違い出力内容をかなり変えています。(下記変更)
blockchain.rs
#[derive(Debug)]
pub struct Blockchain {
pub blocks: Vec<Block>,
unspent_outputs: HashSet<Hash>,
}
Code language: HTML, XML (xml)
println!("coinbase output value: {:?} total fee: {:?}", coinbase.output_value(), total_fee);
if coinbase.output_value() < total_fee {
return Err(BlockValidationErr::InvalidCoinbaseTransaction);
} else {
block_created.extend(coinbase.output_hashes());
}
Code language: PHP (php)
ブロックチェーンを更新する際に、コインの計算が合わないとエラーになります。
最初はジェネシスブロックで、そこに追加していきます。それぞれのブロックの最初のトランザクションはコインベーストランザクション(INPUTなし)で、マイニングに勝ったマイナーによっておかれることを表現しています。unspent_outputs: にあるハッシュを見てみると、消費されたアウトプットは次になくなっていることも確認できます。
ブロックチェーンの基礎を勉強する教材としてとても素晴らしいため、自分用メモとして残しておきたいと思いました。