ホーム

Nix-Bitcoin

Bitcoin,Lightningノード は下記で動かしたことがありますが、いろいろと面倒でした。

http://bitlife.me/bc/2022/01/04/

http://bitlife.me/bc/2022/01/15/

下記動画で、簡単に立ち上げているのを見て試してみました。

NixOSとは何か、はまた別の機会・場所で取り上げるとして、ノードが簡単に立ち上がるかどうか、まずは動かしてみました。

https://nixos.org/download#

NixOSは上記を、VirtualBox7.0でうごかしました。(私の環境は画面とはちがい v23.05)

https://github.com/fort-nix/nix-bitcoin/blob/master/examples/README.md

上記サイトにならってコマンドを実行します。(画面は実行中・・)

. . .

これでVMがたちあがりました。プロンプトが緑から赤に変わっていますが、これでプロセスもネットワークも別のマシンが立ち上がったことがわかります。表示されたコマンドを実行して、ノードが立ち上がっていることを確認してみます。

上記のような結果となりました。具体的な動作は確認していませんが、なによりNixOSに好奇心がわきました。

デフォルトではsshdがインストールされていないので、スクリーンショット(VirtualBoxではとれなかった。ScreenCopyキーでNixOSのスクリーンショット機能がたちあがる。) を別のVirtualBoxのLinuxにScpでコピーして転送しました。(インストールは以下が参考になるかも)

NixOS、もっと掘り下げていきたいです。

BitcoinNFT Inscriptions

BitcoinでNFTが使えるという、とても興味深いニュースを見たので情報を整理してみました。
NFTはEthereumのスマートコントラクトの規格ERC-721で有名ですが、ついにBitcoinでもBRC-20という新しい規格で実装されました。(トークンの規格でスマートコントラクトではない。Ordinalsという仕組みの上で動作)


NFTで一番の不安は、画像などのデータがブロックチェーンに保存されるのではなくIPFSやホスティングサービスを利用することでした。IPFSが安定してアクセスできなかったり、ホスティングサービスが停止したりすると、いくらブロックチェーンが永続的であっても肝心のデータを紛失することになります。それゆえ一番分散がされていて安定しているBitcoinブロックチェーンにデータを刻むことができるInscriptionは、とても理に適っていると思います。

(画像がないものも多い)

下記「BRC-20とは?ビットコインのトークン規格がもたらす可能性と課題」https://coinpost.jp/?p=459652 より引用。

Inscriptionとは
刻印(Inscription)は、OrdinalsとBRC-20で使用される方法で、ビットコインのトランザクションのウィットネスフィールドにJSON(JavaScript Object Notation)形式のテキストファイルを記述するプロセスを指します。これにより、各サトシにトークンデータを関連付けて記述することが可能になります。

「刻印」されたサトシは、通常のビットコインと同じように扱うことができます。つまり、トランザクションで送受信したり、ビットコインのアドレスに保管したりすることが可能です。

ただし、これら特別なサトシを送信する際には、特定のルール、すなわちOrdinalsプロトコルに従う必要があります。これにより、特別なサトシがどのトランザクションで使用され、どの順序で移動されたかを追跡できるようになります。これは、そのサトシの持つ独特な情報を維持しつつ、ビットコインのブロックチェーン上でのその動きを確認するためのものです。

ウィットネスフィールドとは
Segregated Witness(SegWit)と呼ばれる技術の一部として導入された概念。トランザクションに関連する追加のデータを含む特定のフィールドです。

このようにビットコインの新しいアップデートで可能になった機能を使って実装しているため、複雑なことはできず、トークンの送受信などは専用のツールを使って行われるようです。(スマートコントラクトによるものではないという意味)

下記「ビットコインNFTとは?「Ordinals」が実現するNFTの特徴と仕組みについて解説」https://coincheck.com/ja/article/557  より引用

Segwit方式では、Legacy領域と比較して書き込むデータコストが4分の1で済み、さらに1ブロックに詰め込むことができる最大データの容量が4倍(4MB相当)になるというメリットがあります。

ビットコインNFTの具体的な発行コストは、画像データ100KBの書き込みにつき、通常「約7.5〜15ドル」です。

ビットコインNFTの発行コストは手数料相場に大きく左右され、2satoshi/vBで試算すると上記のコストとなります。高い手数料(およそ20satoshi/vB以上)を払えばすぐに発行できる一方で、発行までに時間がかかっても問題ないのであれば、安い手数料でイーサリアムNFTよりも安価に発行することができます。また、最安の手数料水準である1satoshi/vBの場合は、さらに半額である7.5ドルで100KBのビットコインNFT(Inscriptions)を発行できます。

注意点としては、ビットコインの価格が上がれば15ドル以上の手数料がかかってしまう可能性もあります。そのため、必ずMempool(メンプール)の取引手数料水準を確認した上で、適切な手数料レートを設定するようにしましょう。

詰め込むことのできるファイルの最大サイズは4MBということでしょうか。NFTでの活用がすすむとネットワークが重くなるのではという心配もありますが、通信インフラの性能向上もされていくのでチェーンも維持されていくのでしょう。(機能の増加と性能の向上はともに進む。Windows OSがいつまでたっても重いように・・)

下記動画では、実際にNFTを書き込むまでの手順が紹介されています。

bitcoinデーモンを起動させて、ブロックチェーンの同期、インデックス作成、ord walletにbitcoinの送金などの説明があります。

https://github.com/casey/ord

このブログでもbitcoinフルノードの構築をやったことがあります。

Lightning Network」http://bitlife.me/bc/2022/01/15/

Bitcoin Core」http://bitlife.me/bc/2022/01/04/

最初の動画でテキストファイルを’inscribe’していますが、テキストなのになぜ画像が表示されているのだろうと思い実際に確認したところ、絵文字と特殊フォントの文字でした。

https://ordinals.com/inscription/801beb5fd41d3aba56baebcc2b6aadf591d1f526789c148e7ae4273ba11c6cbbi0

下記サイトの画像がないJsonオブジェクトが表示されるだけのものは、NFTではなくコインのものなのでしょう。

https://ordinals.com/

また下記の動画では、BRC -20コインの購入の仕方が詳しく説明されています。

Etheriumでいうガス代、NFTを買うような感覚がOrdinalsではどうかとか、またフリーミントなどトークンの仕組みについて理解が深まります。

Core Blockchain

通常のブロックチェーンはインターネットの通信インフラを前提に構築されますが、このCore Blockchainというのは、通信インフラの構築もカバーするというとても野心的なプロジェクトです。スマホや独自デバイスを使ったP2Pのメッシュネットワークも開発されており、たとえインターネットがなくても機能するというシステムになっています。このあたり豪華な創業メンバーのインタビュー、オフィスの訪問、そのしくみなど、下記の動画のシリーズで意欲的に説明されています。

https://www.youtube.com/watch?v=cYj5F39Tv5A

省電力で動作するデバイスに魅力を感じますが、これが実現できれば素晴らしいと思います。また下記の動画で、実際にマイニングをしたものがあります。マイニングというとProof of Workのビットコインをイメージしますが、ノードをたてて同期させ、されにマイニングとなるととてもコストがかかります。ところがこれが簡単にできるようなので、私も実際にためしてみました。

手順)

https://blog.coreblockchain.cc/posts/iot/mining.html

ウォレットの作り方)

https://github.com/core-coin/wallet-generator

ウォレットジェネレータダウンロード)

https://github.com/core-coin/wallet-generator/releases/download/v1.22.0/wallet-generator-linux-x86_64

マイニングアプリダウンロード)

https://github.com/catchthatrabbit/coreminer/releases/download/v0.19.72/coreminer-linux-x86_64.tar.gz

環境)Ubuntu 22.04

まずウオレットを作ります。

上記バイナリを実行権限を与えて実行するとWebサービスが立ち上がるため、http://(host):8080にアクセスします。

次にダウンロードしたマイニングアプリを解凍して、./mine.sh として実行します。

項目を入力するとマイニングが始まります。

Virtual Boxで動かしていて、上はCPU1つ、下は4つです。(processing unitsで指定)

数時間ほどたって結果を確認しました。

XCBのバランスに変化がありました。(データがないときは下記の画面)

動画では操作しながら説明されていますので、わかりにくい場合はそちらを参考にしてください。しかしこのような動画、日本語のものは珍しいと感じました。あと気になる点としてはビッグプロジェクトのわりには、ここ半年くらいあまり更新がないことです。ということもあり更新が比較的新しいウォレットジェネレータをテストしてみました。

PoWは電力がかかるため環境面からも最近は敬遠されがちですが、ブロックチェーンの分散された特徴を維持するためには、理想の形だと思っています。これまでのブロックチェーンネットワークを維持するための報酬がモチベーション、という形から、メッシュネットワークを(も)維持するための報酬がモチベーションという形になると、通信インフラ自体を新しく構築、維持できることになります。これはとても興味深いです。

Lens Protocol

ソーシャルグラフを使ったサービスをブロックチェーン上で取り扱うプロトコルとして、最近目にしたLens Protocolを調べてみました。(下記参照)

今回、dappをつくるためのプロトコルということで、開発者として気になるところは、どのブロックチェーン上で動くものか、どんな開発環境で実装するのか、実行時のガス代はかかるのか、などです。





















引用ばかりになってしまいましたが、ポリゴンチェーンの環境(EVMのスマートコントラクトを利用)で、GraphQLを使って実装するようです。ガス代はポリゴン自体が負担の少ないチェーンになりますが、それに加えてできるだけ負担が少なくなる仕組みも用意されているようです。API呼び出しもアプリからやる方法とGraphQLのQueryが実行できるサイトが用意されています。

(GraphQLは、Enjinでもでてきました)

http://bitlife.me/bc/2022/03/26/

参照した動画(最下部)にはアプリの実装方法が詳しく説明されています。(上記RecomendedProfilesの実装部分のスクリーンショット)





GraphQLはコピペして利用しています。ドキュメントサイトでは、多数のAPIのQueryが用意されているので、それを編集してすぐに試すことができます。(データの書き込みには認証が必要)

プロファイルIDを指定して、データを取得するQueryを実行してみました。


このブログをはじめてちょうど一年たちましたが、たった一年ですがさまざまな出来事がありました。LUNAの暴落やFTXの経営破綻が暗号通貨市場に多大な影響を与えたせいで、ブロックチェーン業界のイメージに悪影響を与えた部分もあります。しかしながら Lens Protocolのような技術は着々と開発されており、新しい可能性を十分に感じています。まだまだ魅力的な分野にはかわりないでしょう。

参照動画

参考動画

Soulbound Token

イーサリアムの提唱者ビタリック・ブリテンの論文

https://papers.ssrn.com/sol3/papers.cfm?abstract_id=4105763

で話題となった”Soulbound Token(SBT)”。
簡単に言うと譲渡できないNFTというもののようですが、ブロックチェーンのまた新しい可能性を感じます。
ここでは、実際にそのトークンの実装を説明した動画をみて理解を深めたいと思います。(IDE(Remix)の使い方は以下と同様)

http://bitlife.me/bc/2022/04/29/

http://bitlife.me/bc/2022/01/09/

https://github.com/Dervoo/Soulbound-Token/blob/master/contracts/SoulboundToken.sol

// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; /** * An experiment in Soul Bound Tokens (SBT's) following Vitalik's * co-authored whitepaper at: * https://papers.ssrn.com/sol3/papers.cfm?abstract_id=4105763 * * I propose for a rename to Non-Transferable Tokens NTT's */ contract SoulboundToken { struct Soul { uint256 patientIdentityNumber; string identity; // name / surname string town; string street; uint8 streetNumber; string postCode; string sicknessIdentity; string lastTestRecord; string findings; string treatment; string treatmentIndications; string annotations; string plannedVisits; } mapping (address => Soul) private souls; // Souls created by operator mapping (address => mapping (address => Soul)) soulProfiles; // Anybody can create 1 profile for soul owners mapping (address => address[]) private profiles; // Addresses of people who created profiles for a soul string public name; string public ticker; // operation identity address public operator; bytes32 private zeroHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; event Mint(address _soul); event Burn(address _soul); event Update(address _soul); event SetProfile(address _profiler, address _soul); event RemoveProfile(address _profiler, address _soul); constructor(string memory _name, string memory _ticker) { name = _name; ticker = _ticker; operator = msg.sender; } function mint(address _soul, Soul memory _soulData) external { require(keccak256(bytes(souls[_soul].identity)) == zeroHash, "Soul already exists"); require(msg.sender == operator, "Only operator can mint new souls"); souls[_soul] = _soulData; emit Mint(_soul); } function burn(address _soul) external { require(msg.sender == _soul || msg.sender == operator, "Only users and issuers have rights to delete their data"); delete souls[_soul]; for (uint i=0; i<profiles[_soul].length; i++) { address profiler = profiles[_soul][i]; delete soulProfiles[profiler][_soul]; } emit Burn(_soul); } function update(address _soul, Soul memory _soulData) external { require(msg.sender == operator, "Only operator can update soul data"); require(keccak256(bytes(souls[_soul].identity)) != zeroHash, "Soul does not exist"); souls[_soul] = _soulData; emit Update(_soul); } function hasSoul(address _soul) external view returns (bool) { if (keccak256(bytes(souls[_soul].identity)) == zeroHash) { return false; } else { return true; } } function getSoul(address _soul) external view returns (Soul memory) { return souls[_soul]; } /** * Profiles are used by 3rd parties and individual users to store data. * Data is stored in a nested mapping relative to msg.sender * By default they can only store data on addresses that have been minted */ function setProfile(address _soul, Soul memory _soulData) external { require(keccak256(bytes(souls[_soul].identity)) != zeroHash, "Cannot create a profile for a soul that has not been minted"); soulProfiles[msg.sender][_soul] = _soulData; profiles[_soul].push(msg.sender); emit SetProfile(msg.sender, _soul); } function getProfile(address _profiler, address _soul) external view returns (Soul memory) { return soulProfiles[_profiler][_soul]; } function listProfiles(address _soul) external view returns (address[] memory) { return profiles[_soul]; } function hasProfile(address _profiler, address _soul) external view returns (bool) { if (keccak256(bytes(soulProfiles[_profiler][_soul].identity)) == zeroHash) { return false; } else { return true; } } function removeProfile(address _profiler, address _soul) external { require(msg.sender == _soul, "Only users have rights to delete their profile data"); delete soulProfiles[_profiler][msg.sender]; emit RemoveProfile(_profiler, _soul); } }
Code language: JavaScript (javascript)

コードを見てみるとその内容がよく理解できます。

mapping (address => Soul) private souls; // Souls created by operator
mapping (address => mapping (address => Soul)) soulProfiles; // Anybody can create 1 profile for soul owners

この二行が特徴をよく説明しています。オリジナルのコードにはないですが、動画にあるコメントがわかりやすいので追記しました。
Soulという構造体のデータを発行できる人、焼却できる人、登録できる人、更新できる人、参照できる人、それぞれルールが決められています。
所有者が移動できないので構造はシンプルです。
コードの中でeventやzeroHashについても調べてみました。

eventについて

https://qiita.com/hakumai-iida/items/3da0252415ec24fe177b

詳しく説明されいます。サンプルDAppsについてとても興味深いです。

https://www.tutorialspoint.com/solidity/solidity_events.htm

コントラクトからフロントエンドへの通知の実装について書かれています。使い方がよくわかります。(スクショとりました)

zeroHashについて

bytes32 private zeroHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
..
require(keccak256(bytes(souls[_soul].identity)) == zeroHash, “Soul already exists”);

インスタンスがない状態、Nullのような状態を表すために使われているようです。
ためしにゼロのハッシュ値をとってみました。(Ethereum標準ハッシュ関数keccak256 ケチャック)
参考) https://qiita.com/kaito1994/items/62974800419f0e51c6cb

from Crypto.Hash import keccak import binascii keccak256 = keccak.new(data=0, digest_bits=256).digest() print("Keccak256:", binascii.hexlify(keccak256)) #Keccak256: b'c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470'
Code language: PHP (php)

下記サイトでは、SBTついて詳しく書かれています。

https://www.xross-dx.com/article/aboutSBT-byGG-vol1.html

アドレスの所有者に固有の情報を与えことによって、信用調査等に利用できるといったところでしょうか。
情報を改竄できないブロックチェーンならではの使い方と言えます。

Move / Aptos

今週、注目のレイヤー1プロジェクトのAptos(アプトス:APT)が大手取引所に一斉に上場されました。
注目されている理由は、大手投資機関から多額の出資を受けているのもありますが、もともとFacebook(今はMeta)のプロジェクトで途中で断念した、仮想通貨Diem(ディエム 旧リブラ)の元開発者が創設したこともあり、話題もとても豊富なことがあります。
(Facebookのようなプラットホーマが仮想通貨を持つことが国家のような組織から見たら、かなり脅威だったのでしょう、つぶされた感が否めません。)
開発者としては、開発に使われる環境やプログラミング言語Moveにとても興味があります。

https://aptos.dev/cli-tools/aptos-cli-tool/install-aptos-cli

開発には、上記Aptos CLIで行うようです。
また下記動画にAptosについて、またMove言語について詳しい説明がありましたので参考にさせていただきました。

https://www.youtube.com/watch?v=I5dehispk-E

Aptos CLIの使い方や、MoveとSolidityとの違いについて、動画の中でとてもわかりやすく説明されていましたので、その部分のスクリーンショットを使わせていただきます。

Move言語がRust言語ベースでブロックチェーンプログラムに特化(アカウントチェックをやってくれることからコーディング量が減少)していることと、Solanaチェーンにも使われる可能性があるということはとても興味深い内容でした。
「Solana in Rust & TypeScript」

http://bitlife.me/bc/2022/02/11/

Rustは値の所有権という概念があり、デジタル資産の管理と親和性があります。ブロックチェーンプログラムでよく使われるのも理にかなっています。もしかして”Move”というのは、Rustの所有権の移動(Move)という考え方からとっているかもしれませんね。

今回はAptos CLIでなく、便利なPlaygroundがあるということから動画を参考に使ってみました。

https://playground.pontem.network/

起動するとexample-projectが現れます。これらを使ってアドレス0x01から0x02へののコインの送金をしてみました。mint関数は、Coins.moveのものと名前がぶつかるのでmy_mintとしました。実行はscriptの関数をRunの入力項目に引数とともに記述します。

次は新規にファイルを作成して、HelloモジュールをScriptから呼び出します。

ここまでですが、とても使いやすいと感じました。

example-projectのコードも見やすく、何をやっているのか理解がしやすかったです。

もう少し学習をすすめようと思います。

Bitlife Coin / iOS

最近iOS開発を再々開することになり、iOSアプリでも暗号通貨を扱ってみたいという思いから、調べたことを久しぶりに投稿いたします。
iPhoneが発売されてから、iOSアプリ(当時はiPhoneアプリ)開発をはじめ、Swiftきっかけで再開し、そして今回Appleシリコン、MLきっかけで三度始めることになりました。

https://github.com/horizontalsystems/ethereum-kit-ios

http://bitlife.me/bc/2022/01/23/ (前回ブログ)

目標は、上記EthereumKitを以前作ってマイコイン”Bitlife Coin”の残高を表示させることです。
iOSのプログラムにいく前に、Bitlife Coinの復習と、Ropstenテストネットが終了するという情報もあることから前回ブログを参考に、Goerliテストネットへのデプロイをしました。
前回のDocker環境の仕方を忘れてしまい(Docker imageがどっかにいってしまった・・)、いろいろと手間取りました。(メモっておかないとだですね)
Windows Docker Desktop -> Containers -> competent_para スタート
WSL -> docker exec -it competent_pare bash
(こんなやり方だった? WSLが起動しなくなる現象はこれが原因? PC再起動でなんとか復旧)
truffleの実行でエラーがでたため、nvmアップデート

nvm install 12.22.12
nvm use 12.22.12

truffle console –network goerli

その前に、truffle-config.jsの編集(前回このあたりの説明がなかった・・)

ropsten: { provider: () => new HDWalletProvider(mnemonic, `https://ropsten.infura.io/v3/${infura_key}`, 0, numAccounts), network_id: 3, gas: 5500000, // Ropsten has a lower block limit than mainnet confirmations: 2, // # of confs to wait between deployments. (default: 0) timeoutBlocks: 200, // # of blocks before a deployment times out (minimum/default: 50) skipDryRun: true, // Skip dry run before migrations? (default: false for public nets ) from: account, gasPrice: 10000000000, // in wei (default: 100 gwei) websockets: true // Enable EventEmitter interface for web3 (default: false) }, goerli: { provider: () => new HDWalletProvider(mnemonic, `https://goerli.infura.io/v3/${infura_key}`, 0, numAccounts), network_id: 5, gas: 5500000, // Ropsten has a lower block limit than mainnet confirmations: 2, // # of confs to wait between deployments. (default: 0) timeoutBlocks: 200, // # of blocks before a deployment times out (minimum/default: 50) skipDryRun: true, // Skip dry run before migrations? (default: false for public nets ) from: account, gasPrice: 10000000000, // in wei (default: 100 gwei) websockets: true // Enable EventEmitter interface for web3 (default: false) },
Code language: JavaScript (javascript)

infura.ioのアカウントはまだ使用可能で、上記goerliのendpointを確認。
前回同様にデプロイしてミント。

truffle(goerli)> migrate
truffle(goerli)> token.mint(accounts[0], web3.utils.toWei(“5000”, “ether”))

https://qiita.com/guntamania/items/d1605961f0af008e8e8d

せっかくなので、こちらを参考に前回やらなかった送金をしました。

https://goerlifaucet.com/

その前にこちらでEtherを取得
このメタマスクのウォレットのニーモニックをtruffle実行フォルダにある.secretに保存します。

truffle(goerli)> tc = await MyCoin.at(MyCoin.address).then(=>)
truffle(goerli)> tc.totalSupply().then(ts=>ts.toString())
‘5000000000000000000000’
truffle(goerli)> dest = “0x…..” <- 送金先 truffle(goerli)> tc.transfer(dest, 100000000000000) 

さていよいよiOS側ですが、githubから取得したプロジェクトをXcodeに読み込ませビルドします。(github参考に、pod installも。.xcworkspaceを使用)
私テスト用デバイスiPhone6がiOS13.0に対応していないのでiPhoneシミュレータを使いました。
ここでgoerliテストネットワーク用に修正をします。

Configuration.swift
・chain.id 5(goerli)でErc20Token追加
 3(ropsten)でも一応確認。
・BLCトークンアドレスの設定(前回ブログ確認)
・RpcResourceの設定。goerli用の関数を使用
・infuraCredentialsの設定。登録したアカウントのProjectIDとSecretコード。
・defaultWordsの設定。MetaMaskのニーモニックコードを使用。(このユーザの残高を確認。ログイン時の指定できるが面倒なのでデフォルトに)
・RcpResourceの設定。goerli用の関数に変更。引数にinfuraCredentialsを指定。
・TransactionResourceの設定。goerli用の関数に変更。etherScanのアカウントを作成しAPIキーを指定。

Chain.swift
・goerliのcointypeを1から60に変更(ropstenでも同様)
 ニーモニックから出力するアドレスが一致しないため、いろいろと調べたところ、HDWallet.swiftのprivateKey:pathが違ったため。

ganache-cli -m “….”
….

Mnemonic: ….
Base HD Path: m/44’/60’/0’/0/{account_index}

ganacheでも確認可

実行結果

まだ送金ができていませんが、アプリに組み込むのに何が必要なのか理解できた気がします。

<おまけ>

https://api.etherscan.io/apis

コードを修正しながら動作確認していく上でなかなかうまくできなかったので、上記APIも実行して確認しました。

https://api-goerli.etherscan.io/api?module=account&action=tokenbalance&contractaddress=”mycoin contract address”&address=”wallet address”&tag=latest&apikey=”APIKEY”

Response: {“status”:”1″,”message”:”OK”,”result”:”4999998999499499499500″}

Terra LUNA Shock

ちょっと遅くなりましたがTerra Luna ショックについてまとめるのと、これをきっかけにここまでの総括をしようと思います。

http://bitlife.me/bc/2022/03/12/ 参考) 先進的なFinance機能を持つTerra LUNA

ステーブルコインUSTが暴落し、それとともにLUNAも暴落、これまで資産価値上位にあったコインの価値がなくなりました。
クリプト業界にとって大きなできごとであり、自分にとってもこれらの関与についてひと段落するきっかけだったことから長文ですが備忘録としてまとめてみました。

Luna Classic Chart from ByBit

Blockchain技術の興味からこのブログもはじめ、クリプトへの理解を深めるためトレードも始めました。
(ブログでも述べましたが、あれだけクリプトが過熱していた時期に興味をもたなかったのにNFTがきっかけで興味をもつようになりました。)株取引の経験はストックオプションの売買を少ししたくらいでほとんどありません。FXはそれ自体よりもトレードアプリMT4に興味があり学習はしましたが、実際のトレードはやりませんでした。

まず手始めに国内取引所に口座をつくり10万円ほど入金しました。入金するとすぐにメジャーどころのBitcoin、Ethereum、そしてPolkadotなど購入しました。(今考えたらタイミングを考えずに買うなどありえないですね。買わなきゃ始まらないみたいなノリで・・しかもこの時期下落前)Ehereumはスマートコントラクトやネームサービスでドメインを購入したりといろいろと遊べるため積極的に買いました。(ガス代、転送手数料など考えていない時期)メタマスクのウォレットの使い方も覚えました。また取引所では他のコインも売買楽しみました。(板が使えない、使えたとしてはも少額ではできない、スプレッドが高い)ここまでかなりロスをすることは明らかですね。
注目のBlockchainのコインはどれも国内で購入できないことや、やはり板取引でないとかなり不利であることから、情報も多い海外取引所をByBitを使うことにしました。最低10ドルで取引ができ手数料もやすいことから私のような少額で遊ぶ人にはとても向いています。注目のコインもたくさんありいろいろ買いすぎました。
最初は現物ばかりでしたが、デリバティブ取引での空売りも覚え、これまで国内取引所でやっていたことがいかに不利であるか実感しました。(円で取引するので為替変動が影響するのもやっかいです)
ByBitといえどもほしいコインがないことがあり、他の海外取引所も調べました。日本発ということからASTRを購入したかっためGateIOを利用することにしました。ちなみにByBit、GateIOには国内取引所から送金しました。(今は??)  ASTR、ADA、SOLなどのまたメタマス以外のウォレット(Polkatot.js、Yoroi、Phantom)も使ってみて、それぞれ特徴を知りました。(Blogでも利用)
入金の手数料が気になり、いろいろと調べてみるとJPYCのプリペイドを利用すると安くできることがわかり、メタマスクでPolygonチェーンのQuickSwap, SushiSwapを使ってUSDCに(Maticも少し必要)、そしてGateIOに数万円分新規に転送しました。GateioからByBitにはTRXチェーンを使うと手数料がなく転送できました。(その前にUSDC->USDT。最低金額は5000円くらい) このとき「取引所はなくても取引できるんだ」と知りました。(これもあって日本発のコスプレトークンをDeXで買ってみました)ステーキングも興味がありましたが、動かせなくなる資金があるほど余裕もなかったためしくみだけ学習してやりませんでした。


ひととおりクリプトの使い方やしくみがわかったところで、トレードに集中するようになり、外部要因による影響とか(FOMCがどうのナスダックがどうだとか)、テクニカル指標の使い方とか(ボリンジャーバンドがどうだとか)、意識するようになりました。
しかしいきなり10%近い急上昇、下落があるクリプトの相場は非常に難しいです。これが面白い特徴的でもあるのですが、ここで自問自答したのは、何を目的にトレードするかでした。(何を得たいのか?長期、短期? )目的はあくまで勉強なので(このような少額で儲かってもしれている)、ショートタームで難しい局面でも積極的に試行錯誤してチャレンジしました。
クリプトのトレードは、株ほど広範囲(興味のない分野)の情報が必要でもなく、FXほどテクニカルでもなく、適度なストーリー(興味があるBlockchain界隈にニュース)が影響するので、自分にとって面白く感じました。しかしずっとチャートにへばりついているわけにもいかず、どういう時間帯でどのくらいの時間やるのか、ということが重要だと思いました。リアルタイムで見ていれば、急落、急上昇(ボラティリティが高いというのですよね)でポジションを変更することもできますが、見ていないときがほとんどなので、こういうことに対処するにはやはり自動トレードをプログラミングする必要性も感じました。
こういうアルゴリズムを考えるのにも、ボラティリティが高い動きを見る経験が必要になるので、クリプトは向いているのかもしれません。あといろんな感情を経験するものだと思いました。人間味がでるというか応援したいプロジェクトかどうかで判断がかわります。(本来そういうものなのかも。。ちなみに4月中からのダウントレンドでASTRを安値買いをつづけて空売りできませんでした。)
そしてLUNAの暴落がありました。暴落の途中なんども持ち直す動きがあったのでコントロールされていると思い部分的にしか空売りをしませんでした。(実績があったコインだけに、まさかこれ以上は下がらないよね・・と思い続けていました。) あれだけ下がっていても空売りって継続できないものですね。また底と思って買った現物のLUNAが消えてしまいました。(今はLUNA Classic: LUNC ルナシー?) このときもチャートをウォッチできておらず、やはり自動トレードは必要だと感じました。

Bitcoin chart from ByBit

4月中からのダウントレンドでBitcoinに引っ張られる形でアルトコインも下落しましたが、いろいろと種類をもっていたためメンテができず気づいたら$10下回り取引ができなくなるということにもなりました。ここでも自動トレードは必要性を感じました。(それ以前に初心者なのに手を広げすぎか・・あとインバース無期限で下落して結構減らした(SOL))
こういつたこともあり、年の初めからここまでで(5月中)、トレードについてひと段落しようと思いました。
クリプト冬の時代といわれる中、利上げによる株安、そしてなによりロシアによるウクライナ侵攻と、かなり厳しい外部要因がある中のトレードでした。結果資金は半分くらいになり、上昇トレンドの浮ついた気持ちを味わうことはありませんでしたが、いっぱい失敗して勉強になりました。

Bitcoin chart from ByBit

今後、さらなるBitcoinの暴落があるという予測がありますが、もし下がった場合、単に価格が下がるだけでなくもっと深刻な影響がありそうな気がします。LUNAが下がっているとき、USTだけでなくUSDTも下がった瞬間がありました。多くのコインの取引がUSDTとペアになっているので、売られるとUSDTが増大し担保が不安です。(もともと問題をはらんでいる)もしBitcoinが大量に売られれば、この問題が大きくなり、そもそも基準にしているUSDTが下落したら正しい価値がわからず取引することになるのではという心配があります。またLUNA暴落時、USDCをUSDTで買おうとしたときByBitで初めてタイムアウトで取引が成立しない経験しました。あとロウソク足表示が追い付かず、取引判断のタイミングが遅れたのも初めてでした。ByBitはとても処理が速いサーバでもともと優秀なシステムですが、このときは異常なほどトラフィックがあったのでしょう。

クリプトは国境を越えた送金が簡単にでき、メタマスクでそれを経験したときは、本当にその便利さを実感しました。このようはパワフルなツールが、中央集権的な支配をしたい人たちの敵対的な存在になるのかどうかによっても、今後の先行きに影響を与える気がします。非中央集権的な自由を守りたいという気持ちもありつつ、なんでも自由なのがよいのか、ということを最近感じ始め、なにが良いのかよくわからなくなってきています。
またDeXの例を挙げましたが、DeFiが進む取引が自動化され、従来のしくみが不要になります。またBlockchainにはDAO(自立分散組織)というプロジェクトもあり、これが進むと組織も効率化できます。
これらはAI以上に人の仕事を奪いかねません。(システムの自動化・無人化) こういった方向性に夢をもちつつも、何かわからない懸念みたいなものも同時に感じています。(民主的で自由だと思っていたシステムが実はそうでなかったとか・・お金を持っている人が影響力をもつのも民主的?)
とても奥が深いです。

大変長くなりましたが、経験したことを後で思い出すことができるように書きました。(損失しましたが、それが少しでも役に立ったという思いになれます。)


まだまだいろいろと勉強していきたいと思っています。

Ethereum Remix & Github

Ethereum の開発環境RemixでSolidity を使った開発を、下記記事で以前試しましたが、

http://bitlife.me/bc/2022/01/09/

今回は、RemixとGithubアカウントを連携してより環境を充実させることと、より具体的に開発を進めるためにサンプルコードBallot.solを掘り下げてみました。

これは投票する項目をデプロイ時に登録して、投票権を与えたアカウントの投票させ、その結果一番多い投票があった項目を表示するものです。

最初登録する項目proposalNamesの与え方がよくわかりませんでしたが、動画(最下部)を参考にしました。

このように配列で与えるのですが、それも適当なデータではなく、きちんとした文字列である必要があり、下記コードで生成しました。

const ethers = require('ethers'); async function createBytes(args){ const name = args[0]; const bytes = ethers.utils.formatBytes32String(name); console.log("Bytes: ", bytes); }
Code language: JavaScript (javascript)

$ node createBytes.js name01
Bytes: 0x6e616d6530310000000000000000000000000000000000000000000000000000
$ node createBytes.js name02
Bytes: 0x6e616d6530320000000000000000000000000000000000000000000000000000

デプロイ時いちいちコピペするのが面倒なので、コードの中で与えるように変更しました。

https://github.com/systemsblue/Solidity-work01/blob/main/contracts/3_Ballot.sol

このような変更も今回 Remixのプラグイン、DGITを使ってできました。

Githubアカウント側の準備としては、Settings -> Developer settings -> Personal access tokes -> Generate new token でトークンを発行してこれを DGIT の Github Settings に貼り付けます。

あとはgitコマンドを使うようにメニューから実行していきます。

最初にもどってBallotの操作手順を追っていきます。

コンパイルするとコンストラクタの引数をなくしたので、ビルドすると上のように入力エリアがなくなります。これでDeployボタンをクリックします。(二つの名前が暗黙的に登録されます)

操作はACCOUNT(上の画像)を切り替えながら、ときにはアドレスをコピペして下記に貼り付け、ボタンをクリックしていきます。

操作は結構面倒です。

まずchairpersonで、投票の権限を与えるアカウントを確認して、このアカウントが選択されているときにgiveRightToVoteが使えます。ここに投票するアカウントのアドレスをコピペするのですが、ACCOUNTを切り替えてコピーし、chairpersonにまたもどしてgiveRightToVoteをクリックします。

投票できるアカウントが登録できたら、それぞれのACCOUNTに切り替えて投票します(Voteをクリック)。このときの値は2項目であれば、インデックスとして0と1になります。

winnerNameをクリックすると投票数が多い方の名前(といっても数値)が表示されます。

このサンプルはいろんなエッセンスを学ぶことができとても参考になります。IDEをWebアプリで使うことを考えると、Githubの連携も欠かせないと思いました。

CosmosとかPolkadotなどでもGithubアカウントが必要だったのですが、認証の意味とファイルの保存目的のような感じを受けました。Gitコマンドのように使えるこのプラグインはとても便利です。

参考動画

Astar Network

以前取り上げたPolkadotのバラチェーンであるAstar Networkについて、いろいろ試してみました。

http://bitlife.me/bc/2022/02/26/

基本的な使い方はこの「Substrate / Polkadot」で取り上げたとおりですが、「Solidity to WASM Compiler」というドキュメントからWASMについて調べたいと思ったのがきっかけです。

https://docs.astar.network/build/smart-contracts/wasm/solidity

WASMは一つのバイナリをいろいろな場所で動かすことができるため、最近とても興味を持って調べています。

https://decode.red/blog/202204021431/

まず結果からですが、SBYトークンが取得できず(枯れているみたい)うまくいきませんでした。(先週も今も) しかしそこに至る経緯をメモしておきたいので、このまま進めたいと思います。(やりたいことは最後の動画を参考にしました)

その前に、Astar Networkについて整理しますが、Stake Technologiesという会社で創業者が日本人ということもあり個人的にもとても応援しているプロジェクトです。dApp開発者が報酬を得られるdApp Stakingというものに興味を持っています。

あと名前がややこしいのですが、Polkadot/Kusama (メインネット/実験ネット)に相当するのが、Astar/Shiden で、Shibuyaはテストネットになります。実験ネットとテストネットは違い実験ネットのコインは購入する必要があります。(少額はFaucetで取得できるみたい(しかし今はできない?)) Plasm Networkという名前もさまざまなドキュメントで残っていますが、これはAster Networkの以前の名前のようです。

AstarにはWASMがアップロードするためのコントラクトの項目がなかったので、Shibuyaで作業することにしました。

ShibuyaのFaucetは、Discord で取得できという案内がありましたができず、Astarのポータルからもできませんでした。

下記コミュニティFaucetからはできましたが、SS58(ネイティブ)ではなくH160(EVM)でした。

https://www.as-faucet.xyz/en#

下記でコンバートしてEVMデポジットに入金が確認できたのですが、ポータルでSS58に変換することができず、WASMをデプロイするためのガス代として使用できませんでした。(EVMから引き出しでエラー。少額だから?)

https://shibuya.subscan.io/

では、前置きが長くなりましたが下記サイトを参考に環境構築(solidityコンパイラ)からやってみます。

https://docs.astar.network/build/smart-contracts/wasm/solidity

sudo apt install llvm openssl libxml2-dev
sudo apt-get install liblld-10-dev

いつものように、Ubuntu20.04にインストールましたが、llvmのバージョンがあわずバイナリーを使うことにしました。(13が必要でUbuntuでは10,11,12までしかなし)

wget https://github.com/hyperledger-labs/solang/releases/download/v0.1.10/solang-linux-x86-64
wget https://raw.githubusercontent.com/hyperledger-labs/solang/master/examples/flipper.sol

テストプログラムも取得しました。(やっている内容はビット反転ですね)

contract flipper { bool private value; /// Constructor that initializes the `bool` value to the given `init_value`. constructor(bool initvalue) { value = initvalue; } /// A message that can be called on instantiated contracts. /// This one flips the value of the stored `bool` from `true` /// to `false` and vice versa. function flip() public { value = !value; } /// Simply returns the current value of our `bool`. function get() public view returns (bool) { return value; } }
Code language: PHP (php)

コンパイルしてできた、flipper.contract ファイル をアップロードします。

スクリーンショットとは違いますが、実際のアカウントは、shibuya01を使用。

あと、警告も解消させています。

Walletからinjectしただけでは、EVMデポジットに送ることができず、JSONファイルであらためてインポートしました。

結局できたのは、SBYが取得できなかったため(H160(EVM)でなくSS58(ネイティブ)でないと上記に表示できない?)、Deployする直前までで、実行についてサイトにあるものをご参考ください。

へんな形になりましたが、開発がどんどんすすんでいる最中のお試しとしては、できなかったとして何もしないよりもできたとこだけ記録しておくということ大切だと思っています。

ポータルの使い方としては、Polkadotと同じなので、このあたり統一されていてとてもわかりやすいと思いました。

Avalanche Postman-collection

Exchange Chain (X-Chain), Platform Chain (P-Chain), Contract Chain (C-Chain) の3つのビルドインブロックチェーンをもつ、独特なしくみで高いパフォーマンスとEthereumとの互換性をもつAvalanche Platform。

Web APIで操作できるしくみは他のプラットフォームでも珍しくないのですが、Postmanの設定ファイルが用意されていることを動画(最下部)で知り便利だと思い試してみました。

しかしながら結果からいうと、Avalancheのテストノードが使える状態に同期するまでの時間がかかりすぎて(30時間以上かかるようで見積残り処理時間もなかなか減らずいつ終わるかわからない・・)、やろうとしていた動画のようなWallet間の送金はできませんでした。そのためいろいろとトライしたことの記録となります。

https://docs.avax.network/build/tutorials/nodes-and-staking/run-avalanche-node

上記を参考に、nodeの起動とcurlコマンドで送る手順が動画と同じことを確認できます。

./avalanchego –network-id=fuji –http-host 127.0.0.1

テストネットはFUJIというらしく(ここでも日本語が・・) このようにオプションを指定して起動します。(何もつけなければメインネット) ここではWSLでバイナリモジュールを使って起動。

次はPostmanをインストールして、下記から二つの設定ファイル(environment,collction)を読み込んで実行します。

https://github.com/ava-labs/avalanche-postman-collection

memo) ローカルアクセスのためにPostmanAgentが起動している必要あり

“Create a Keystore User”まではできますが、”Create an Address”は、上記ブートストラップがtrueにならないとできません。(これが30時間以上かかる?)

これとは別にWalletの準備をしました。

アドレスにC-ChainとX-Chainがあります。Xはネイティブ用で、CはEVM用でMetaMaskアドレスに送ることができます。

X-Chainに2 Avax、C-Chainに1 Avax送った結果です。上記Walletを作ると、X,C,P 3つのアドレスが作成されます。動画によるとPはステーキング用のようです。(アドレスはXとP部分以外は同じ文字列)

Postmanの前にもともとWallet-SDKを使って送金しようとたのですが、これもうまくいきませんでした。(うーん)

https://docs.avax.network/build/tools/avalanche-wallet-sdk/

下記メモです。

import { NetworkConstants, Network} from '@avalabs/avalanche-wallet-sdk'; これがうまくExportされないためExportされないためないため const net = require('./avalanche-wallet-sdk/dist/index.js'); テストネット切り替えなど部分的にはうまくいったものもあるが (node-fetchをクローバルにする方法などいろいろ試したりする方法などいろいろ試したり.jsの内容もいろいろ変えたり、 ts-nodeでバージョンを変えたりts-node-esmもためしたが同じ import {MnemonicWallet, BN} from '@avalabs/avalanche-wallet-sdk' これはうまくいくので(X,C,Pとも メインネットンネット(x-avax..., x-fuji...) XとPはこの文字以外は基本的に同じ字以外は基本的に同じ
Code language: JavaScript (javascript)

アドレス生成コード

import {MnemonicWallet, BN} from './avalanche-wallet-sdk/dist' const net = require('./avalanche-wallet-sdk/dist/index.js'); const mnemonic = `wedding ...... orient bicycle`; net.setNetwork(net.TestnetConfig); //net.setNetwork(net.MainnetConfig); let myWallet = new MnemonicWallet(mnemonic) console.log(myWallet.getAddressX()); console.log(myWallet.getAddressP()); console.log(myWallet.getAddressC());
Code language: JavaScript (javascript)

また以下のようにPaper Walletというのを出力できます。

気になったのが、ここのアドレスとWebに表示されているアドレスがXだけ違っていました.

うまくいかないことが多かったのですが、いろいろと理解は深まりました。また機会があれば続きをやりたいと思います。

参考動画

Enjin Platform

ERC1155というコントラクトを考案した、Enjin社。NFTの分野で進んでいる印象があります。

今回、NFTの登録、Enjin Walletの接続、GraphQLを使った情報の取得を試してみました。

また下記NFTについて、他のBlockchainとの比較が興味深い記事です。

Enjin SDKのページから、上部にあるリンクからKovanテストネットワークを選びます。

https://docs.enjin.io/sdks/getting-started

https://kovan.cloud.enjin.io/platform

アカウントの登録をして、プロジェクトを作成します。

このときiPhoneにも、Enjin Walletアプリをインストールします。

https://immersednow.medium.com/integrating-enjin-coin-enj-with-unity-using-the-enjin-unity-sdk-part-1-enjin-account-wallet-9ec9d263d227

Settingsで表示されるQRコードをアプリで読み取ると、Walletがリンクされます。

Walletへの入金は、KETHは下記から、

https://gitter.im/kovan-testnet/faucet

https://ethdrop.dev/

KENJはユーザサポートにメールで問い合わせ、Walletアドレスを知らせて入金してもらいました。(KETH, KENJは、ETH,ENJのKovanテストネットワーク用コイン)

ユーザサポートに聞きながらトライ&エラーをしたのでない画面があったり、前後している部分がありますが、FT,NFTの登録、トランザクションでのエラーを起こすときはKETHが足りないのも原因になるようです。

Webでの操作ごとにWallet側で承認の作成をしなくてはならないところは面倒に感じました。少なくともプロジェクトの作成、アセットの作成、アセットの発行(MINT)の3回必要。実は最初のMINTは成功したのですが、Tibit ProjのMINTは失敗しています。MINTに成功するとスマホにも表示されますが、表示できているのは最初のもの。(登録エラーのときもそうですが、エラーの原因がわかりづらい)

あとメモとしては、Walletを開発バージョンにしないと、KETH,KENJを表示しないため、設定画面のバージョン表示部分を10回タップする必要があります。

今回は、Enjin Platformのほんの一部ですが、Enjinを少しでも理解したかったので触ってみました。下記動画にはEnjin社のNFTに対する取り組みが詳しく説明されています。ポルカドットパラチェーン対応のEfinityについてはまた調べたいです。

NEAR Protocol

Nightshadeという独自シャーディングモデルによってスケーラビリティを向上させ高い性能を誇るNEAR Protocolの開発環境を試したみました。

参考:

https://coinpost.jp/?p=234911

https://coinpost.jp/?p=324304

下記Etherumの図がわかりやすかったので、拝借しました。
今回は、Examplesページ
“Rust & AssemblyScript Code Examples for building on NEAR”

https://near.org/examples/ から

NEAR Wallet Integrationを選びました。”Open in Gitpod” クリック(要Githubアカウント)

VS CodeライクなWebアプリが立ち上がり、開発環境一式が自動的にビルドされます。

“Open Browser”ボタンをクリックすると、フロントエンドのWebアプリが新しいWinodowで立ち上がります。(このときブラウザに許可をする)

Sign in すると、Walletとの接続を求められます。(必要になるアカウントの設定は済んでいるとする)

接続が終了すると、画面が変化。

“Say hi!”ボタンをクリックして、スマートコントラクトの呼び出し。

リンクをクリックしてスマートコントラクトが呼び出された様子を見てみる。

コードを見てみる。

上記3つのコードでやっていることは、なんとなく理解できそうです。

NEARというブロックチェーンから開発環境も含めて、実用性が高いという印象を受けました。(既存のWeb開発っぽい・・ブロックチェーンならではという部分のハードルが低そう・・) クロスチェーンに関する部分もまだ開発中ということで、まだまだ先が楽しみです。

参考動画

https://www.youtube.com/watch?v=G6f8scktyDM

Terra LUNA

テラは、Cosmos のブロックチェーン開発エンジンTendermintによって開発されています。LUNAというネイティブトークン以外に、USTという担保なしのアルゴリズムによって法定通貨とペッグする、ステーブルコインも発行しており、下記www.terra.moneyにも”Programmable Money”とあるようにファイナンス関して先進的な印象をもちました。最近勢いがあります。

https://github.com/terra-money/LocalTerra

今回は、LocalTerraというローカルブロックチェーンを使ってテストしてみました。(ここにもterra-moneyとありますが、”money” 目立ちます)

環境) Docker, WSL / Ubuntu 20.04 / Windows 11

git clone –depth 1 https://www.github.com/terra-money/LocalTerra
cd LocalTerra

(私の環境では、docker-composeをアップデート /usr/local/bin)

sudo wget https://github.com/docker/compose/releases/download/v2.3.2/docker-compose-linux-x86_64

docker-compose up

これで一気にブロックチェーンの起動までいきます。新しいコンソールを開き、

docker-compose stop

で停止します。

LocalTerraの起動状況

起動したときのコンテナの状態

terrad statusなどのコマンドは、CLIから実行可能。

アカウントがあらかじめ用意されているので、LocalTerraに接続して、Terra Station Wallet (Chrome機能拡張)を作成する。

Chrome機能拡張

Rustの設定

https://docs.terra.money/docs/develop/dapp/quick-start/initial-setup.html

rustup default stable
rustup target add wasm32-unknown-unknown
cargo install cargo-generate –features vendored-openssl
cargo install cargo-run-script

Terrain インストール

sudo npm install -g @iboss/terrain

DApp イントール

https://docs.terra.money/docs/develop/dapp/quick-start/using-terrain-localterra.html#install-and-run-localterra

terrain new my-terra-dapp
cd my-terra-dapp
npm install

デプロイ

terrain deploy counter –signer validator

コンソールを使ってデプロイしたコントラクトにアクセス

フロントエンドアプリを使ってコントラクトにアクセス(http://localhost:3000/)

terrain sync-refs
cd frontend
npm install
npm start

Walletに接続して、カウンターをインクリメント(コンソールのつづきなので9)

“+”を押すと、Walletがひらく

インクリメント完了

increment, getCountのコード確認

Blockchain開発にRustという言語はとても重要な位置をしめていますね。USTのようなステーブルコインのしくみはここでは関与しませんでしたが、とても興味深いです。

これまで、USDT,USDCのように実物のドルの担保があるのが普通でしたが、アルゴリズムだけで実現したものを皆が信用するということは、すごいことだなと、単純に思います。いろんな金融商品を組み合わせてリスクヘッジしたりすることは投資の世界でよくあるようですが、こういうのもアルゴリズムがあるのでしょう。最近Blockchainを研究するとともに、ちょっとファイナンス関連にも興味をもつようになってきたような・・

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: にあるハッシュを見てみると、消費されたアウトプットは次になくなっていることも確認できます。

ブロックチェーンの基礎を勉強する教材としてとても素晴らしいため、自分用メモとして残しておきたいと思いました。

Plutus / Cardano

前回につづいてカルダノのPlutusスマートコントラクトを今回はHaskellプログラミングのPlayground環境で試してみました。

デモファイルがいくつもあるのですが、支払いのしくみがわかるStarterを選びました。(最後に参考の動画のリンク)

“Compile”->”Simulate”->”Evaluate”ボタンで実行しますが、まだこのコードではValidatorが実装されていないのでエラーがでます。
--validateSpend _myDataValue _myRedeemerValue _ = error () -- Please provide an implementation. validateSpend (MyDatum myDataValue) (MyRedeemer myRedeemerValue) _ = myDataValue == myRedeemerValue

35行目を上記のように変更してもう一度実行します。

成功したので、シミュレーションの結果を見てみます。(12345はパスワード, 30000000ADA送金)

Slot 0, 1, 2とみていきます。

アカウント方式でない、コインの所有者を変更していく、UTXO(ビットコインと同様の未使用トランザクションアウトプット)のしくみが、わかりやすく見ることができます。イーサリアムはUTXOを使っていませんが、後発ゆえにいいとこどりをしている部分でしょうか。

(E)UTXOについて https://iohk.io/jp/blog/posts/2021/04/13/plutus-what-you-need-to-know/

参考動画

コードの細部まで丁寧に説明されており、とてもわかりやすいです。(といっても難解ですが・・)

Playgroundがデフォルトでどこまで実装されているかを確認するために、”HelloWorld”を最初に実行するといいと思います。

Haskellを復習してまたチャレンジしてみたいと思います。(ここまで記録をとっておくと次からやりやすい。Githubアカウントが必要で”Save”で自分のGistに保存してくれる。)

https://decode.red/blog/tag/haskell/

Marlowe / Cardano

Haskellで開発さているカルダノですが、そのHaskellの難易度とは真逆のビジュアルプログラミング環境Marloweがあるのを知り、試してみました。

ブロックチェーンコントラクトの内容なのに、プログラミング教育についてのブログ、http://decode.red/ed/ で扱った方がいいのではと思えるほどのギャップに驚きました。

まるでスクラッチです。それもそのはず、URLからGoogleのBlocklyをベースにしているようです。結合できるプログラミングブロックを制約することによってミスを少なくできるので、セキュリティが要求されるコードに使うことは、ある意味理にかなっているかもしれません。下は、シミュレーション画面。コードが表示されます。

ここでは、下記動画のデモを実行してみました。(挙動をわかりやすくするため数値をかえています。)

以下完成したコード

内容は、Player1,Play2がそれぞれコインを預け入れ、次に両者が別々に入力する数字が一致し、かつPlayer1の数が1なら、Player1が払い戻しをうけ、1以外ならPlayer2が、一致していなかったらもらえない、という一種の賭けです。賭けなので平等な条件にならないといけないのですが、デバッグ表示がわかりづらいので、金額を変えました。ADAというのはカルダノで使われているコインです。

“Start Simulation”ボタンが押されたら、以下の順で画面がすすんでいきます。

Player1,2とも1の場合

Player1,2とも2の場合

Player1が2、Player2が1の場合

slotというのは、プログラムのすすむ時間のようなものと解釈しましたが、何もしないと預けいれたコインがもどされるような仕組みがはいっているようです。(間違っていたらすみません–; )

カルダノネットワークは、イーサリアムネットワークのERC20を変換してもってくることができるようになるということですが、これはとても魅力的に思います。ブロックチェーンの世界はコインも開発環境も個性的で面白いです。

Bitlife Coin

EthereumのERC20 token templateというものを使って、テストネットワーク上のマイコイン(Bitlife Coin)を作ってみました。マイコインをブラウザアドオンのMetaMaskからスマホのMetaMaskに送金します。(Ropstenテストネットワーク)

https://github.com/hackers-live/erc20-token-template

環境) Ubuntu20.04/Docker/Ubuntu20.04/WSL/Windows11

インストール

touch ~/.bash_profile
curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.34.0/install.sh | bash
nvm install 11.11.0
nvm use 11.11.0
node -v && npm -v
npm i -g truffle
npm i -g truffle-flattener

最初、WSLのUbuntuで試みましたが、やはり上記バージョンの組み合わせでないとうまくいかないことからdockerで新たに構築しました。
dockerではrootユーザで操作するため以下のコマンドが必要になりました。

npm config set unsafe-perm true

また、開発環境等はいっていないため、gcc, pythonも必要となります。(ネイティブビルドをするため: node-gyp-build)

テンプレートの編集

git clone https://github.com/hackers-live/erc20-token-template.git
cd erc20-token-template/
npm install
vi contracts/MyCoin.sol

// 10 billion contract MyCoin is ERC20Capped(10000000000 ether) { string public name = "Bitlife Coin"; string public symbol = "BLC"; uint8 public decimals = 18; address public CFO; address public CEO;
Code language: PHP (php)

オリジナルの部分のみ変更する。

設定ファイルの作成

.infura_key infuraのプロジェクトID (https://infura.io/ で登録)
.account アカウントアドレス
.secret ブラウザMetaMaskでアカウント作成するときのニーモニックコード

まずローカルでデプロイテストをします。(truffle単体でシミュレートできるのですね。前はGanacheを使った)

truffle develop

コンソールで、

truffle(develop)> migrate

とするとデプロイします。各コマンドを実行してテストします。(テストネットと同じなので以下で説明)

確認ができたら、テストネットにアクセスします。

truffle console –network ropsten

同じくコンソールで、

truffle(ropsten)> migrate

1_initial_migration.js (Total cost:0.00196019 ETH)
2_deploy_coin.js (total cost:0.00945698 ETH)

がデプロイされる。

アカウント確認

truffle(ropsten)> accounts = await web3.eth.getAccounts()

5つ表示され、一番目がMetaMaskと同じアドレス。
マイコインの確認

truffle(ropsten)> token = await MyCoin.deployed()
truffle(ropsten)> token.name()
‘Bitlife Coin’
truffle(ropsten)> token.symbol()
‘BLC’
truffle(ropsten)> token.address
‘0x0eD1cf4ADc9c9E53Dc1581512ebE971a6501028E’

このアドレスをMetaMaskで”Import Tokens”に入力する。

コインを生成できるアカウントの確認

truffle(ropsten)> token.isMinter(accounts[0])
true
truffle(ropsten)> token.isMinter(accounts[1])
false

マイニング

truffle(ropsten)> token.mint(accounts[0], web3.utils.toWei(“1000”, “ether”))

マイニングするごとにブラウザのMetaMaskのBLCコインが増えていくことを確認。
またブラウザのMetaMaskを操作して、スマホのMetaMaskに送金する。スマホ側も新規トークンアドレスをインポートしておく。

GASS代が必要なので送金する前にETHがない場合は、フォーセットから取得。

https://faucet.egorfine.com/


コンソールで金額の確認(BNはBigNumberの略)

truffle(ropsten)> balance = await token.balanceOf(accounts[0])
undefined
truffle(ropsten)> balance
BN {
negative: 0,
words: [ 65011712, 54678630, 666133, <1 empty item> ],
length: 3,
red: null }
truffle(ropsten)> balance.toString()
‘3000000000000000000000’

truffle(ropsten)> supp = await token.totalSupply()
undefined
truffle(ropsten)> supp
BN {
negative: 0,
words: [ 41943040, 28165598, 888178, <1 empty item> ],
length: 3,
red: null }
truffle(ropsten)> supp.toString()
‘4000000000000000000000’

スマホ画面

スマホアプリでETHとならんで表示されているのを見て、ちょっと感動しました。

これはメインネットでも同様にできるのですが、GASS代がかかるのと今は用途がないので、テストネットで十分です。独自通貨の発行ってなんか夢がありますね。

Dapp Tools

ブロックチェーン技術を使った分散型アプリケーションとしてDappとかdAppとかあらわされますが、Ethereum上で動作するDappの開発言語Solidityのテスト環境としてdapptoolsというものを見つけたの試してみました。

https://github.com/dapphub/dapptools

(下記動画で学習中、テストパターンを与える部分がよくわからなかったので確認してみただけになります。ブロックチェーンは様々な種類があり、それぞれ開発環境も豊富です。それが一気に押し寄せてきた感じがあり、とりあえず気になるものからどんどんためして理解を深めようと思っています。)

動画では、Openzeppelinとか使用している部分もありますが、ここではDapp ToolsといいながらDappとは関係ない純粋にSolidity言語による一般ロジックのテストの部分に注目しています。

環境) VSCode + Ubuntu20.04/WSL/Windows11

インストール

curl -L https://nixos.org/nix/install | sh
. “$HOME/.nix-profile/etc/profile.d/nix.sh”
curl https://dapp.tools/install | sh

初期化

mkdir dapp_test2
cd dapp_test2
dapp init
code .

dappコマンドでファイルは自動生成され、以下の内容に編集します。(*.t.sol がテストコード)

Dapptest2.sol

// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.6; contract Dapptest2 { uint8[] internal arr; function remove(uint8 _index) internal{ require(_index < arr.length, "index out of bound"); for(uint i = _index; i < arr.length - 1 ; i++){ arr[i] = arr[i+1]; } arr.pop(); } }
Code language: JavaScript (javascript)

Dapptest2.t.sol

// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.6; import "ds-test/test.sol"; import "./Dapptest2.sol"; contract Dapptest2Test is Dapptest2, DSTest { Dapptest2 test; //event DebugLogEvent(string); uint8[] private copy; function test_remove(uint8[] memory _arr, uint8 _i) public { /* function test_remove() public { uint[] memory _arr = new uint[](4); _arr[0] = 1; _arr[1] = 2; _arr[2] = 3; _arr[3] = 4; uint _i = 2; */ if(_i >= _arr.length){ return; } arr = _arr; // delete copy; for(uint i=0;i<arr.length;i++){ if(i!=_i){ copy.push(arr[i]); } } remove(_i); assertEq(arr.length, copy.length); for(uint i=0;i<arr.length;i++){ assertEq(arr[i], copy[i]); } //emit DebugLogEvent("-- end --"); } function test_length(uint8[] memory _arr, uint8 _i) public{ if(_i >= _arr.length){ return; } assert(_arr.length == _i); } function setUp() public { test = new Dapptest2(); } function testFail_basic_sanity() public { assertTrue(false); } function test_basic_sanity() public { assertTrue(true); } }
Code language: JavaScript (javascript)

動画ではremove()関数のテストの様子がわかりますが、入力の配列とインデックスに何が与えられているのかわかりづらかったため、test_length()という関数を追加して試してみました。

dapp test –fuzz-runs 10

このコマンドを実行しても上記スクリーンショットのように成功するときもあれば、下記のように失敗するときもあります。

失敗したとき[FAIL]のCounterexampleという部分に、配列とインデックスがでてきますが、毎回違うためランダムに入力データが与えられていることが確認できました。(見やすくするためオリジナルのuint256をuint8に変更)

–fuzz-runsを指定しないと100がデフォルトで与えられるようです。

本来の目的のremove()関数のテストでは、リムーブされたことをテストするのが目的のため、配列やインデックスの数はなんでもいいのでチェックする必要はなく、テストしていないため毎回成功することになります。

VSCodeの環境(Solidity機能拡張あり)でSolidityのテストできる環境をためせたことは有益でした。

Cadence / Flow

NFTが得意とされるFlowブロックチェーンの記述言語、Cadence(ケーデンス)を試してみました。(音楽用語のカデンツのことですね)

https://docs.onflow.org/cadence/tutorial/01-first-steps/

CadenceにはPlaygroundが用意されており、これを使ってFlowの特徴であるアカウントごとのストレージについてチュートリアルを実行して理解を深めました。

まずは、単純な文字列を表示するだけのプログラムです。上記コントラクトをデプロイします。左に表示されているのはアカウントで、0x01からアドレスがふられています。これは0x01にプログラムとしてデプロイしたのでコントラクト名Helloがアドレスの下に表示されます。(言語はSwiftに似ている)

次にトランザクションのプログラムを記述して送信します。Transaction Signerを選んで送信しますが、ここではどのSignerを選んでもコントラクトの文字列を表示します。
次は、コントラクト(<-で表現されるものはリソースと呼ぶらしい)をストレージに保存して、他のアカウントからアクセスできないようにします。記述したら上と同様デプロイします。

保存されたリソースが実行できることを確認します。loadしたリソースは戻すか破棄する必要があるようです。次に他のアカウントからアクセスできる方法を考えます。

0x02アカウントのストレージにあるリソースをloadするのではなく、linkを取得します。ためしに0x03アカウントでトランザクションを送信しますがエラーになりまだアクセスできません。

0x02アカウントで送信するともちらん成功しました。

他のアカウントからアクセスするためには、少しトランザクションを変更したものを用意し送信してみます。今度は成功しました。

このような感じで、Playgroundではアカウントの切り替えなど直感的で、Flowのしくみを学ぶことができます。NFTが得意とされているようですので、また次の機会に試してみたいと思います。

参考動画

Lightning Network

ビットコインのマイクロペイメントに対応したオフチェーンネットワークLightning Networkを試してみました。

https://github.com/lightningnetwork/lnd/tree/master/docker

現在のブロックチェーンはスケーラビリティなど今後問題になってくる技術的な課題があり、それを克服するために(メインチェーン/オンチェーンに負担をかけないような)様々な工夫が用意されています。そのアプローチの仕方が各ブロックチェーンごとに個性的(Layer2、クロスチェーンなどなど)で、技術的好奇心が掻き立てられます。ビットコインではオンチェーンとは独自のしくみのオフチェーンでペイメントチャンネルを経由してコインの売買ができるようです。(ノード構築のインセンティブは手数料)

簡単に言えば取引ごとにオンチェーンに書き込むのではなく、まとまった取引の開始(チャンネルを開く)と終了(チャンネルを閉じる)のみとし、取引自体はオフチェーンで実行されることのようです。

ここでは上記サイトのdockerによる実装を試しました。3つのコンソールを開きメインコンソールではbitcoinデーモン、アリス用のコンソールではdockerで実装されたアリスノード、もう一つはボブ用です。アリスからボブへの送金を試みます。ちょっと長いため最後にまとめて配置しました。

ここ最近、にわかですがブロックチェーンの情報収集をしていて思うことは、ちょっと大げさですが人類があらゆる知恵を絞り出してこの分野に取り組んでいるような気がしてしまいます。ビットコインとならぶ存在のイーサリアム、新しい存在の、ポルカドット、カルダノ、ソラナ、コスモス、ニア、フローなど、様々な背景のある人たちが入り混じって取り組んでいます。エンジニアとして感じたことは暗号通貨のチャートにオープンソースのリンクがあることに、なんという時代になってきたんだ、と思ってしまいます。(資金調達・取引のメカニズムがコードになっていて、バーチャルだけでなくリアルの世界で通用してしまっている) またそれぞれのBlockchainには思想があり、それを支持する人の主義主張をきくのも興味深いです。ネットワークの安定維持(ノード構築のインセンティブ)、分散化(特定の人の影響力が大きくならないようなしくみ)、TPSのような性能をバランスよく最大化させるアイディアは、暗号通貨のことだけでなく、次世代の社会インフラを考える際のヒントになります。次世代ブロックチェーンの議論については、現在のしくみを生かして改善する考え方と、新しいしくみを根本から作ってしまう考え方とわかれる傾向にあるのかなと感じます。(Lightning Networkは前者)

かつてパソコンの黎明期国内外様々なメーカが独自規格のハード、OSを作っていましたが、今のブロックチェーンの規格は、なんかそのころに似ている気がしています。(とても活気があってエキサイティング) そこから思うことは、決してエンジニア目線で良いと思ったものが必ずしも強くないことです。WINTELが勝ち取ってきたようにユーザに近いところが充実しているものが強いのかもしれません。

とはいってもSolidity、Cadence、SimplicityといったBlockchainならではのキーワード、従来のキーワードでもあまり表に出てこなかった、Rust、WebAssembly、Haskellがクローズアップされており、反応してしまいます。今回もdockerが多用されていますが、これまでもテストしたWeb3, React / Node などもあわせて最近のフロントエンドからバックエンドまであらゆるものが活用されているのがわかります。こういったことからも世界中のエンジニアが総力戦で取り組んでいる気がして、前の大げさな表現になりました。

Blockchain、面白すぎです。

環境) Ubuntu20.4/WSL/Windows11

Main Console

$ export NETWORK="simnet" $ docker volume create simnet_lnd_alice simnet_lnd_alice $ docker volume create simnet_lnd_bob simnet_lnd_bob $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 1dd1039ed38b lnd "./start-lnd.sh" 12 seconds ago Up 11 seconds 9735/tcp, 10009/tcp alice e4fc59546fff btcd "./start-btcd.sh" 15 seconds ago Up 12 seconds 8333-8334/tcp, 18333-18334/tcp, 18555-18556/tcp, 28901-28902/tcp btcd (alice console) $ MINING_ADDRESS=rX6B5SfUFCeCDi8mei55RVctaLh8nJUXEX docker-compose up -d btcd Recreating btcd ... done $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 900848493f15 btcd "./start-btcd.sh" 5 seconds ago Up 4 seconds 8333-8334/tcp, 18333-18334/tcp, 18555-18556/tcp, 28901-28902/tcp btcd 1dd1039ed38b lnd "./start-lnd.sh" 4 minutes ago Up 4 minutes 9735/tcp, 10009/tcp alice $ docker exec -it btcd /start-btcctl.sh generate 400 [ "30513adbb2ea06a2f41ff6e820f28c0541f74add61db7221288695ca0fedfdf0", "63e8712d9c82c85c3420747b9d0c2dcb0830054154f39fbbd69b650d6a08d335", "5d63dd30dba612b8fcb98583439a278b3189240064366c2943fcb5acab7710a4", "5440ecd7403fd4cbafc54cf2463dc970c774b6cc42a8fd7c3aa7bb511a9937c9", "60730b05b5ad1b420ed8423a4ba399cf673e1dde3dbb0158558a92424f28f7f7", "403844d8e249f4977d143dc60ba8bd4954f98e1ef75ec81c2b0650201928cc86", "78ca8280c6a6de6e18122759459a7f385f290c48d99cfee6a5314fc36508cb6f", "413968a4d9a6377b8fe791aa3168778ac2525f162078124a0b25423259afdf9c", "5e4b2583234d35c0669418546593325f08efe450fc469691831aea84c1983ac0", "19d4d6ec5229152e3b95e0b65d4db5ed3c75dcee23a75c9159025813a490b8dd", "77d779970fc355f5f6820710907433570a1e9e47e68262a1f280f5913213bcbd", "781d8f2adc43261023e45562b169a9e3a60d08f68cf858f8ea5afd7e8f804844", "363204521e8f8e36e0a6be1428958c1a2f43a875156e6623fd60612b99588f76", "6ae88c7fbe26730e5590df3785ac6758c999a696fa8b1268b828550bf6727a8b", "1ad55b323913f41fe25d8dd5c284526a446192d43710e3fd4bfe2e1a71920ccd", ... $ docker exec -it btcd /start-btcctl.sh getblockchaininfo | grep -A 1 segwit "segwit": { "status": "active", $ (bob console) $ docker inspect bob | grep IPAddress "SecondaryIPAddresses": null, "IPAddress": "", "IPAddress": "172.20.0.4", (alice consolからbob-nodeに接続addressddress) (alice でoepnchannelel) $ docker exec -it btcd /start-btcctl.sh generate 3 [ "04a28809c867e71fa0c70630cf81885fadddafc2a9759588e5d6dfcdea07a424", "6e121d9e71bb4ad2e5f35d14bbf3f00e7a943cd18c87b3a4cc531421308a9fb5", "4c4e90c4e94321fe425d6280535cb26c2068e367577ef3f3acec9507c76bcce6" ] (alice でclosechannelel) $ docker exec -it btcd /start-btcctl.sh generate 3 [ "62dab67d832a50f2d69c3f86e88eea425fae796100751e3554845271542001d9", "7f58bd2257d43be5f4853d73bcf220f2ef6bf65c2a703d6fa9961cd41c81b014", "538ae071300bfa5f437ccd815d737812d4753dd2bd6cf7b0484b4d6d042362e6" ]
Code language: JavaScript (javascript)

Alice Console

$ docker-compose run -d --name alice --volume simnet_lnd_alice:/root/.lnd lnd Creating btcd ... done alice $ docker exec -i -t alice bash bash-5.1# bash-5.1# lncli --network=simnet walletbalance { "total_balance": "0", "confirmed_balance": "0", "unconfirmed_balance": "0", "account_balance": { "default": { "confirmed_balance": "0", "unconfirmed_balance": "0" } } } bash-5.1# lncli --network=simnet channelbalance { "balance": "0", "pending_open_balance": "0", "local_balance": { "sat": "0", "msat": "0" }, "remote_balance": { "sat": "0", "msat": "0" }, "unsettled_local_balance": { "sat": "0", "msat": "0" }, "unsettled_remote_balance": { "sat": "0", "msat": "0" }, "pending_open_local_balance": { "sat": "0", "msat": "0" }, "pending_open_remote_balance": { "sat": "0", "msat": "0" } } bash-5.1# lncli --network=simnet newaddress np2wkh { "address": "rX6B5SfUFCeCDi8mei55RVctaLh8nJUXEX" } (addressをmainin colsoleのMINING_ADDRESSSS.Recreating btcdするとwalletbalanceが変化nceが変化変化-5.1# lncli --network=simnet walletbalance { "total_balance": "1505000000000", "confirmed_balance": "1505000000000", "unconfirmed_balance": "0", "account_balance": { "default": { "confirmed_balance": "1505000000000", "unconfirmed_balance": "0" } } } (main consoleからaddressress,bob consoleからpubkey所得してbob得してbobてbobob nodeに接続接続-5.1# bash-5.1# lncli --network=simnet connect 0204e6918ae3239cc8da262715e5ada2d3540cc9fec6db7d6b72e544e2c77f6cac@172.20.0.4 { } bash-5.1# lncli --network=simnet listpeers { "peers": [ { "pub_key": "0204e6918ae3239cc8da262715e5ada2d3540cc9fec6db7d6b72e544e2c77f6cac", "address": "172.20.0.4:9735", "bytes_sent": "391", "bytes_recv": "391", "sat_sent": "0", "sat_recv": "0", "inbound": false, "ping_time": "0", "sync_type": "ACTIVE_SYNC", "features": { "0": { "name": "data-loss-protect", "is_required": true, "is_known": true }, "5": { "name": "upfront-shutdown-script", "is_required": false, "is_known": true }, "7": { "name": "gossip-queries", "is_required": false, "is_known": true }, "9": { "name": "tlv-onion", "is_required": false, "is_known": true }, "12": { "name": "static-remote-key", "is_required": true, "is_known": true }, "14": { "name": "payment-addr", "is_required": true, "is_known": true }, "17": { "name": "multi-path-payments", "is_required": false, "is_known": true }, "23": { "name": "anchors-zero-fee-htlc-tx", "is_required": false, "is_known": true }, "31": { "name": "amp", "is_required": false, "is_known": true }, "45": { "name": "explicit-commitment-type", "is_required": false, "is_known": true }, "2023": { "name": "script-enforced-lease", "is_required": false, "is_known": true } }, "errors": [ ], "flap_count": 1, "last_flap_ns": "1642158005985969341", "last_ping_payload": null } ] } bash-5.1# bash-5.1# lncli --network=simnet openchannel --node_key=0204e6918ae3239cc8da262715e5ada2d3540cc9fec6db7d6b72e544e2c77f6cac --local_amt=1234567 { "funding_txid": "05b707addfd5aae36fdf62610376e45d4d6859f9e559a5e24957ce173e1a284b" } (main coloseでfundingng transaction) bash-5.1# lncli --network=simnet listchannels { "channels": [ { "active": true, "remote_pubkey": "0204e6918ae3239cc8da262715e5ada2d3540cc9fec6db7d6b72e544e2c77f6cac", "channel_point": "05b707addfd5aae36fdf62610376e45d4d6859f9e559a5e24957ce173e1a284b:0", "chan_id": "887305883680768", "capacity": "1234567", "local_balance": "1231097", "remote_balance": "0", "commit_fee": "3140", "commit_weight": "772", "fee_per_kw": "2500", "unsettled_balance": "0", "total_satoshis_sent": "0", "total_satoshis_received": "0", "num_updates": "0", "pending_htlcs": [ ], "csv_delay": 148, "private": false, "initiator": true, "chan_status_flags": "ChanStatusDefault", "local_chan_reserve_sat": "12345", "remote_chan_reserve_sat": "12345", "static_remote_key": false, "commitment_type": "ANCHORS", "lifetime": "38", "uptime": "38", "close_address": "", "push_amount_sat": "0", "thaw_height": 0, "local_constraints": { "csv_delay": 148, "chan_reserve_sat": "12345", "dust_limit_sat": "354", "max_pending_amt_msat": "1222222000", "min_htlc_msat": "1", "max_accepted_htlcs": 483 }, "remote_constraints": { "csv_delay": 148, "chan_reserve_sat": "12345", "dust_limit_sat": "354", "max_pending_amt_msat": "1222222000", "min_htlc_msat": "1", "max_accepted_htlcs": 483 } } ] } (bob consoleで-5.1# lncli --network=simnet sendpayment --pay_req=lnsb555550n1ps7zkvupp5fd6kx42j5dgd2dc0znmev8et60vqnkcl09nt4al48sjeelf4d76qdqqcqzpgxqyz5vqsp5atu4jx427nlgrwmchg32scz2e3qjdflrxjswcynee34vp3rh3c8s9qyyssqlqfdy6ncp6lm8fs6uyec0yyrqz5aazcum9ehq355x4qpl5c36tj88u5mc636w7aw7n8xjetcgek47hh3u4qp3nprj8k5r6k0cpp837gqusyazn Payment hash: 4b75635552a350d5370f14f7961f2bd3d809db1f7966baf7f53c259cfd356fb4 Description: Amount (in satoshis): 55555 Fee limit (in satoshis): 55555 Destination: 0204e6918ae3239cc8da262715e5ada2d3540cc9fec6db7d6b72e544e2c77f6cac Confirm payment (yes/no): yes +------------+--------------+--------------+--------------+-----+----------+-----------------+-------+ | HTLC_STATE | ATTEMPT_TIME | RESOLVE_TIME | RECEIVER_AMT | FEE | TIMELOCK | CHAN_OUT | ROUTE | +------------+--------------+--------------+--------------+-----+----------+-----------------+-------+ | SUCCEEDED | 0.025 | 0.227 | 55555 | 0 | 852 | 887305883680768 | | +------------+--------------+--------------+--------------+-----+----------+-----------------+-------+ Amount + fee: 55555 + 0 sat Payment hash: 4b75635552a350d5370f14f7961f2bd3d809db1f7966baf7f53c259cfd356fb4 Payment status: SUCCEEDED, preimage: 2cf46eed79d3aa72f942ea8a2eeb4f7aa50c437670d51e9e98d350fd232ba8ab bash-5.1# bash-5.1# lncli --network=simnet channelbalance { "balance": "1175542", "pending_open_balance": "0", "local_balance": { "sat": "1175542", "msat": "1175542000" }, "remote_balance": { "sat": "55555", "msat": "55555000" }, "unsettled_local_balance": { "sat": "0", "msat": "0" }, "unsettled_remote_balance": { "sat": "0", "msat": "0" }, "pending_open_local_balance": { "sat": "0", "msat": "0" }, "pending_open_remote_balance": { "sat": "0", "msat": "0" } } bash-5.1# lncli --network=simnet listchannels { "channels": [ { "active": true, "remote_pubkey": "0204e6918ae3239cc8da262715e5ada2d3540cc9fec6db7d6b72e544e2c77f6cac", "channel_point": "05b707addfd5aae36fdf62610376e45d4d6859f9e559a5e24957ce173e1a284b:0", "chan_id": "887305883680768", "capacity": "1234567", "local_balance": "1175542", "remote_balance": "55555", "commit_fee": "2810", "commit_weight": "1116", "fee_per_kw": "2500", "unsettled_balance": "0", "total_satoshis_sent": "55555", "total_satoshis_received": "0", "num_updates": "2", "pending_htlcs": [ ], "csv_delay": 148, "private": false, "initiator": true, "chan_status_flags": "ChanStatusDefault", "local_chan_reserve_sat": "12345", "remote_chan_reserve_sat": "12345", "static_remote_key": false, "commitment_type": "ANCHORS", "lifetime": "438", "uptime": "438", "close_address": "", "push_amount_sat": "0", "thaw_height": 0, "local_constraints": { "csv_delay": 148, "chan_reserve_sat": "12345", "dust_limit_sat": "354", "max_pending_amt_msat": "1222222000", "min_htlc_msat": "1", "max_accepted_htlcs": 483 }, "remote_constraints": { "csv_delay": 148, "chan_reserve_sat": "12345", "dust_limit_sat": "354", "max_pending_amt_msat": "1222222000", "min_htlc_msat": "1", "max_accepted_htlcs": 483 } } ] } (上記-5.1# lncli --network=simnet closechannel --funding_txid=05b707addfd5aae36fdf62610376e45d4d6859f9e559a5e24957ce173e1a284b --output_index=0 { "closing_txid": "1b8f588256cedc8e31ed5818bdcd1edc5deff96ced9bfebe59acfc3fca8f7629" } (main coloseでfundingng transaction) bash-5.1# lncli --network=simnet walletbalance { "total_balance": "1534999932848", "confirmed_balance": "1534999932848", "unconfirmed_balance": "0", "account_balance": { "default": { "confirmed_balance": "1534999932848", "unconfirmed_balance": "0" } } } bash-5.1#
Code language: PHP (php)

Bob Console

$ docker-compose run -d --name bob --volume simnet_lnd_bob:/root/.lnd lnd Starting btcd ... done bob $ docker exec -i -t bob bash bash-5.1# lncli --network=simnet walletbalance { "total_balance": "2029999990000", "confirmed_balance": "2029999990000", "unconfirmed_balance": "0", "account_balance": { "default": { "confirmed_balance": "2029999990000", "unconfirmed_balance": "0" } } } bash-5.1# lncli --network=simnet channelbalance { "balance": "0", "pending_open_balance": "0", "local_balance": { "sat": "0", "msat": "0" }, "remote_balance": { "sat": "0", "msat": "0" }, "unsettled_local_balance": { "sat": "0", "msat": "0" }, "unsettled_remote_balance": { "sat": "0", "msat": "0" }, "pending_open_local_balance": { "sat": "0", "msat": "0" }, "pending_open_remote_balance": { "sat": "0", "msat": "0" } } bash-5.1# lncli --network=simnet getinfo { "version": "0.14.1-beta commit=v0.14.1-beta-dirty", "commit_hash": "6042004edaaa5b3cad0a0808ff23dba4716f7178", "identity_pubkey": "0204e6918ae3239cc8da262715e5ada2d3540cc9fec6db7d6b72e544e2c77f6cac", "alias": "0204e6918ae3239cc8da", "color": "#3399ff", "num_pending_channels": 0, "num_active_channels": 0, "num_inactive_channels": 0, "num_peers": 0, "block_height": 806, "block_hash": "56e1d3d993da053d4b50cdd08b8101f72d91fac1a42845cef06eebc3a4293d2d", "best_header_timestamp": "1642157626", "synced_to_chain": true, "synced_to_graph": false, "testnet": false, "chains": [ { "chain": "bitcoin", "network": "simnet" } ], "uris": [ ], "features": { "0": { "name": "data-loss-protect", "is_required": true, "is_known": true }, "5": { "name": "upfront-shutdown-script", "is_required": false, "is_known": true }, "7": { "name": "gossip-queries", "is_required": false, "is_known": true }, "9": { "name": "tlv-onion", "is_required": false, "is_known": true }, "12": { "name": "static-remote-key", "is_required": true, "is_known": true }, "14": { "name": "payment-addr", "is_required": true, "is_known": true }, "17": { "name": "multi-path-payments", "is_required": false, "is_known": true }, "23": { "name": "anchors-zero-fee-htlc-tx", "is_required": false, "is_known": true }, "30": { "name": "amp", "is_required": true, "is_known": true }, "31": { "name": "amp", "is_required": false, "is_known": true }, "45": { "name": "explicit-commitment-type", "is_required": false, "is_known": true }, "2023": { "name": "script-enforced-lease", "is_required": false, "is_known": true } } } (pubkey->alice console) bash-5.1# bash-5.1# lncli --network=simnet listpeers { "peers": [ { "pub_key": "035a928e2fdb16f8356735d189028bd2a424f10d6dea8b997b66ac27811c6e996a", "address": "172.20.0.3:44330", "bytes_sent": "391", "bytes_recv": "391", "sat_sent": "0", "sat_recv": "0", "inbound": true, "ping_time": "0", "sync_type": "ACTIVE_SYNC", "features": { "0": { "name": "data-loss-protect", "is_required": true, "is_known": true }, "5": { "name": "upfront-shutdown-script", "is_required": false, "is_known": true }, "7": { "name": "gossip-queries", "is_required": false, "is_known": true }, "9": { "name": "tlv-onion", "is_required": false, "is_known": true }, "12": { "name": "static-remote-key", "is_required": true, "is_known": true }, "14": { "name": "payment-addr", "is_required": true, "is_known": true }, "17": { "name": "multi-path-payments", "is_required": false, "is_known": true }, "23": { "name": "anchors-zero-fee-htlc-tx", "is_required": false, "is_known": true }, "31": { "name": "amp", "is_required": false, "is_known": true }, "45": { "name": "explicit-commitment-type", "is_required": false, "is_known": true }, "2023": { "name": "script-enforced-lease", "is_required": false, "is_known": true } }, "errors": [ ], "flap_count": 1, "last_flap_ns": "1642158005986281830", "last_ping_payload": null } ] } (alice consoleでopenen channel) bash-5.1# bash-5.1# lncli --network=simnet addinvoice --amt=55555 { "r_hash": "4b75635552a350d5370f14f7961f2bd3d809db1f7966baf7f53c259cfd356fb4", "payment_request": "lnsb555550n1ps7zkvupp5fd6kx42j5dgd2dc0znmev8et60vqnkcl09nt4al48sjeelf4d76qdqqcqzpgxqyz5vqsp5atu4jx427nlgrwmchg32scz2e3qjdflrxjswcynee34vp3rh3c8s9qyyssqlqfdy6ncp6lm8fs6uyec0yyrqz5aazcum9ehq355x4qpl5c36tj88u5mc636w7aw7n8xjetcgek47hh3u4qp3nprj8k5r6k0cpp837gqusyazn", "add_index": "1", "payment_addr": "eaf9591aaaf4fe81bb78ba22a8604acc4126a7e334a0ec1279cc6ac0c4778e0f" } (payment_request->alice console.alice console: send payment from alice to bob) bash-5.1# lncli --network=simnet channelbalance { "balance": "55555", "pending_open_balance": "0", "local_balance": { "sat": "55555", "msat": "55555000" }, "remote_balance": { "sat": "1175542", "msat": "1175542000" }, "unsettled_local_balance": { "sat": "0", "msat": "0" }, "unsettled_remote_balance": { "sat": "0", "msat": "0" }, "pending_open_local_balance": { "sat": "0", "msat": "0" }, "pending_open_remote_balance": { "sat": "0", "msat": "0" } } bash-5.1# bash-5.1# lncli --network=simnet walletbalance { "total_balance": "2030000045555", "confirmed_balance": "2030000045555", "unconfirmed_balance": "0", "account_balance": { "default": { "confirmed_balance": "2030000045555", "unconfirmed_balance": "0" } } } bash-5.1#
Code language: PHP (php)

※code中、漢字がまざると文字化けが・・まだこのテーマになれない・・

Web3.js + React.js

ユーザが使うDapps(Decentralized Applications)という形にするにはUIが必要で、Webブラウザを使う方法は代表的な形になるのでしょう。

フロントエンドでよく使われるweb3.js と react.jsを、ここまで作ったしくみに追加してみました。

https://zenn.dev/shunp110/articles/630a0166f468e4

上記、参考にさせていただきました。

環境) Ubuntu20.04/WSL/Windows11

$ node -v
v16.13.1
$ npm -v
8.1.2
$ npx -v
8.1.2
$ npm install web3
$ npm install -g serve
$ npx clear-npx-cache
$ npx create-react-app my-app
$ cd my-app
$ export NODE_OPTIONS=”–max-old-space-size=1024″

src/App.js

import "./App.css"; import Web3 from "web3/dist/web3.min.js" import ABI from "./contracts/Hello.json"; const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); const address = "0x482a64967a50076C6F00b0bD859F56514eA07402"; const abi = ABI.abi; const contract = new web3.eth.Contract(abi, address); function App() { const handleCall = async () => { const msg = await contract.methods.get().call(); alert(msg); }; return ( <div className="App"> <h1>web3.js + react.js DEMO</h1> <button onClick={handleCall}>Call</button> </div> ); } export default App;
Code language: JavaScript (javascript)

contracts/Hello.json は下記でコンパイルした結果のbuildディレクトリのものを使用します。

http://bitlife.me/bc/2022/01/08/

また、上記で実行したように、Ganache-cliを立ち上げ、Deployをしたものとします。(conract address使用)

ビルド・実行

$ npm run build
$ serve -s build

rpm startでは、javascript heap out of memoryとなったため、このようにしました。

“scripts”: {
“start”: “react-scripts start”,
“build”: “GENERATE_SOURCEMAP=false react-scripts build”,
“test”: “react-scripts test”,
“eject”: “react-scripts eject”
},

不要かもしれませんが、package.jsonもこのようにしました。(-max-old-spaceも同様、いろいろ試行錯誤した結果なのでのこしておきます)

Call ボタンをクリックすると、上記Alertが表示されました。

何気ない画面ですが、いろんなものが詰まっています。ここまで効率的に開発できるのもやはりフロントエンド、バックエンドのJavaScript環境が強力だからでしょう。この充実ぶりはホットであることの証明ですね。

(web3.js という名前自体が、Web3.0の時代もJSだよね、と)

モダンなJavaScriptをためした記事のリンクを下記に参考まで

https://decode.red/blog/202112051381/
https://decode.red/blog/202106061289/
https://decode.red/ed/archives/1125
https://decode.red/ed/archives/1153

http://bitlife.me/bc/2022/02/11/

Ethereum IDE (Remix) & MetaMask

いよいよGUIツールを使って送金やコントラクトの動作確認をしてみました。

ベースとなる環境は前回のGanacheでデフォルトのID二つ使います。

Ganache-cli立ち上げ時に表示されるPrivateKeyをMetaMaskにインポートしてアカウントを作成します。(デフォルトでアカウントはアンロックされている) ネットワークはGanacheをdevelopmentとして追加します。(127.0.0.1:8545にRPC接続。いろいろと調べてチェーンIDは1337とした)

MetaMaskでは、0x827..がAccount3、0xA28…がAccount4で最初は同じ100ETHの画面。

Account3から4に10ETH送金しました。ガス代として0.00042ETHがひかれているのを確認できます。
送金前後[0][1]の差異
アクティビティから詳細が確認できます。

Account4にはアクティビティがありませんでした。

次に、Remixを試してみます。

Solidityのサンプルサイトからカウントをインクリメント、ディクリメントするコードを新規作成し、コンパイル、デプロイデバッグ実行しました。(まず上記コンパイルボタン押す)
デプロイ画面で、ENVIRONMENTでWeb3Providerを選択し、ローカルのGanacheに接続します。この時デフォルトで[0]番目のアカウントが選択されました。デプロイボタンを押すと、下にメニューが追加されます。

自動的に関数のボタンが作成され、デバッグ体制を作ってくれます。

inc,decで値を増減させ、getまたはcount(変数)で数値を表示します。(上記incを一回押し、getを押した様子)

他にもいろいろと動かしみましたが、まだエラー解決に時間がかかります。(ネットの記事、YouTube動画などで動作確認済のはずのものが思い通り動かせないなど・・書籍などでも古めで、2018年くらいの情報が多い。。しかしブロックチェーンの本質はかわらないので、対応していくのみ)

これらのツールを使って効率よく開発をすすめていきたいと思います。(Ganache便利! これもGUI版あるみたいなのでまた)

Truffle.js Framework

Ethereum 環境の理解を深めるために、以前フレームワークやツールを使わずテストをしましたが、今回はTruffle.jsフレームワークを使って構築・テストをしたいと思います。

参考: https://zenn.dev/shunp110/articles/0080928ab43289
  : https://qiita.com/toshiok/items/12b47b28e5fb6c5909b1

以前Gethで作ったブロックチェーンのローカル環境は、Ganacheを使います。

環境: Ubuntu20.04/WSL/Windows11

$ node -v
v16.13.1
$ npm -v
8.1.2

インストール

$ sudo npm install -g truffle
$ sudo npm install -g ganache-cli

ネットワーク起動

$ ganache-cli
Ganache CLI v6.12.2 (ganache-core: 2.13.2)
Available Accounts
(0) 0x6Adc538Ed8526217B04354DDF6E15dF53039B986 (100 ETH)
(1) 0xcB2289aAa662eadFDCB5c0655E88B6a44dc11FaD (100 ETH)
(2) 0x85B350bC7c0c75D70EE9FE5e3d20c5Ead091F8dA (100 ETH)
(3) 0x3CC61a4a4E70Ae097390f6d0DfC8c56c9555EFD9 (100 ETH)
(4) 0x12099D695cc5526D9A71944F3b551b03b25A3Fee (100 ETH)
….

アカウントやETHがあらかじめ用意されています。

次に、別コンソールでコードの作成、configの編集、コンパイル、デプロイ、コンソールの実行をします。

$ truffle init

contracts/Hello.sol

pragma solidity >=0.4.22 <0.9.0; contract Hello { function get() public pure returns (string memory) { return "Hello!"; } }
Code language: JavaScript (javascript)

migrations/2_hello.js

const Hello = artifacts.require("Hello"); module.exports = function (deployer) { deployer.deploy(Hello); };
Code language: JavaScript (javascript)

(デフォルトで生成される、1_initial_migrations.js をそのままにしたため2_という名前にする)

truffle_config.js

development: { host: "127.0.0.1", // Localhost (default: none) port: 8545, // Standard Ethereum port (default: none) network_id: "*", // Any network (default: none) },
Code language: CSS (css)

上記部分のコメントをはずす。

$ truffle compile

$ truffle migrate –network development

Compiling your contracts...
===========================
> Everything is up to date, there is nothing to compile.

Starting migrations...
======================
> Network name:    'development'
> Network id:      1641626547449
> Block gas limit: 6721975 (0x6691b7)

1_initial_migration.js
======================
   Deploying 'Migrations'
   ----------------------
   > transaction hash:    0xaf7dc12859e4a1275e2daa1710c2ce7673652a7da394f395435fad33879c84f1
   > Blocks: 0            Seconds: 0
   > contract address:    0x67cD5Bee85BBbFFF12F8482711fB8649F506a4e5
   > block number:        1
   > block timestamp:     1641626555
   > account:             0x6Adc538Ed8526217B04354DDF6E15dF53039B986
   > balance:             99.99502292
   > gas used:            248854 (0x3cc16)
   > gas price:           20 gwei
   > value sent:          0 ETH
   > total cost:          0.00497708 ETH

   > Saving migration to chain.
   > Saving artifacts
   -------------------------------------
   > Total cost:          0.00497708 ETH

2_hello.js
==========
   Deploying 'Hello'
   -----------------
   > transaction hash:    0xad64a961af2ce0ccab6901c45fd7030c2fe8a91cc480ac996267c508ef3a3081
   > Blocks: 0            Seconds: 0
   > contract address:    0x0A551aEF4c63f9a77eC2f307D9e99878C7c32Ee6
   > block number:        3
   > block timestamp:     1641626555
   > account:             0x6Adc538Ed8526217B04354DDF6E15dF53039B986
   > balance:             99.99147276
   > gas used:            134995 (0x20f53)
   > gas price:           20 gwei
   > value sent:          0 ETH
   > total cost:          0.0026999 ETH

   > Saving migration to chain.
   > Saving artifacts
   -------------------------------------
   > Total cost:           0.0026999 ETH

Summary
=======
> Total deployments:   2
> Final cost:          0.00767698 ETH

$ truffle console –network development

truffle(development)> web3.eth.getAccounts(function(err, data){accounts = data });
[
‘0x6Adc538Ed8526217B04354DDF6E15dF53039B986’,
‘0xcB2289aAa662eadFDCB5c0655E88B6a44dc11FaD’,
‘0x85B350bC7c0c75D70EE9FE5e3d20c5Ead091F8dA’,
‘0x3CC61a4a4E70Ae097390f6d0DfC8c56c9555EFD9’,
‘0x12099D695cc5526D9A71944F3b551b03b25A3Fee’,
‘0x3Ff15F4c7EEC3338104645780D6c78C6ca9103A7’,
‘0x2095e763CD5bD681308d259905D4eDCE0e7f9Af3’,
‘0xcFAd6063c4B5FF7233950Ca55f34Aa56eF72175a’,
‘0xA0BA9eB80Bd62D0c56CAe6311Cb8C7482F21523f’,
‘0xa4188D85d855bD1837e31C9EA5251bC75c650014’
]
truffle(development)> web3.eth.getBalance(accounts[0]);
‘99990922500000000000’
truffle(development)> web3.eth.getBalance(accounts[1]);
‘100000000000000000000’
truffle(development)> web3.eth.sendTransaction({from: accounts[0], to: accounts[1], value: web3.utils.toWei(’20’,’ether’)});
{
transactionHash: ‘0x4e040a381ba1bae54f090b0b60e723b5f0c0e0fed2fab660e925cd7ecc040d72’,
transactionIndex: 0,
blockHash: ‘0x975091b47f1343022343bc87c4880b64328d79117a457891a7f7bb62049ca10b’,
blockNumber: 5,
from: ‘0x6adc538ed8526217b04354ddf6e15df53039b986’,
to: ‘0xcb2289aaa662eadfdcb5c0655e88b6a44dc11fad’,
gasUsed: 21000,
cumulativeGasUsed: 21000,
….
truffle(development)> web3.eth.getBalance(accounts[0]);
‘79990502500000000000’
truffle(development)> web3.eth.getBalance(accounts[1]);
‘120000000000000000000’
truffle(development)> web3.eth.getTransaction(‘0x4e040a381ba1bae54f090b0b60e723b5f0c0e0fed2fab660e925cd7ecc040d72’);
{
hash: ‘0x4e040a381ba1bae54f090b0b60e723b5f0c0e0fed2fab660e925cd7ecc040d72’,
nonce: 4,
blockHash: ‘0x975091b47f1343022343bc87c4880b64328d79117a457891a7f7bb62049ca10b’,
blockNumber: 5,
transactionIndex: 0,
from: ‘0x6Adc538Ed8526217B04354DDF6E15dF53039B986’,
to: ‘0xcB2289aAa662eadFDCB5c0655E88B6a44dc11FaD’,
value: ‘20000000000000000000’,
gas: ‘0x15f90’,
gasPrice: ‘20000000000’,
input: ‘0x’,
v: ‘0x25’,
r: ‘0xae5a478f99b3a927b949957b50f7a11d063a342f10cd19350f4032d2d5474e30’,
s: ‘0x4f25702b2eba9d2aa51cd895f013848c0afdc00f56d5e5c8b8d9e700c06b6222’
}
truffle(development)> Hello.deployed().then( c => instance = c );
TruffleContract {
constructor: [Function: TruffleContract] {
_constructorMethods: {
configureNetwork: [Function: configureNetwork],
setProvider: [Function: setProvider],
….
truffle(development)> instance.get()
‘Hello!’

コンソールでは、ETHの送金、確認、それからコントラクトの関数の実行をしています。accounts[0]のETHが最初から少ないのは、デプロイのときにGAS代がひかれています。

この組み合わせは、gethで構築したことを考えると本当にありがたく感じます。IDEとかはまた試す予定です。

※まだこのブログテーマの使い方になれていないせいで、表示が見づらい点がありますが、改善していきます。

Bitcoin Core

ここまでEthereumやSymbolをさわってきましたが、やはり基本はBitcoinということでこのブログの開始にあたり、環境を整えました。

bitcoin-cliを使っていろいろとテストしようと、最初はdockerとか使った簡単な(と思われる)やり方を試しましたが、情報が古かったりうまく動作しなかったため、やはりソースから実装することにしました。

参考) [bitcoin]自分のsignetを立てよう

環境) Ubuntu20.4/WSL/ Windows 11

git clone https://github.com/bitcoin/bitcoin.git
cd bitcoin

sudo apt install build-essential libtool autotools-dev automake pkg-config bsdmainutils python3

sudo apt install libevent-dev libboost-dev libboost-system-dev libboost-filesystem-dev libboost-test-dev

./contrib/install_db4.sh pwd

export BDB_PREFIX=’/home/k/work1/bitcoin/db4′

./autogen.sh

./configure BDB_LIBS=”-L${BDB_PREFIX}/lib” BDB_CFLAGS=”-I${BDB_PREFIX}/include” –disable-tests –disable-bench –without-gui –without-miniupnpc –with-utils –with-sqlite=yes –without-bdb

make

sudo make install

walletを作成するときにsqliteが使えるようにする必要があるため上記のようにconfigureオプションに加えました。

signetの起動

$ bitcoind -signet

Walletの作成

$ bitcoin-cli -signet createwallet testwallet
{
“name”: “testwallet”,
“warning”: “”
}

アドレス取得

$ bitcoin-cli -signet getnewaddress
tb1qw8k2tutz36qpfmtes2jny2wcmavh0mt2edvt96

情報取得

$ bitcoin-cli -signet getblockchaininfo
{
“chain”: “signet”,
“blocks”: 71428,
“headers”: 71428,
“bestblockhash”: “000000dc046a49f82b6bb65633ba4650e093f7fd2e7956efa65304c0a545fbdd”,
“difficulty”: 0.002700124394835933,
“time”: 1641274764,
“mediantime”: 1641272545,
“verificationprogress”: 0.9999990656266684,
“initialblockdownload”: false,
“chainwork”: “000000000000000000000000000000000000000000000000000000c98018dd0a”,
“size_on_disk”: 231372553,
“pruned”: false,
“softforks”: {
“bip34”: {
“type”: “buried”,
“active”: true,
“height”: 1 ………

以下サイトでも確認。

次はフォーセットからコインの取得です。

bitcoind では以下のようにtestwalletへの入金のトランザクションが表示され、(フォーセットのページのtxidの値 1e4645….)

2022-01-04T05:17:57Z UpdateTip: new best=000000b99486707164e3ebb0ae6e7a4ab0e63872b79c54a13fa716a3602a3b67 height=71424 version=0x20000000 log2_work=39.654561 tx=734111 date=’2022-01-04T05:17:56Z’ progress=1.000000 cache=0.0MiB(25txo)
2022-01-04T05:22:17Z [testwallet] AddToWallet 1e4645cdc4c9ce729f4b809668ea8ca16071a8b1b82db28372c9f18de3d97698 new
2022-01-04T05:22:30Z UpdateTip: new best=0000001f59a29230b5dc275f6b311ba506e1505d39f01c98ae5d59ada0155d31 height=71425 version=0x20000000 log2_work=39.654581 tx=734223 date=’2022-01-04T05:22:27Z’ progress=1.000000 cache=0.0MiB(192txo)
2022-01-04T05:22:30Z [testwallet] AddToWallet 1e4645cdc4c9ce729f4b809668ea8ca16071a8b1b82db28372c9f18de3d97698 update

コンソールでは、下記のように変化があることを確認できました。

$ bitcoin-cli -signet getbalance
0.00000000

$ bitcoin-cli -signet getbalance
0.01000000

結局、ソースからの構築の方が簡単でした。signetはブロック数がテストネットに比べて少ないので同期がはやく容量も少なく済むため使いやすいです。

まずは環境構築でした。

参考書籍) 「ビットコインとブロックチェーン(Mastering Bitcoin)」(NTT出版)

The First Post !

これまでBlockchain関連の記事を下記のように別のブログで書いてきましたが、もっと深く学習したいという思いから専用のブログを立ち上げました。(ハードフォーク?)

https://decode.red/net/archives/904

https://decode.red/net/archives/478
http://decode.red/blog/202201041398/
http://decode.red/blog/20181215924/
http://decode.red/blog/20160409562/

追記(このブログをはじめてから他で扱ったもの)

https://decode.red/blog/202209101492/