1. go语言从零实现以太坊客户端-JSON-RPC

go语言从零实现以太坊客户端-JSON-RPC

  • [1. JSON-RPC](#1. JSON-RPC)
    • [1.1 JSON-RPC结构](#1.1 JSON-RPC结构)
    • [1.2 常规的HTTP API](#1.2 常规的HTTP API)
    • [1.3 基于Http的JSON-RPC](#1.3 基于Http的JSON-RPC)
  • [2. 以太坊JSON-RPC API](#2. 以太坊JSON-RPC API)
  • [3. JSON-RPC API分类](#3. JSON-RPC API分类)
  • [4. JSON-RPC数据格式](#4. JSON-RPC数据格式)
  • [5. Postman调用以太坊节点JSON-RPC API](#5. Postman调用以太坊节点JSON-RPC API)
    • [5.1 查询区块链ID](#5.1 查询区块链ID)
      • [5.1.1 基于hardhat node节点](#5.1.1 基于hardhat node节点)
      • [5.1.2 基于sepolia节点](#5.1.2 基于sepolia节点)
    • [5.2 查询区块链账户余额](#5.2 查询区块链账户余额)
      • [5.2.1 基于hardhat node节点](#5.2.1 基于hardhat node节点)
      • [5.2.2 基于sepolia节点](#5.2.2 基于sepolia节点)
    • [5.3 查询合约代币名称](#5.3 查询合约代币名称)
      • [5.3.1 基于hardhat node节点](#5.3.1 基于hardhat node节点)
      • [5.3.2 基于sepolia节点](#5.3.2 基于sepolia节点)
    • [5.4 查询合约中账户余额](#5.4 查询合约中账户余额)
      • [5.4.1 基于hardhat node节点](#5.4.1 基于hardhat node节点)
      • [5.4.2 基于sepolia节点](#5.4.2 基于sepolia节点)
    • [5.5 区块链账户转账](#5.5 区块链账户转账)
      • [5.5.1 基于hardhat node节点](#5.5.1 基于hardhat node节点)
      • [5.5.2 基于sepolia节点](#5.5.2 基于sepolia节点)
    • [5.6 合约中账户转账](#5.6 合约中账户转账)
      • [5.6.1 基于hardhat node节点](#5.6.1 基于hardhat node节点)
      • [5.6.2 基于sepolia节点](#5.6.2 基于sepolia节点)
  • [6. 总结](#6. 总结)

1. JSON-RPC

RPC即远程过程调用,一般用于多进程通信。

JSON-RPC是基于JSON格式来进行RPC通信。

TCP通信传输16进制字节流,接收端要按通信协议对字节流逐段截取,将字节数组转换为实际含义值,再进行条件分支流转。通信协议较低层,数据交互复杂。

HTTP一般为前后端应用系统使用,HTTP协议承载SON格式数据,请求的url中包含了后端接口映射名,前端的请求可以直接访问到后端接口。应用层通信协议,数据交互简单。

JSON-RPC是应用层协议,可以基于HTTP、TCP等底层协议,来承载SON格式数据。以太坊是基于http post。请求的url中的后端接口并不是实际要调用的接口,而是一个通用接口。实际要调用的接口名称在JSON格式的数据中。

1.1 JSON-RPC结构

clike 复制代码
// 请求
{
    "jsonrpc": "2.0",
    "method": "method_name",
    "params": [...],
    "id": 1
}

// 响应(成功)
{
    "jsonrpc": "2.0",
    "result": ...,
    "id": 1
}

// 响应(错误)
{
    "jsonrpc": "2.0",
    "error": {
        "code": -32601,
        "message": "Method not found"
    },
    "id": 1
}

1.2 常规的HTTP API

前后端服务,路由到后端的query(string name, int age)方法,返回数据

clike 复制代码
const url = 'https://api.example.com/query';
const data = {
    name: '张三',
    age: 25,
};

const response = await fetch(url, {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
    },
    body: JSON.stringify(data)
});

1.3 基于Http的JSON-RPC

比如要查询账户余额

(1) http请求路由到后端的query(Data data)方法

(2) 解析data结构,method: 'eth_getBalance'表示要调用的方法是eth_getBalance,方法参数是[address, 'latest']

(3)调用eth_getBalance(address, 'latest')

clike 复制代码
const url = 'https://api.example.com/query';
const data = {
	jsonrpc: '2.0',
	method: 'eth_getBalance',
	params: [address, 'latest'],
	id: 1
};

const response = await fetch(url, {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
    },
    body: JSON.stringify(data)
});

2. 以太坊JSON-RPC API

官网介绍

web3.js、Go-Ethereum等库使用不同编程语言实现的JSON-RPC规范。

3. JSON-RPC API分类

操作对象区分为区块链上数据、合约数据。

操作方式区分为读操作、写操作。

分为四种:

(1)读区块链数据

(2)写区块链数据

(3)读合约数据

(4)写合约数据

读操作不改变区块链\合约状态,所以不需要签名等操作,JSON数据格式简单,相当于明文传输。

写操作会改变区块链\合约状态,需要签名等操作,JSON数据格式复杂。

4. JSON-RPC数据格式

以太坊使用的JSON-RPC对params有如下规定:

未格式化的字节数组和数量。 两者都使用十六进制编码传递,但对格式化有不同的要求。

数量

当对数量(整数、编号)进行编码时:编码为十六进制(以"0x"为前缀),最紧凑的表示方法。

0 应表示为"0x0"

以下是一些示例:

0x41(十进制中是 65)

0x400(十进制中是 1024)

错误:0x(后面至少有一位,0 是"0x0")

错误:0x0400(不允许有前导零)

错误:ff(必须有前缀 0x)

当对无格式数据(字节数组、帐户地址、哈希、字节码数组)进行编码时:编码为十六进制,以"0x"为前缀,每字节两个十六进制数字。

以下是一些示例:

0x41(大小为 1,"A")

0x004200(大小为 3,"0B0")

0x(大小为 0,"")

错误:0xf0f0f(位数必须是偶数)

错误:004200(必须以 0x 为前缀)

5. Postman调用以太坊节点JSON-RPC API

5.1 查询区块链ID

5.1.1 基于hardhat node节点

clike 复制代码
method为eth_chainId
params为空数组
即调用eth_chainId()接口
返回16进制字符串"0x539",即1337

5.1.2 基于sepolia节点

返回16进制字符串"0xaa36a7",即11155111

5.2 查询区块链账户余额

5.2.1 基于hardhat node节点

clike 复制代码
method为eth_getBalance
params为[账户地址, 区块参数]
即调用eth_getBalance(address)接口
返回16进制字符串

5.2.2 基于sepolia节点

5.3 查询合约代币名称

5.3.1 基于hardhat node节点

clike 复制代码
method为eth_call
params为
[
	{
		合约地址,
		合约方法和参数
	}, 
	区块参数
]

即调用eth_getBalance(address)接口

合约地址:"0x5FbDB2315678afecb367f032d93F642f64180aa3"
合约方法:name()。keccak256编码函数name(),取前四字节0x06fdde03
返回16进制字符串:
// 0x
// 0000000000000000000000000000000000000000000000000000000000000020  // 偏移量:32字节
// 0000000000000000000000000000000000000000000000000000000000000007  // 长度:7字节
// 4d79546f6b656e00000000000000000000000000000000000000000000000000  // 数据:"MyToken"

调用

5.3.2 基于sepolia节点

5.4 查询合约中账户余额

5.4.1 基于hardhat node节点

clike 复制代码
method为eth_call
params为[
{
	合约地址,
	合约方法和参数
}, 
区块参数]
即调用balanceOf(address)接口
合约地址:"0x5FbDB2315678afecb367f032d93F642f64180aa3"
合约方法:balanceOf(address)。keccak256编码函数balanceOf(address),取前四字节70a08231
方法参数:address为"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266",去掉0x,补齐64位为000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266。
合约方法和方法参数合并为0x70a08231000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266
返回16进制字符串:
// 0x
// 00000000000000000000000000000000000000000000003635c9adc5dea00000  // 数据1000000000000000000000

5.4.2 基于sepolia节点

同上

5.5 区块链账户转账

5.5.1 基于hardhat node节点

clike 复制代码
method为eth_sendTransaction
params为[
{
	转账账户地址,
	接收账户地址,
	金额
}
]
即调用eth_sendTransaction(address,address,uint64)接口
转账账户地址:"0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266"
接收账户地址:"0x70997970C51812dc3A010C7d01b50e0d17dc79C8"
金额:"0x5F5E100"
返回16进制字符串:
// 0xf7d34f6bc376d100540c4ababe71a01fcaa8a30da7d3c965cb26af95f8a067f9  // 交易哈希

5.5.2 基于sepolia节点

不支持eth_sendTransaction,sepolia网络不持有账户私钥,无法解析出账户地址

需要用eth_sendRawTransaction

5.6 合约中账户转账

5.6.1 基于hardhat node节点

clike 复制代码
method为eth_sendTransaction
params为[
{
	合约地址,
	合约方法和参数
}
]
即调用transfer(address,uint256)接口
合约地址:"0x5FbDB2315678afecb367f032d93F642f64180aa3"
合约方法:transfer(address,uint256)。keccak256编码函数transfer(address,uint256),取前四字节a9059cbb
方法参数:
address为"0x70997970C51812dc3A010C7d01b50e0d17dc79C8",去掉0x,补齐64位为00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c8。
value为de0b6b3a7640000(十进制1000000000000000000),补齐64位为0000000000000000000000000000000000000000000000000de0b6b3a7640000
合约方法和方法参数合并为0xa9059cbb00000000000000000000000070997970c51812dc3a010c7d01b50e0d17dc79c80000000000000000000000000000000000000000000000000de0b6b3a7640000
返回16进制字符串:
// "0x1502a7ecf417dc760444dd32e888ab051cf8815669ebf10cf0a9b9a809ed0610"  // 交易哈希

5.6.2 基于sepolia节点

不支持eth_sendTransaction,sepolia网络不持有账户私钥,无法解析出账户地址

需要用eth_sendRawTransaction

6. 总结

相关推荐
PXM的算法星球2 小时前
用 semaphore 限制 Go 项目单机并发数的一次流量控制优化实践
开发语言·后端·golang
ZNineSun3 小时前
GORM:Go的ORM 框架
golang·orm·gorm·crud
源代码•宸3 小时前
Golang语法进阶(定时器)
开发语言·经验分享·后端·算法·golang·timer·ticker
a程序小傲3 小时前
得物Java面试被问:边缘计算的数据同步和计算卸载
java·开发语言·数据库·后端·面试·golang·边缘计算
mutourend12 小时前
以太坊交易类型综述
区块链
nbsaas-boot15 小时前
Go vs Java 的三阶段切换路线图
java·开发语言·golang
modelmd18 小时前
Go 编程语言指南 练习题目分享
开发语言·学习·golang
福大大架构师每日一题1 天前
2026年1月TIOBE编程语言排行榜,Go语言排名第16,Rust语言排名13。C# 当选 2025 年度编程语言。
golang·rust·c#
拔剑纵狂歌1 天前
helm-cli安装资源时序报错问题问题
后端·docker·云原生·容器·golang·kubernetes·腾讯云