构建以太坊应用时,传统的客户端-服务器架构中新增了区块链这一核心组件。本文将深入探讨以太坊应用的常见架构模式,涵盖无服务器应用、浏览器插件、私有节点、离线签名等关键设计要素,帮助你构建高效可靠的去中心化应用。
无服务器应用中的客户端-区块链交互
无服务器应用是以太坊最典型的应用形式,整个交互流程完全在客户端和区块链之间进行。
客户端代码分发
首先需要将客户端代码分发给用户。最简单的方式是设置一个包含web3功能的静态页面,可以托管在AWS S3、Google Cloud、Github pages等任何云平台或自有服务器上。如果用户支持bzz或ipfs协议,还可以通过Swarm或IPFS实现完全去中心化分发。
区块链查询机制
应用需要能够从区块链读取信息,这要求连接到活跃的以太坊节点。用户可能已经通过官方Mist客户端或流行的Metamask浏览器插件建立了节点连接。对于没有安装这些工具的用户,可以连接到公共以太坊节点进行查询操作。
公共节点应当只开放查询功能,禁止暴露账户管理API,且不能有任何解锁的账户。Infura提供了免费的公共节点服务,是不错的选择。
交易发送策略
当用户需要提交交易并执行状态改变操作时:
- 已安装Mist或Metamask的用户可以直接通过这些工具管理账户并批准交易
- 其他用户需要手动发送交易来与应用交互
大多数应用通过要求用户向特定地址发送ETH来实现这一过程,通常会提供二维码或复制到剪贴板功能。客户端应用可以监控合约事件来更新用户界面。
对于需要执行合约函数的场景,可能要求用户在发送ETH时附带额外数据。可以使用合约函数的request方法获取执行方法所需的数据:
SimpleToken.at(tokenAddress).transfer.request("0xbcfb5e3482a3edee72e101be9387626d2a7e994a", 1e18).params[0].data这种模式需要用户进行相当复杂的操作,不是所有用户都了解如何在以太坊交易中附加数据。如果必须实现,请确保合约的回退函数能够拒绝所有支付或具有合理的默认行为,避免用户忘记包含额外数据时损失资金。
聪明的回退函数设计可能总是执行用户发送交易的预期行为,这样智能合约只需对用户发送资金做出反应,根据当前状态运行不同的功能,而无需用户设置任何额外数据。
另一个技巧是添加代理合约,每个代理合约在接收以太币时在主合约中执行特定功能。这种方法虽然只适用于简单的应用,但可以帮助减少浏览器中没有以太坊感知软件的用户的复杂性。
实现自有钱包方案
另一种让用户与智能合约进行复杂交互的方法是在应用中集成钱包管理功能。应用可以为用户创建新账户,用于直接从代码发送交易。
用户需要为这个新账户注入一些以太币,一旦账户有足够的余额支付交易费用,客户端代码就可以通过点击代表用户执行任何需要的操作。
这种模式涉及大量编码工作,需要添加生成、加密和导入以太坊账户的功能。所有交易都需要手动创建和签名,然后作为原始交易发送到节点。它还需要用户更多参与,负责设置新账户并妥善保管账户文件。
然而,一旦设置完成,用户就可以直接从你的应用程序零摩擦地进行以太坊交易,而无需安装任何软件。👉 获取完整的钱包集成方案
服务器与区块链的交互模式
现在让我们添加服务器组件,暂时将客户端放在一边。以下内容不仅适用于应用服务器,也适用于独立应用、脚本或批处理过程。
设置本地节点
第一种解决方案是设置本地以太坊节点,并从应用程序使用其JSON RPC接口执行所有区块链操作。
你可能希望保持一个解锁账户以便从应用程序运行交易(Geth和Parity的unlock标志在这里很有用)。确保节点的JSON RPC接口只能从你的应用程序访问,否则任何人都可能访问你的节点并窃取资金。作为额外的预防措施,将解锁账户中的资金保持在最低限度,并根据需要从不同的来源补充。
离线签名与公共节点
另一种解决方案是让应用离线签名交易,然后将它们中继到公共节点。这种方法需要盲目信任所连接的公共节点:虽然它不能修改你发送给它的交易,但它可以选择不将它们中继到网络,或者为你的查询提供虚假响应。
可以通过同时连接到多个节点并向所有节点发送相同的交易或查询来缓解这个问题,但这会使你的代码库更加复杂。
整体架构协调与最佳实践
在了解了设置客户端-区块链和服务器-区块链查询和交易的不同方式后,现在讨论如何将所有内容协调组织起来。
客户端与服务器协调
客户端和服务器同时与区块链交互意味着你可能需要协调两者。例如,你可能希望服务器对客户端在链上执行的操作做出反应,或者在客户端可视化合约的某些状态变化。
观察合约变化的规范方法是从客户端和服务器[监听合约事件]。精心设计事件,确保所有相关操作都有相关联的事件,并使用索引参数,以便观察者可以只过滤与他们相关的事件。
客户端也可以将他们发出的交易id发布到服务器,作为在链上执行操作的证明,而不是让服务器监听事件。但是请注意,恶意行为者可能正在监控链上交易,并可能向服务器推送来自不同客户端的交易id,假装它属于自己。确保仅将客户端到服务器的消息用作通知,而不是作为事实来源。
无论依赖监控交易还是事件,都要确保在合理数量的确认后才对其做出反应。即使交易已被挖掘,它仍然可能受到[链重组]的影响,并最终在不同的上下文中运行,可能变得无效。在采取行动之前等待大约十几个区块(在测试网络中更多),但考虑让最终用户知道交易成功但尚未确认,以免让他们一无所知。
服务器职责与考量
关键问题是你为什么需要服务器。在传统的客户端-服务器应用中,服务器充当永久存储,执行业务逻辑并协调客户端;所有这些任务现在都可以在链上执行。
尽管如此,支持应用的服务器仍然有许多用途。首先,链上代码不能直接与链外服务协作。这意味着如果你想与第三方服务集成,注入外部数据(如USD/ETH汇率),或执行发送电子邮件等基本操作,你需要服务器来处理这些。
服务器还可以充当智能合约的缓存或索引引擎。虽然最终的事实来源是区块链,但你的客户端可以依赖服务器进行搜索功能,并在链上验证返回的数据。
由于使用合约存储会产生gas成本,如今在以太坊上存储大数据非常昂贵。因此,你的应用可能还依赖服务器存储大数据块,而只在链上保留哈希值用于验证。复杂计算也是如此,可能超过以太坊区块gas限制,因此需要在单独的基础设施中运行。
值得强调的是,围绕EVM出现了越来越多的项目,为这些服务提供无缝集成。例如存储领域的Filecoin或Storj,以及计算领域的Truebit。最终,服务器可能会变得越来越薄,直到消失在一系列侧链服务和集成中。也许几年后,这篇文章将过时,我们的区块链应用将以完全去中心化的方式运行。
常见问题
什么是以太坊无服务器应用?
以太坊无服务器应用是指整个交互流程完全在客户端和区块链之间进行的去中心化应用。它不需要传统的中枢服务器,客户端代码可以直接与区块链网络交互,实现真正的去中心化架构。
如何选择适合的节点连接方案?
选择节点连接方案需考虑用户群体和技术要求。对于技术用户,推荐使用Metamask或Mist;对于普通用户,可以使用公共节点如Infura。如果应用需要高度去中心化,可以考虑让用户自行选择节点提供商。
离线签名有哪些安全风险?
离线签名虽然增强了安全性,但依赖公共节点中继交易。主要风险包括节点可能不中继交易或提供虚假查询响应。建议通过多节点验证和交易状态监控来降低这些风险。
为什么还需要服务器组件?
尽管区块链能处理许多传统服务器功能,但服务器仍然在集成外部服务、大数据存储、复杂计算和数据索引方面发挥关键作用。链上代码无法直接访问链外资源,这是服务器存在的主要价值。
如何处理交易确认的不确定性?
交易确认需要等待足够数量的区块确认(主网约12个块,测试网更多)。应在用户界面明确显示交易状态:已提交、已打包、已确认等不同阶段,管理用户预期并提供良好的用户体验。
智能合约事件监听的最佳实践是什么?
设计事件时应包含所有关键状态变化,使用索引参数提高过滤效率,确保事件数据足够用于业务逻辑处理。同时要建立事件重放机制,处理连接中断等异常情况。