← COMP5565 全部讲次
L04a · 第 4 周

L04a DApps 开发环境与生命周期:把一家网店拆成五块问归谁管

去中心化不是一个开关,是五个各自独立的选择题。

一句话版

去中心化是五道各自独立的选择题,绝大多数 DApp 只在其中一两道上真的选了”去”。

一个类比:把一家网店拆成五块,逐块问归谁管

一家普通网店有五块东西:算订单的后台、顾客看的网页、存商品图的硬盘、客服聊天、还有那个域名。它们全在一家公司手里,所以这家公司随时能改价、能删商品、能把某个顾客拉黑。

把它搬成 DApp,要做的是逐块问一遍”这块归谁管”。后台换成智能合约,规则写死在链上谁也改不了;网页还是 HTML 和 JavaScript,可以照样托管在一台普通服务器上;商品图太大不适合上链,扔进 IPFS,链上只留一个哈希;客服聊天走 Waku 这类点对点协议;域名换成 ENS。五块里你换掉几块,这个应用就有几分去中心化。

类比在哪里失效:网店老板改价格只要点一下后台,合约改规则做不到——部署完连作者都动不了,只能另起一个合约再想办法把用户引过去。另一处更要命:网店的服务器挂了顾客访问不了,合约所在的链不会挂,但它也不会自己干活。课件那句”所有合约执行最终都源于一笔外部账户发起的交易”意味着合约没有心跳,众筹到期该退款这件事,得有人花钱发一笔交易去戳它一下。

概念卡

1. 分布式 ≠ 去中心化(Distributed vs Decentralized)

人话定义:分布式分散的是资源——机器摆在多少个地方;去中心化分散的是权力——谁说了算(p.4)。

例子:两者追求的性质完全不同,这组对照课件列得很整齐:

Distributed ComputingDecentralized Computing
分散什么计算与存储资源权力(authority)
追求Reliability、Efficiency、ScalabilityIntegrity、Transparency、Availability

一家公司的云服务器横跨三大洲,是彻底的分布式,却一点不去中心化——拔电源的开关仍然只有一个。

常见误解

以为部署得够分散就自动去中心化了 → 这两件事正交。课件在介绍 DApp 特性时特意加了一行小字 “but not always”(p.6),又在对照表底下补一句:不是所有号称 DApp 的东西都完全去中心化,有些仍保留一定程度的控制权与所有权(p.7)。判断一个 DApp 有多”去中心化”,要看五个维度各自的答案,不看它自称什么。

2. 五个维度与链下存储(IPFS / Swarm)

人话定义:可去中心化的五块是后端逻辑、前端、数据存储、消息通信、名字解析(p.6)。其中存储这一块几乎所有 DApp 都妥协了。

例子:区块链存大文件成本高得离谱,所以通行做法是文件放链下,链上只存哈希,靠这个哈希把链上和链下钉在一起(p.9)。链下可以是中心化的云数据库,也可以是 IPFS 或 Swarm 这类 P2P 网络。IPFS 的代价写得很直白:只能存静态内容,不支持动态,应用因此更依赖第三方 API 和用户钱包与链的交互(p.10)。

常见误解

以为”存了哈希”等于”数据永远在” → 链上那个哈希只证明文件没被改过,不保证还有人存着它。IPFS 节点会回收长期无人访问的内容,要它一直在得有人做 pinning(补充)。前端也有同样的问题:课件在讲前端时直接反问了一句”谁保有控制权”——网页托管在一台普通服务器上,这个应用就已经不完全去中心化了(p.8)。

3. 三个环境与那条 JSON-RPC(Toolchain)

人话定义:写 DApp 要同时开三摊:开发环境编译合约、前端环境跑界面、以太坊网络执行交易。三者之间说的是同一种话——JSON-RPC。

例子:课件那张架构图把三摊圈成三个虚线框,连接它们的三条粗箭头上写的全是 JSON-RPC(p.20):

三摊之间的连线:左上开发环境里 Remix 和 VS Code 加 Hardhat 编写编译部署 Solidity,配 OpenZeppelin 合约库和 Ganache 本地链;左下前端环境里浏览器装 MetaMask,代码读 window.ethereum 请求授权,用 web3.js 或 ethers.js 调用;右侧以太坊网络由一对对执行层加共识层客户端组成,示例是 Geth 配 Lighthouse,下方是 Alchemy 和 Infura 托管节点 API 以及测试网 Sepolia 和 Holešky;左边两摊各自用一条标着 JSON-RPC 的双向箭头连到以太坊网络,开发环境另有一条向下的箭头把合约地址和 ABI 交给前端

工具按角色分七类(p.21):IDE(Remix、VS Code)、开发框架(Hardhat)、执行层与共识层客户端(Geth + Lighthouse、Nimbus、Prysm)、测试链(Ganache)、Web3 库(web3.js、ethers.js)、Web3 浏览器(Brave、Mist)、钱包(MetaMask)。Alchemy 和 Infura 同时出现在客户端和 Web3 库两行,因为它们卖的就是”用 API 代替你自己跑节点”。

常见误解

以为连钱包要调 MetaMask 自己的 SDK → 标准做法是读 window.ethereum 这个被扩展注入页面的对象,先用 isMetaMask 判断装没装,再调 eth_requestAccounts 弹窗请求授权(p.29)。这套接口是标准化的,换 Coinbase Wallet 代码不用改。测试网也要记准:课件列的五个里现在只剩 Sepolia 该用,Ropsten、Goerli、Rinkeby 早已关停,Holešky 也在 2025 年 9 月退役,测试币由 faucet 免费发、值零元(p.22、p.24)。

4. 五阶段生命周期与那条回头路(Lifecycle)

人话定义:Design → Implementation on testnet → Testing & Auditing → Deployment → Upgrades(p.30–34)。最后一个阶段的存在,全是因为合约改不了。

例子:五个阶段各自要交付什么:

DApp 开发生命周期五阶段横向排开:Design 阶段做概念定义、用户体验草图和架构决策;Implementation 阶段搭开发环境、写编译合约、可选地先发到测试网;Testing and Auditing 阶段做单元测试、集成测试和第三方安全审计;Deployment 阶段把合约迁到主网、前端切主网并接上监控告警;Upgrades 阶段用代理模式留升级口、建治理机制、持续监控安全与网络升级兼容性;最后一个阶段有一条虚线箭头回到 Implementation,标注说明合约代码不可直接修改所以升级要另起一层

Testing 那一格里的三项不能互相替代:单元测试管单个函数、集成测试管前后端连通、安全审计要请外部专家(p.32)。Deployment 那一格除了迁主网,还特意要求接监控,对异常交易或大额交易告警(p.33)。

常见误解

以为”上线了就完了”,Upgrades 只是可选的售后 → 课件把它列为独立阶段,而且三项内容里第一项就是代理模式(p.34)。合约代码一旦部署无法直接改写,想修 bug 只能另起一层间接跳转,这件事必须在设计阶段就决定,事后加不上。第三项”持续监控”也不只是看有没有被攻击,还包括确认自己的合约跟得上以太坊自身的网络升级。

把它们串起来

这半份课件的主线是一句反复出现的话:去中心化是有代价的,而代价决定了你会在哪几块上妥协。

开头先把”分布式”和”去中心化”拆开,是为了让后面那五个维度站得住——如果这两个词是一回事,那么”部分去中心化”这种说法就没有意义了。接着五个维度逐块过一遍,每一块都给出了妥协的理由:前端托管在服务器上是为了方便,存储放 IPFS 是因为上链太贵,消息走 Waku 是因为合约根本不能主动发消息。众筹那个例子是全篇的锚:传统方案里发起人和众筹平台都必须被信任,换成合约之后规则自动执行,谁也赖不掉。

后半段的工具链和生命周期其实回答同一个问题——既然合约改不了,流程要怎么设计才不会翻车。答案是把出错的成本尽可能提前:先在 Ganache 本地跑,再上测试网花假钱验证,再请人审计,最后才上主网。三道关都在主网之前,因为主网之后就没有回头路了,只剩代理模式这一条又贵又绕的补救路。

课件里的坑

  • [编辑残留] p.27 讲开发框架时写着 “Both integrate with Visual Studio and other IDEs”,但上面只列了 Hardhat 一个。原本这里是 Truffle 和 Hardhat 两项,Truffle 停止维护后删掉了一行,“Both” 没跟着改(p.27)
  • [已退役但仍在列] p.21 的工具表和 p.31 的实施阶段都还把 Truffle 列为可选框架。Consensys 在 2023 年 9 月宣布 Truffle 和 Ganache 一并 sunset,当年底停止维护——课件 p.25、p.26 整两页讲的 Ganache 同在这批里。框架换 Hardhat 或 Foundry,本地链换 Hardhat Network 或 Anvil(补充)
  • [测试网状态] p.22 的测试网清单里,Ropsten 标了 EOL 2022、Goerli 标了 deprecated 2022,但 Rinkeby 没标——它同样已经关停。清单上的 Holešky 也在 2025 年 9 月退役,验证者测试转到 Hoodi;现在写合约做 Lab 只剩 Sepolia(p.22)
  • [已废弃的协议] p.12 的 Whisper 课件自己标了 deprecated,继任者是 Waku。这一条课件写对了,但容易被当成两个并列选项记(p.12)

课后 10 分钟:考点复习

这 10 分钟怎么用:合上页面先默写三样——分布式与去中心化各自追求的三个性质、五个可去中心化的维度、生命周期五阶段的名字和顺序;再做下面的变式题;最后回查两个最容易混的点——Alchemy 和 Infura 为什么在工具表里出现两次、哪些测试网还活着。

必背

  1. 分布式计算分散的是计算与存储资源,追求 reliability / efficiency / scalability;去中心化计算分散的是权力(authority),追求 integrity / transparency / availability。
  2. 一个应用可去中心化的五个维度:后端逻辑、前端、数据存储、消息通信、名字解析;课件明确标注 DApp 的透明、韧性、抗审查「but not always」,多数 DApp 只做到部分维度。
  3. 区块链不适合存大文件,通行做法是文件放 IPFS 或 Swarm 等链下存储,链上只存其哈希作为链上与链下的锚点;IPFS 只能承载静态内容。
  4. 开发工具链分三个环境:开发环境(Remix / VS Code + Hardhat 写 Solidity)、前端环境(浏览器 + 钱包 + web3.js / ethers.js)、以太坊网络(执行层 + 共识层客户端,如 Geth + Lighthouse,或用 Alchemy / Infura 的 API 代替自建节点);三者之间统一走 JSON-RPC。
  5. 测试网 Sepolia 与 Holešky 在课件里都标权益证明,Ropsten、Goerli、Rinkeby 已退役;Holešky 已于 2025 年 9 月退役、验证者测试转用 Hoodi,写合约一律用 Sepolia;测试币由 faucet 免费发放、无真实价值;Ganache 提供本地链与预置账户,私钥可导入 MetaMask。
  6. DApp 开发生命周期五阶段:Design → Implementation on testnet → Testing & Auditing → Deployment → Upgrades;测试阶段含单元测试、集成测试和第三方安全审计,部署后要接监控对异常或大额交易告警。
  7. 合约代码部署后无法直接修改,升级只能靠代理模式(proxy pattern)另起一层间接;这是生命周期最后一个阶段单独存在的原因。

完整例题

题面(课件 p.25 的 Ganache 面板):面板上 GAS PRICE 显示 20000000000、GAS LIMIT 显示 6721975,第一个账户初始 100 ETH、现在余额 99.46 ETH、TX COUNT 为 32。问:(a) 这个 gas price 是多少 gwei?(b) 平均每笔交易烧了多少 gas?(c) 那个 GAS LIMIT 是单笔交易的上限吗?

  1. (a) 单位换算的基准是 1 gwei = 10⁹ wei。代入:20000000000 ÷ 10⁹ = 20 gwei。这是以太坊上最常见的一档测试配置。
  2. (b) 先算花掉的钱:100 − 99.46 = 0.54 ETH。把这 0.54 整个当成 gas 费,前提是这些交易没有把 ETH 净转出去——账户之间互转总额不变,但要是钱进了某个部署出来的合约余额里就不能这么算。考试按前一种算。
  3. 换成 wei:0.54 × 10¹⁸ = 5.4 × 10¹⁷ wei。
  4. 除以交易笔数:5.4 × 10¹⁷ ÷ 32 = 1.6875 × 10¹⁶ wei 每笔 = 0.016875 ETH 每笔。
  5. 再除以单位 gas 的价格:1.6875 × 10¹⁶ ÷ (2 × 10¹⁰) = 843750 gas 每笔。余额只给到两位小数,所以这个数真正可信的只有两位有效数字,答「84 万量级」就够。
  6. 这个数值得多看两眼:普通的 ETH 转账固定消耗 21000 gas,843750 是它的 40 倍。说明这 32 笔里有大量的合约部署和合约调用,不是简单转账——这恰好符合”开发时反复部署调试”的场景。
  7. (c) 不是。6721975 是区块的 gas 上限,一个区块里所有交易消耗之和不能超过它。单笔交易的上限由发送方自己在交易里设 gasLimit 字段,两者是不同层级的东西。把它错当成单笔上限,会得出”每笔最多花 0.134 ETH”这种没有依据的结论。

变式题(先自己做)

(1) 同样在 20 gwei 下,一笔标准的 ETH 转账(21000 gas)要花多少 ETH?(2) 如果这个开发者把 gas price 调到 1 gwei,那 0.54 ETH 够他跑多少 gas?

提示

两问都只用一个公式:手续费 = gas 用量 × gas 价格。第一问已知右边两项求左边,第二问已知左边和价格求用量。注意全程用 wei 做中间单位,最后再换回 ETH。

参考答案与自检(非官方评分标准)

自检要点:① 中间计算一律换成 wei,直接拿 ETH 和 gwei 相乘是主要失分点;② 写完回代验一次量级;③ 第二问答出来的是 gas 数量,不带 ETH 单位。

(1) 21000 gas × 20 gwei = 21000 × 20 × 10⁹ wei = 4.2 × 10¹⁴ wei = 0.00042 ETH。对照上面例题算出的每笔平均 0.016875 ETH,相差约 40 倍(精确是 40.2),与”843750 是 21000 的 40 倍”互相印证 ✓。

(2) 0.54 ETH = 5.4 × 10¹⁷ wei,除以 1 gwei = 10⁹ wei:5.4 × 10¹⁷ ÷ 10⁹ = 5.4 × 10⁸ gas,也就是 5.4 亿 gas。按每笔 843750 gas 算能跑约 640 笔,正好是 20 gwei 下 32 笔的 20 倍 ✓ 与价格降到二十分之一相符。

闪卡自测

1. 一家跨三大洲部署的云服务,是分布式还是去中心化?

是彻底的分布式,但完全不去中心化。分布式分散的是计算与存储资源,去中心化分散的是权力。云服务的机器遍布全球,但决定权仍然只在一家公司手里(p.4)。

2. 一个应用可以去中心化的五个维度是哪五个?

后端逻辑(application logic)、前端、数据存储、消息通信、名字解析(p.6)。课件特意强调 DApp 带来的透明、韧性、抗审查 “but not always”,绝大多数 DApp 只在其中一两个维度上真的做到了。

3. 为什么几乎所有 DApp 都把大文件放链下?链上留的是什么?

区块链不适合存大量数据,例如文档和多媒体。通行做法是文件放链下存储(中心化的云数据库或去中心化的 IPFS、Swarm),链上只存这份数据的哈希,用它把链上与链下钉在一起(p.9)。

4. IPFS 最大的限制是什么?它给应用带来什么连带后果?

只支持静态内容,没有动态内容。后果是应用得更多依赖第三方 API 和用户钱包与区块链的交互来补上动态的部分(p.10)。

5. 课件在介绍前端时反问了一句什么?为什么这一问很关键?

“Who keeps control?”——前端可以托管在一台普通服务器上,一旦这样做,这个应用就不再是完全去中心化的了(p.8)。这一问是五个维度这套框架的起点:去中心化不是有或没有,是逐块回答的。

6. 三个环境之间用什么协议通信?

JSON-RPC。架构图上连接开发环境、前端环境和以太坊网络的三条箭头全部标着它(p.20)。web3.js 和 ethers.js 做的事情就是把 JSON-RPC 封装成好用的编程接口(p.21)。

7. Alchemy 和 Infura 为什么在工具表里出现了两次?

它们既算”执行层与共识层客户端”,也算 Web3 库。因为它们提供的是托管节点的 API 服务——你不用自己跑 Geth,直接调它们的接口就能读写链(p.21)。代价是又引入了一个需要信任的中心。

8. 目前还能用的以太坊测试网有哪些?测试币怎么来?

课件 p.22 列的是 Sepolia 和 Holešky,都是权益证明,Ropsten、Goerli、Rinkeby 已经退役——按这份清单答题。按现在的实际情况只剩 Sepolia:Holešky 在 2025 年 9 月也退役了,验证者测试转到 Hoodi。测试网有自己的货币,与真 ETH 完全无关、不值钱,由 faucet(水龙头)网站免费发放(p.22、p.24)。

9. Ganache 和测试网的分工是什么?

Ganache 是跑在本地的虚拟链,秒出块、零等待,还预置一批带假币的账户,私钥可以直接导入 MetaMask(p.25、p.26)。测试网是公开的真网络,有真实的出块延迟和其他人的交易。开发时先用 Ganache 快速迭代,快完成了再上测试网验证真实条件。Ganache 这个工具已随 Truffle 退役,现在这个位置由 Hardhat Network 或 Anvil 顶上,分工逻辑没变。

10. 生命周期里 Testing 阶段的三项内容分别管什么?

单元测试确认单个合约函数按预期工作;集成测试验证整个 DApp 生态的运转,包括前后端连通;安全审计要请外部专家来找漏洞(p.32)。三项互不替代,审计尤其不能自己审自己。

11. 为什么 Upgrades 要单独作为一个生命周期阶段?

因为合约部署后代码无法直接修改(p.11)。想改只能用代理模式另起一层间接跳转,而这件事必须在设计阶段就决定,上线后加不上(p.34)。这个阶段还包含治理机制和持续监控——后者不只看有没有被攻击,也要确认合约跟得上以太坊自身的网络升级。

下一讲

同一周的后半份正式进 Solidity 语法,把这半份里反复出现的”合约不可修改""合约不能自己醒来""代理模式”逐个落到代码上——不可修改对应 selfdestruct 的语义变迁,代理模式对应 delegatecall,而监控异常交易靠的是事件(event)。

下一讲 →
L04b L04b Solidity:在广场中央装一台谁都能按的机器

个人整理的学习笔记,不是官方材料;数字与结论以课件和讲师为准。