Dapp #
- 去中心化应用。
- 运行在区块链或分布式网络上,而非传统服务器。
- 去中心化技术栈 + 智能合约编程 + 前端与区块链的交互方式。
Dapp 与传统应用的比较:
对传统应用来说,相当于去银行办业务,到前台(前端)填写表单,由柜员(后端服务器)处理我们的请求,这个过程是我们与柜员直接沟通,然后完成操作。但在 Dapp 中主要是通过代理人办理区块链业务,到前台(前端网页)填写表单,然后私人代理(钱包,如 MetaMask)会验证我们的身份,帮我们签字。邮递员(RPC 节点)负责传递信息,最后由公证处(区块链)来进行最终的执行和记录。
Dapp 架构 #
-
前端
- Dapp 与用户交互的界面(由 HTML、CSS、Javascript、React、Rust 构建)。
- Dapp 前端不直接连接区块链网络,通过「钱包注入的 provider」或「第三方 RPC 节点」与区块链交互。
- 需要区块链钱包(如 MetaMask)进行身份验证和签署交易,确保隐私和安全。
- 通过 RPC 节点对智能合约发起只读调用,获取合约状态、事件日志等链上数据(通俗来说,「只读」可以被理解为想查看账户余额,前端通过 RPC 节点,然后直接读取区块链数据,最后现实结果)。
- 对需要修改状态的操作,由前端构造对智能合约的交易调用,交由钱包完成签名后,再通过 RPC 节点广播到区块链网络并最终上链执行(这里可以简单理解为想转账,然后前端构造交易,钱包随之弹出确认窗口,RPC 节点再广播到区块链,矿工进行打包执行,状态发生改变)。
-
智能合约
- Dapp 的核心,定义应用的业务逻辑。
- 部署在区块链上。
- 由 Solidity 编写,通过 EVM 执行。
-
数据检索器
- 智能合约以
Event的形式释放日志事件,数据检索器检索这些数据并写入 PostgreSOL 等传统数据库中(这部分还是感到困惑)。
- 智能合约以
-
区块链和去中心化存储
- 区块链存储智能合约的状态数据及交易记录。
- 去中心化存储包括 IPFS 或 Arweave,存储大规模非结构化数据,如图片、视频、文档等。
- 去中心化存储使得所有数据在多个节点上备份,确保数据持久性和去中心化特性。
Dapp 开发流程 #
(1)需求分析
- 功能需求:转账?查询余额?创建投票?
- 区块链平台选择:在哪个平台构建 Dapp?以太坊?Solana?Polygon?
- 用户体验设计:Dapp 界面设计和交互流程。
(2)智能合约开发
- 编写智能合约:使用 Solidity 或其他相关语言编写合约,确保满足(1)需求分析。
- 编写测试用例:为智能合约编写单元测试,确保合约逻辑正确。
- 审计和优化:对合约进行安全审计,确保合约安全性,避免常见漏洞——重入攻击、整数溢出等。
(3)检索器开发
- 确定功能需要的数据内容:前端使用的数据大部分来自检索器。
- 编写检索器程序:主流检索器框架(如 ponder 和 subgraph)都用了 TypeScript 语言作为检索器的程序编写语言。
- 部署和运维:编写程序完成后用 Docker 部署到云服务器中。
(4)前端开发
- 选择前端框架:可用现代前端框架如 React、Vue 来构建 UI,前端会通过 JavaScript 与智能合约进行交互。
- 连接钱包:通过 MetaMask 等 Web3 钱包,用户可以连接到 Dapp,并授权其与智能合约交互。
- 显示区块链数据:前端需要从区块链和检索器内获取数据——如数据余额、交易记录,通过用户界面展示。
- 处理交易签名与确认:用户发起交易时,前端与钱包交互,获取用户签名并将交易发送到区块链。
(5)与区块链交互
- 读取数据:前端通过智能合约的公开函数读取区块链上的状态数据——余额、合约信息。
- 发送交易:当用户发起交易时,前端需要通过钱包签署交易并发送到区块链,执行合约中的功能(如转账)。
(6)部署与上线
- 部署智能合约:使用 Hardhat 或 Foundry 等工具将智能合约部署到测试网(如 Sepolia)或主网。
- 前端部署:将前端应用部署到去中心化平台(如 IPFS)或传统的 Web 服务(如 Vercel)。
- 发布和维护:将 Dapp 上线,收集用户反馈并定期更新合约和前端。
RPC 简述 #
RPC(Remote Procedure Call),意为「远程过程调用」,是连接前端应用与区块链网络的关键桥梁。RPC 是理解 Dapp(去中心应用)和传统应用之间差别很重要的一个概念,我认为主要体现在两者的交互方式上。
Dapp 和传统应用都有前端。传统应用没有 RPC,数据和资产属于平台,前端通过调用后端 API 来获取数据和执行操作,「转账」时告诉银行服务器个人信息和密码,银行服务器验证过后完成操作;Dapp 中,数据和资产都属于私人,前端通过个人钱包和 RPC 与区块链进行交互,「转账」时需要个人的钱包签名,然后再由 RPC 广播到全网,全网的验证者验证信息无误后执行操作。
RPC 功能:
- 读取链上数据。包括查询账户余额、交易历史,读取智能合约的状态变量,获取区块信息、Gas 价格等。
- 发送交易。将用户签名的交易广播到区块网络,查询交易状态和确认数,估算交易所需的 Gas 费用。
- 事件监听。监听智能合约事件(Events),实时获取链上状态变化。
- 网络管理。切换不同的区块链网络(主网、测试网)等。
详见 RPC 节点服务详解。
Solidity 智能合约编程 #
Solidity 是面向合约的高级编程语言,专门用于在以太坊虚拟机(EVM)上编写智能合约。
-
每个 Solidity 文件都必须以版本声明开始:
pragma solidity ^0.8.0; -
//是 solidity 文件中的单行注释符号。 -
pragma关键字用于声明 solidity 源代码所需的编译器版本,确保合约在兼容的编译器环境中正确编译。 -
contract关键字用于定义一个智能合约,其语法格式为contract 合约名 { ... }。 -
函数是 Solidity 智能合约中执行具体逻辑操作的核心组成部分。
- 通过函数,可以实现对状态变量的读取、修改,或执行特定业务逻辑。
-
一个智能合约的基本结构通常由三部分组成:状态变量、构造函数、普通函数。
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; contract MyContract { // 状态变量 uint256 public myNumber; // 构造函数 constructor() { myNumber = 100; } // 函数 function setNumber(uint256 _number) public { myNumber = _number; } } -
Solidity 中函数的标准声明格式如下:
function <函数名>(<参数列表>) <可见性> <状态可变性> <修饰符列表> <虚拟/重写关键字> returns (<返回值列表>) { // 函数体 }
- 状态变量是指在合约中定义的、其值永久存储在区块链上的变量。它们用于记录合约的持久化数据,构成合约的整体状态。当合约被部署后,这些变量将被写入区块链,并在合约的整个生命周期中保持可访问性和可追踪性。