Home

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をためした記事のリンクを下記に参考まで

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

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