Decentralized Applications (DApps)
Introduction
Mastering EthereumのDecentralized Applications (DApps)を読んでいた際、オークションDAppのソースコード(auction_dapp)が古く、そのままでは動かなかったので、コードのアップデートやリファクタリングを行った。
本記事は2024/03時点のメモ。Swarm/Whisperの挙動は検討中。
環境の前提として、以下記事参照。
Challenge
- Swarm/Whisperへのエンドポイントに依存した実装になっている。
- 単一障害点となる可能性があるので、より完全な非中央集権化されたアプリケーションにしたい。
Development
Backend
特に修正不要だった。
version
$ truffle version
Truffle v5.11.5 (core: 5.11.5)
Ganache v7.9.1
Solidity v0.5.16 (solc-js)
Node v18.3.0
Web3.js v1.10.0
compile
$ truffle compile
Compiling your contracts...
===========================
> Compiling ./contracts/AuctionRepository.sol
> Compiling ./contracts/DeedRepository.sol
> Compiling ./contracts/ERC721/DeprecatedERC721.sol
> Compiling ./contracts/ERC721/ERC721.sol
> Compiling ./contracts/ERC721/ERC721Basic.sol
> Compiling ./contracts/ERC721/ERC721BasicToken.sol
> Compiling ./contracts/ERC721/ERC721Holder.sol
> Compiling ./contracts/ERC721/ERC721Receiver.sol
> Compiling ./contracts/ERC721/ERC721Token.sol
> Compiling ./contracts/Migrations.sol
> Compiling ./contracts/utils/AddressUtils.sol
> Compiling ./contracts/utils/math/Math.sol
> Compiling ./contracts/utils/math/SafeMath.sol
> Artifacts written to /Users/yuichirokondo/Workspace/Web3/auction_dapp/backend/build/contracts
> Compiled successfully using:
- solc: 0.5.16+commit.9c3226ce.Emscripten.clang
migrate
$ truffle migrate --network ganache
Compiling your contracts...
===========================
> Everything is up to date, there is nothing to compile.
Starting migrations...
======================
> Network name: 'ganache'
> Network id: 5777
> Block gas limit: 6721975 (0x6691b7)
1_initial_migration.js
======================
Deploying 'Migrations'
----------------------
> transaction hash: 0x7036c2139553229612302089c4755730ce624a36e69596a6b7ac0d14cc8eea9d
> Blocks: 0 Seconds: 0
> contract address: 0x1D81C57FD8f33C36E246Cf13D7Af29b54dd06a7C
> block number: 1
> block timestamp: 1709882400
> account: 0x633592b50220e1E87b106BfBF3A45F4D9157E7DA
> balance: 99.999235437625
> gas used: 226537 (0x374e9)
> gas price: 3.375 gwei
> value sent: 0 ETH
> total cost: 0.000764562375 ETH
> Saving migration to chain.
> Saving artifacts
-------------------------------------
> Total cost: 0.000764562375 ETH
2_deploy_contracts.js
=====================
Deploying 'AuctionRepository'
-----------------------------
> transaction hash: 0xd51654619cab51a67a1d998dbbbb7ea5eda1161a8b44a9ce306ad82fbb0c90ab
> Blocks: 0 Seconds: 0
> contract address: 0x29a412B146aAe61A0256707065cb94Bd4fcC6c8b
> block number: 3
> block timestamp: 1709882400
> account: 0x633592b50220e1E87b106BfBF3A45F4D9157E7DA
> balance: 99.992158969101747614
> gas used: 2179788 (0x2142cc)
> gas price: 3.177688086 gwei
> value sent: 0 ETH
> total cost: 0.006926686357605768 ETH
Deploying 'DeedRepository'
--------------------------
> transaction hash: 0x0cf04f8cf287f551f3dff93f3abff49547503f6c9941ef80f11a72823664ad1f
> Blocks: 0 Seconds: 0
> contract address: 0xC3daB6B7c84b0342607D5904b7214b7F1E3DAad6
> block number: 4
> block timestamp: 1709882400
> account: 0x633592b50220e1E87b106BfBF3A45F4D9157E7DA
> balance: 99.986355183038938641
> gas used: 1843691 (0x1c21eb)
> gas price: 3.147916903 gwei
> value sent: 0 ETH
> total cost: 0.005803786062808973 ETH
> Saving migration to chain.
> Saving artifacts
-------------------------------------
> Total cost: 0.012730472420414741 ETH
Summary
=======
> Total deployments: 3
> Final cost: 0.013495034795414741 ETH
Frontend
MetaMaskは2021年頃web3
オブジェクトではなくwindow.ethereum
オブジェクトを提供するようになったらしいので[1]、その修正。
それに伴い、その他細かい修正。
例えば、fromWei
をutils.fromWei
に修正など。
Content Delivery
Fleek
バックエンド側でtruffleでコンパイルしたコントラクトのjsonを動的にフロントエンド側にコピーできる仕組みを導入することで、Fleekにおけるデプロイを可能にしている。(今回はとりあえずshx cp
を使っているが、本来はGulp的なものに統合した方がいいかもしれない。)
Image Upload
Swarmじゃなくて、IPFSにしてみるのもありかも。
js-ipfs
とか使えばユーザのブラウザ側で画像をアップロードできそう。その場合ゲートウェイが不要となる。
Result
IPFS上に展開されている。
Discussion
Backend
DEEDREPOSITORY_ADDRESS
とAUCTIONREPOSITORY_ADDRESS
さえ変更すれば、WalletでBackend(ブロックチェーン)を切り替えられる。例えば、MetaMaskでネットワークを切り替えて、ローカルでGanacheを起動していればそれを使えるし、EthereumのTestnetやMainnetを使うこともできる。
DAppにおいてバックエンドを意味するブロックチェーンを切り替えることができるように設計することは、いくつかの利点がある。
-
ブロックチェーンの選択肢: 複数のブロックチェーン間での移行を可能にすることで、異なるネットワークの特徴(例えば、トランザクションコスト、速度、コミュニティのサポートなど)を活用できる。
-
将来の柔軟性: 技術の進化に伴い、新しいブロックチェーンが現れた場合や、より良いソリューションが利用可能になった場合に、容易に移行できる。
-
冗長性と耐障害性: もし一つのブロックチェーンに問題が生じた場合に、別のブロックチェーンにスムーズに切り替えることで、アプリケーションの稼働を継続できる。
スマートコントラクトのアドレスを外部から与えることができれば、異なるブロックチェーン環境や異なるスマートコントラクトのインスタンスに接続する柔軟性を持たせることができ、これは特に以下のような場合に有効であると考えられる。
- 開発、テスト、本番環境を分けて管理したい場合。
- ユーザーが自由に異なるブロックチェーンネットワークを選択できるようにしたい場合。
- プロジェクトがブロックチェーンのアップグレードやマイグレーションを計画している場合。
ただし、このような設計を採用する際には、異なるブロックチェーン間でのインターフェイスの互換性、セキュリティ対策、データ整合性の保持などの追加的な考慮が必要となる。設計の複雑さが増すため、プロジェクトの要件やリソースに応じて、このアプローチが最適かどうかを判断する必要がある。
DApps
Auction DAppも一見、ほぼ完全に非中央集権化されたアプリケーションに見えるが、実際に使うことを考えると、以下のように中央集権的なシステムに依存する分が出てくる。
- Wallet
- ブロックチェーン接続時にInfuraのようなゲートウェイが必要。
- 名前解決
- IPNS
- IPFSだけだとどうしてもユーザビリティが低いので、ユーザーフレンドリーな名前を使えるようにしたい。ただ、その場合、DNSLinkが必要となり、DNSに依存してしまう。
- FleekもIPFS上にコンテンツをデリバリした場合、自動でIPNSが設定されるっぽい。
- ENS
-
.eth
ドメインにアクセスする際にスマートコントラクトが必要なので、フルノードが必要になる。ただ、全てのユーザがフルノードを持つのは厳しいので、Infuraのようなゲートウェイが必要になってしまう。
-
- IPNS
ユーザビリティを優先すると、どのような手法を取っても、結局、ゲートウェイやDNSのような中央集権的なシステムに依存してしまう。現状、何か良い方法はないのだろうか。。?
ただ、ユーザビリティを考えると無理に全てを分散型にする必要もないのかもしれない。トレードオフもありそう。
どこかで線引きをするとしたら、ユーザビリティを優先してエンドユーザーがゲートウェイなどを使うのを許容するのはアリ?バックエンドとフロントエンドが分散システムであれば十分かも?
Discussion