Cấu Trúc Của Một Ứng Dụng Web3 (DApp)

Cấu trúc của các ứng dụng Web 3.0 (hay còn gọi là “DApps”) hoàn toàn khác so với các ứng dụng web 2.0.

Ví dụ như Medium – một trang blog đơn giản cho phép người dùng xuất bản content của riêng họ và tương tác với content từ những người khác.

Đầu tiên, phải có một nơi để lưu trữ dữ liệu cần thiết, chẳng hạn như dữ liệu người dùng, bài đăng, tag, bình luận, lượt thích, v.v.

Thứ hai, backend code (được viết bằng một trong các ngôn ngữ như Node.js, Java, hoặc Python) phải xác định được logic business của Medium. Ví dụ, điều gì sẽ xảy ra khi một user mới đăng ký, đăng 1 bài blog mới hoặc bình luận vào 1 bài blog của người khác?

Thứ ba, frontend code (thường được viết bằng JavaScript, HTML, và CSS) phải xác định được logic UI của Medium. Ví dụ, trang web sẽ trông như thế nào, và điều gì sẽ xảy ra khi có người dùng tương tác với mỗi element trên trang?

Tổng hợp tất cả những điều trên, khi bạn đăng 1 bài blog lên Medium, bạn tương tác với phần frontend của Medium, sau đó frontend sẽ request đến backend, và backend sẽ truy vấn đến database. Tất cả phần code này được lưu trữ trên các máy chủ tập trung và được gửi đến user thông qua trình duyệt internet.

Nhưng tất cả những điều này đang thay đổi.

Công nghệ Blockchain đã mở ra một hướng đi mới cho các ứng dụng Web 3.0. Trong bài viết này, chúng ta sẽ tập trung vào những điều tuyệt vời mà blockchain Ethereum mang lại.

Điều Gì Tạo Nên Sự Khác Biệt Cho Web3?

Không giống như các ứng dụng Web 2.0 như Medium, Web 3.0 không cần bên trung gian. Không có cơ sở dữ liệu tập trung nào lưu trữ trạng thái ứng dụng và không có máy chủ web tập trung nào chứa logic backend.
Thay vào đó, bạn có thể tận dụng blockchain để xây dựng ứng dụng trên một “máy trạng thái” (state machine) phi tập trung được duy trì bởi các nodes ẩn danh trên internet.
State machine là máy duy trì một số trạng thái chương trình nhất định và các trạng thái tương lai được phép trên máy đó. Blockchains là các state machine được khởi tạo với một số trạng thái ban đầu và có các quy tắc rất nghiêm ngặt (tức là sự đồng thuận) xác định cách trạng thái đó có thể chuyển đổi.

Không có thực thể nào kiểm soát máy trạng thái phi tập trung này – nó được duy trì bởi tất cả mọi người trong network.
Còn máy chủ backend thì sao? Thay vì kiểm soát backend của Medium, trong web3 bạn có thể viết smart contracts xác định logic của ứng dụng và triển khai chúng trên máy trạng thái phi tập trung. Điều này có nghĩa là những người muốn xây dựng ứng dụng blockchain sẽ triển khai code của họ trên máy trạng thái được chia sẻ chung này.

Về phần frontend, nó gần như không thay đổi gì, ngoại trừ một số vấn đề, chúng tôi sẽ đề cập sau.

Đây là cấu trúc của một ứng dụng web3:

Chúng Ta Sẽ Tìm Hiểu Kĩ Hơn Về Cấu Trúc Này…

1) Blockchain

Blockchain Ethereum thường được gọi bằng cái tên “máy tính thế giới”. Đó là bởi vì nó là một máy trạng thái xác định, có thể truy cập toàn cầu và được duy trì bởi một mạng lưới các nodes ngang hàng (không tập trung). Các thay đổi trạng thái trên máy trạng thái này được điều chỉnh bởi các quy tắc đồng thuận mà những người ngang hàng nhau (peers) trong network tuân theo.

Vì vậy, nói cách khác, nó được thiết kến để trở thành một cỗ máy trạng thái mà bất kỳ ai trên thế giới đều có thể truy cập và ghi vào. Do đó, máy này không thuộc sở hữu của bất kỳ thực thể nào – mà là của tất cả mọi người trong mạng lưới.
Thêm một điều nữa: dữ liệu chỉ có thể được ghi vào blockchain Ethereum – bạn không bao giờ có thể cập nhật dữ liệu hiện có.

2) Smart contracts

Một smart contract là một chương trình chạy trên blockchain Ethereum và xác định logic đằng sau những thay đổi của trạng thái xảy ra trên blockchain. Smart contracts được viết bằng các ngôn ngữ cấp cao như Solidity hoặc Vyper.

VÌ phần code của smart contract code được lưu trữ trên Ethereum blockchain, nên bất kỳ ai cũng có thể kiểm tra logic ứng dụng của tất cả các smart contracts trên mạng lưới.

3) Ethereum Virtual Machine (EVM)

Tiếp theo, bạn có Máy Ethereum Virtual, thực hiện logic được xác định trong các smart contracts và xử lý các thay đổi trạng thái xảy ra trên máy trạng thái có thể truy cập toàn cầu này.
EVM không hiểu các ngôn ngữ cấp cao như Solidity và Vyper – những ngôn ngữ được sử dụng để viết smart contracts. Thay vào đó, bạn phải biên dịch ngôn ngữ cấp cao thành bytecode, sau đó EVM mới có thể thực hiện phần việc tiếp theo.

4) Front-end

Cuối cùng, chúng ta có giao diện người dùng (front end). Như chúng tôi đã đề cập phía trên, front end xác định logic UI, nhưng front end cũng giao tiếp với logic ứng dụng được xác định trong smart contracts.
Việc giao tiếp giữa front end và smart contracts phức tạp hơn một chút so với biểu đồ ở trên. Chúng ta hãy cùng tìm hiểu cách chúng giao tiếp trên Ethereum:

Làm thế nào để code front end giao tiếp với smart contracts trên Ethereum?

Chúng tôi muốn font end của mình giao tiếp với smart contracts để chúng có thể chạy các functions, nhưng hãy nhớ rằng Ethereum là một mạng phi tập trung. Mỗi node trong mạng Ethereum đều giữ một bản sao của tất cả các trạng thái trên máy trạng thái Ethereum, bao gồm code và dữ liệu được liên kết với mọi smart contract.

Khi chúng ta muốn tương tác với dữ liệu và code trên blockchain, chúng ta cần tương tác với một trong những nodes này. Bởi vì bất kỳ node nào cũng có thể phát request thực hiện giao dịch trên EVM. Sau đó, một miner sẽ thực hiện giao dịch và truyền sự thay đổi trạng thái kết quả đi ra phần còn lại của mạng lưới.
Có hai cách để phát một giao dịch mới:

  1. Thiết lập node của riêng bạn chạy phần mềm blockchain Ethereum
  2. Sử dụng các nodes được cung cấp bởi dịch vụ của các bên thứ ba

Nếu bạn sử dụng dịch vụ của bên thứ ba, bạn không phải đối mặt với tất cả các vấn đề đau đầu khi tự chạy một node từ đầu tới cuối. Trong khi, việc thiết lập một node Ethereum mới trên máy chủ của riêng bạn có thể mất nhiều ngày. (Có rất nhiều dữ liệu để đồng bộ hóa – Nó thậm chí có thể chiếm nhiều băng thông và bộ nhớ hơn so với một máy tính xách tay thông thường có thể xử lý.)
Hơn nữa, chi phí lưu trữ toàn bộ blockchain Ethereum sẽ tăng lên khi DApp của bạn mở rộng và bạn cần thêm nhiều nodes hơn để mở rộng cơ sở hạ tầng của mình. Bạn sẽ cần đến nhiều kỹ sư DevOps để duy trì cơ sở hạ tầng, đảm bảo thời gian hoạt động đáng tin cậy và thời gian phản hồi nhanh chóng.
Các nodes mà bạn kết nối khi cần tương tác với blockchain (cho dù bạn tự thiết lập chúng hay sử dụng các nodes hiện có từ các dịch vụ của bên thứ ba) thường được gọi là “nhà cung cấp”.

Mọi ứng dụng khách Ethereum (tức là nhà cung cấp) đều triển khai JSON-RPC specification. Điều này đảm bảo rằng sẽ có một bộ phương pháp thống nhất khi các ứng dụng front end muốn tương tác với blockchain. Nếu bạn cần phần sơ khai về JSON-RPC, thì đó là giao thức gọi procedure từ xa (RPC) không trạng thái, xác định một số cấu trúc dữ liệu và quy tắc xử lý chúng. Đây là phương thức truyền tải bất khả tri, vì vậy, các khái niệm có thể được sử dụng trong cùng một quy trình, qua ổ cắm, qua HTTP hoặc trong nhiều môi trường truyền thông báo khác nhau. Nó sử dụng JSON (RFC 4627) như một data format.

Khi bạn kết nối với blockchain thông qua một nhà cung cấp, bạn có thể đọc trạng thái được lưu trữ trên blockchain. Nhưng nếu bạn muốn viết cho phần trạng thái, vẫn còn một việc nữa bạn cần làm trước khi có thể gửi giao dịch tới blockchain – “ký” giao dịch bằng key cá nhân của bạn.

Ví dụ, hãy tưởng tượng chúng ta có DApp cho phép người dùng đọc hoặc xuất bản các bài đăng trên blog lên blockchain. Bạn có thể có một botton trên frontend cho phép bất kỳ ai truy vấn các bài đăng trên blog được viết bởi một người dùng cụ thể. (Hãy nhớ rằng việc đọc từ chuỗi khối không yêu cầu người dùng phải ký một giao dịch.)

Tuy nhiên, khi người dùng muốn publish một bài đăng mới lên chain, DApp của chúng ta sẽ yêu cầu người dùng “ký” giao dịch bằng key cá nhân của họ – sau đó DApp mới chuyển giao giao dịch sang blockchain.

Việc “ký kết” các giao dịch này là nơi mà Metamask thường xuất hiện.

Metamask là một công cụ giúp các ứng dụng dễ dàng xử lý việc quản lý key và ký kết giao dịch. Metamask lưu trữ các keys riêng của user trong trình duyệt và bất cứ khi nào font end cần người dùng ký giao dịch, nó sẽ gọi đến Metamask.

Metamask cũng cung cấp kết nối với blockchain (với tư cách là “nhà cung cấp”) vì nó đã có kết nối với các nodes do Infura cung cấp để ký giao dịch. Vì vậy, Metamask vừa là nhà cung cấp vừa là người ký.

Lưu trữ trên Blockchain

Tất nhiên là cấu trúc này sẽ có ý nghĩa nếu bạn xây dựng một ứng dụng nơi tất cả các smart contrascts và dữ liệu hoàn toàn ở trên blockchain Ethereum. Nhưng bất kỳ ai đã xây dựng ứng dụng trên Ethereum đều biết rằng việc lưu trữ mọi thứ trên blockchain rất tốn kém.
Hãy nhớ rằng, với Ethereum, người dùng trả tiền mỗi khi họ thêm dữ liệu mới vào blockchain. Đó là do việc thêm một trạng thái vào máy trạng thái phi tập trung làm tăng chi phí cho các nodes đang duy trì máy trạng thái đó.
Yêu cầu người dùng trả thêm tiền để sử dụng DApp của bạn mỗi khi giao dịch của họ yêu cầu thêm trạng thái mới không phải là ý tưởng hay. Một cách để giải quyết việc này là sử dụng giải pháp lưu trữ bên ngoài chuỗi phi tập trung.
IPFS là một hệ thống tệp phân tán để lưu trữ và truy cập dữ liệu. Vì vậy, thay vì lưu trữ dữ liệu trong cơ sở dữ liệu tập trung, hệ thống IPFS phân phối và lưu trữ dữ liệu trong mạng ngang hàng. Điều này giúp bạn dễ dàng lấy ra khi cần.
IPFS cũng có một lớp incentive được gọi là “Filecoin”. Lớp này khuyến khích các nodes trên khắp thế giới lưu trữ và truy xuất dữ liệu này.
Swarm tương tự ở chỗ là mạng lưu trữ phi tập trung, nhưng có một điểm khác biệt đáng chú ý. Trong khi Filecoin là một hệ thống riêng biệt, hệ thống incentive của Swarm được tích hợp sẵn và thực hiện thông qua các smart contracts trên blockchain Ethereum để lưu trữ và truy xuất dữ liệu.
Với IPFS hoặc Swarm, cấu trúc ứng dụng của chúng ta sẽ có dạng như sau:

Những độc giả tinh ý cũng có thể nhận thấy trong sơ đồ bên dưới rằng phần front end code không được lưu trữ trên blockchain. Chúng ta có thể lưu trữ code này trên AWS, như chúng ta thường làm trong Web 2.0, nhưng điều đó tạo ra một điểm giới hạn tập trung cho DApp của bạn. Điều gì sẽ xảy ra nếu AWS gặp sự cố? Điều gì sẽ xảy ra nếu nó kiểm duyệt ứng dụng của bạn?

Đó là lý do tại sao, nếu bạn muốn xây dựng một ứng dụng phi tập trung thực sự, bạn có thể chọn host cho front end của mình trên một giải pháp lưu trữ phi tập trung, như IPFS hoặc Swarm.

Cấu trúc ứng dụng của bạn sẽ như sau:

Truy Vấn Blockchain

Đến giờ, chúng ta đã nói về cách ghi vào blockchain bằng việc ký các giao dịch và sau đó gửi chúng đến blockchain. Nhưng còn việc đọc dữ liệu từ các smart contracts trên blockchain thì sao? Có hai cách chính để thực hiện điều này:

1) Sự Kiện Smart Contract

Bạn có thể sử dụng thư viện Web3.js để truy vấn và tìm hiểu về các sự smart contract events. Bạn có thể biết các sự kiện đặc biệt và xác định callback mỗi khi sự kiện được kích hoạt. Ví dụ: nếu bạn có một smart contract gửi một luồng thanh toán liên tục từ người A đến người B mỗi block, thì bạn có thể tạo ra một sự kiện mỗi khi một khoản thanh toán mới được thực hiện cho người B. Phần front end code của bạn có thể biết các sự kiện đang được kích hoạt.

2) The Graph

Cách tiếp cận trên có thể thực hiện được, nhưng nó có một số hạn chế. Điều gì sẽ xảy ra nếu bạn triển khai một smart contract và sau đó nhận ra rằng bạn cần một sự kiện được phát ra mà ban đầu bạn không có? Khi đó vạn phải triển khai lại smart contract mới với sự kiện và dữ liệu đó. Hơn nữa, việc sử dụng các lệnh callback để xử lý các logic front end khác nhau sẽ rất phức tạp.
Đây là lúc “The Graph” xuất hiện.

The Graph là một giải pháp index off-chain giúp truy vấn dữ liệu trên blockchain Ethereum dễ dàng hơn. The Graphcho phép bạn xác định các smart contract nào để index, các sự kiện và function call nào để lắng nghe và cách chuyển các sự kiện sắp đến thành các thực thể mà logic front end của bạn (hoặc bất kỳ thứ gì đang sử dụng API) có thể sử dụng. Nó sử dụng GraphQL làm ngôn ngữ truy vấn – thứ ngôn ngữ mà nhiều kỹ sư front end yêu thích vì tính biểu đạt của nó so với các API REST truyền thống.

Bằng cách lập index dữ liệu blockchain, The Graph cho phép chúng ta truy vấn dữ liệu on-chain trong logic ứng dụng của chúng ta với độ trễ thấp.
Bây giờ, cấu trúc DApp của chúng ta sẽ như sau:

Chúng gần như đã xong, nhưng vẫn còn một đề mục chính là mở rộng quy mô (scaling Dapp).

Scale DApp

Có thể bạn đã nghe qua, rằng Ethereum không mở rộng — hoặc ít nhất là chưa từng.

Ethereum average gas price
Giá gas trung bình của Ethereum
Average transaction fee
Phí giao dịch trung bình
Average block size
Kích thước block trung bình

Việc xây dựng DApp trên Ethereum với phí gas cao và các block full dẫn đến trải nghiệm người dùng rất tệ. Rất may, vẫn có giải pháp cho vấn đề này.

Một giải pháp scaling phổ biến là Polygon (giải pháp scaling L2). Thay vì thực hiện các giao dịch trên blockchain chính, Polygon có các “sidechains” xử lý và thực hiện các giao dịch. Một sidechain là một blockchain thứ cấp giao tiếp với chain chính. Sidechain sẽ thường xuyên gửi “rollup” các block gần đây của nó trở lại chain chính.

Các ví dụ khác về giải pháp L2 là Optimistic Rollups và zkRollups. Tương tự Polygon, chúng ta thực hiện hàng loạt các giao dịch off-chain bằng cách sử dụng smart contract “rollup” và sau đó định kỳ cam kết các giao dịch này với chain chính.

Các giải pháp L2 thực hiện giao dịch (tức là phần chậm) off-chain, chỉ với dữ liệu giao dịch được lưu trữ trên chain. Điều này cho phép chúng ta mở rộng quy mô blockchain vì chúng ta không phải thực hiện mọi giao dịch trên chain. Các giao dịch sẽ trở nên nhanh hơn và rẻ hơn – và chúng vẫn có thể giao tiếp với blockchain Ethereum chính khi cần.

Kết Luận

Hầu hết mọi người dành hàng tháng để tìm hiểu cách hoạt động của tooling chain, vì vậy nếu bạn là một nhà phát triển DApp, tôi hy vọng bài viết này sẽ giúp bạn tiết kiệm thời gian.

Nếu bạn quan tâm đến việc xây dựng các ứng dụng Web 3.0 hoặc bất kỳ thứ gì liên quan đến Web3, thì hãy đón đọc những blog sắp tới của chúng tôi với tag #web3, bạn có thể tìm thấy các tips và hướng dẫn hữu ích giúp bạn xây dựng và triển khai Dapp cho riêng mình.

Nguồn tham khảo: Preethi Kasosystemdy