惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

The GitHub Blog
The GitHub Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Microsoft Security Blog
Microsoft Security Blog
J
Java Code Geeks
S
SegmentFault 最新的问题
Apple Machine Learning Research
Apple Machine Learning Research
N
Netflix TechBlog - Medium
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园_首页
宝玉的分享
宝玉的分享
Google DeepMind News
Google DeepMind News
B
Blog RSS Feed
Hugging Face - Blog
Hugging Face - Blog
量子位
Blog — PlanetScale
Blog — PlanetScale
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
阮一峰的网络日志
阮一峰的网络日志
D
Docker
罗磊的独立博客
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
云风的 BLOG
云风的 BLOG
IT之家
IT之家
MyScale Blog
MyScale Blog
Microsoft Azure Blog
Microsoft Azure Blog

又耳笔记

用AI挣钱之AI建站:二维码生成器工具 用AI挣钱之AI建站:https://markdowntopdf.top Cloudflare Workers实战番外一:用Static Assets托管网站,告别传统方案 Cloudflare Workers实战(五):不止JavaScript,拥抱Python与Rust Cloudflare Workers实战(四):托管和分发静态文件 Cloudflare Workers实战(三):实现认证、重定向与缓存 Cloudflare Workers实战(二):动态修改后端响应 Cloudflare Workers实战(一):随心所欲操作客户端请求 Cloudflare workers不完全指南 使用n8n创作短篇小说 水果风波:信任的代价 用Python将PDF文件转换成图片 rust网络框架Pingora源码阅读3 rust网络框架Pingora源码阅读2 rust网络框架Pingora源码阅读1 Pingora快速入门教程1之总览 Rust模板引擎askama快速入门引擎 使用Loco快速搭建自己的后台系统 用Rust发一封图文并茂的邮件 Rust小项目: 写一个简单的恶意流量阻断器 Rust小项目: 写一个简单的网页爬虫 Rust命令行库Clap快速入门教程 Rust小项目:用Rust写一个端口扫描器 Rust真全栈开发快速入门 rust声明宏快速入门教程 Rust文本处理快速入门教程 RUST web框架axum快速入门教程6之测试 白嫖免费的Rust在线运行时shuttle RUST web框架axum快速入门教程5之中间件 用Rust来做以太坊开发5之事件日志及签名
用Rust来做以太坊开发1之客户端
About 又耳宁 关于技术与股票的一些零碎想法 · 2023-11-19 · via 又耳笔记

本系列文章主要是用Rustethers-rs来复刻《用Go来做以太坊开发》这本书本的内容,所以本系列文章的标题叫做《用Rust来做以太坊开发》, 算是ethers-rs的快速入门教程, 因为原书写得足够好了,所以本系列更多的只是代码层面的复刻,不会说明太多相关的基础知识。

本书和《用Go来做以太坊开发》这本书秉承一样的宗旨

本意是如果你已经对以太坊和Rust有一些熟悉,但是对于怎么把两者结合起来还有些无从下手,那这本书就是一个好的起点 - 改自《用Go来做以太坊开发》

关于Ethereum的开发可以一般来说分为两类。

  • 链上开发,也就是开发合约,这部分一般使用solidity编程语言来开发。
  • 链外开发,也就是跟区块链的交互,比如读取区块数据,发送交易及与合约交互等。

其实还有一种,那就是侧链或者说layer2之类的开发。

本系列文章主要专注于第二种。

本文用到的依赖如下:

ethers = {version="2.0", features=["rusttls", "ws"]}
tokio = {version="1", features=["full"]}
eyre = "0.6"

快速入门

ethers-rsgo-ethereum的概念有点不一样,前者叫provider, 后者叫client,provider这个概念应该是从ethers.js哪里继承过来的,如果你使用过ethers.js那么对于ethers-rs的很多概念应该比较熟悉。

use ethers::prelude::*;

const RPC_URL: &str = "https://cloudflare-eth.com";

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let provider = Provider::<Http>::try_from(RPC_URL)?;
    let block_number = provider.get_block_number().await?;
    println!("当前节点区块高度: {block_number}");
    Ok(())
}

客户端/provider

要想跟以太坊网络交互,自然是要先连接网络中的一个节点的,对于节点我们有很多选项,大致分为两类,公开(外部)的和私有的,下面是一些公开的免费接口(都需要注册), 私有的自然是需要自己搭建,这里就不赘述了。

  1. Etherscan
  2. INFURA
  3. Alchemy
  4. Pocket Gateway
  5. Ankr

具体的优缺点和详细对比参考:https://docs.ethers.org/v5/api-keys/

如果查询的数据比较简单,比如只是区块链的基本数据(区块hash, 交易列表,事件列表)那么可以直接使用免费公开的接口如:

上面的不同主要在于使用的应用协议不同,如果要做监听类的操作,我们需要使用wss(Websocket)协议。

当我们确定好要连接的节点之后,就可以使用代码连接了。

use ethers::prelude::*;

const HTTP_RPC_URL: &str = "https://cloudflare-eth.com";
const WEBSOCKET_RPC_URL: &str = "wss://cloudflare-eth.com";

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let provider = Provider::<Http>::try_from(HTTP_RPC_URL)?;
    let block_number = provider.get_block_number().await?;
    println!("current block number: {block_number}");
    let provider = Provider::<Ws>::connect(WEBSOCKET_RPC_URL).await?;
    let block_number = provider.get_block_number().await?;
    println!("current block number: {block_number}");
    Ok(())
}

对于本地连接,一种更高效的连接方式是IPC连接。

use ethers::providers::Provider;

const IPC_RPC_URL: &str = "~/.ethereum/geth.ipc";

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let provider = Provider::connect_ipc(IPC_RPC_URL)?;
    let block_number = provider.get_block_number().await?;
    println!("current block number: {block_number}");
    Ok(())
}

至此我们有了一个可以访问以太坊网络的客户端,但是网络不总是可靠的,比如网络掉线或者网络重连等,所以我们不得不处理这些琐碎的问题,这些问题一般处理起来比较烦人,不过庆幸的是,ethers-rs已经为我们做了这些琐碎的工作,它提供了很多额外的包装,比如QuorumRetryRW等包装类型,它们分别代表的功能如下

  • Quorum: 在创建的时候设置多个请求后端,只有当结果超过50%的值一样才会返回,比如创建的时候设置了三个节点,分别返回了[1,1,3], 那么Quorum这个类型的客户端会返回1,即使结果3最先返回。
  • Retry: 这个应该很好理解,就是重试,我们可以设置最大重试次数和回退的初始值。
  • RW: 这个就是读写分离,一个用来读,一个用来写,这个一定程度上也能提升性能。

具体示例代码参考官方文档吧:

除此之外,ethers-rs还提供Mock用于测试, 以及自定义的扩展。

小结

本文只是简单的罗列了ethers-rs的各种构建客户端的方式,对应着《用Go来做以太坊开发》的第一章, 和go-ethereum不同的是,ethers-rs提供了很多额外的包装类型,可以不用处理重试,数据一致性(一定程度上的数据一致性, 这对Quorum选择的多个节点有要求)等一些常见的问题,通过这些包装类型我们可以写出更安全更高效的代码。

参考链接