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. 总结

相关推荐
Web3李李14 小时前
链游想要获得市场认可,核心从来不是极致去中心化
web3·去中心化·区块链·软件开发·链游开发
圣殿骑士-Khtangc15 小时前
Go错误处理最佳实践进阶从error到panic的完整指南
golang
运维开发笔记16 小时前
3.6 Go defer 语句学习笔记
golang
FfHUCisI17 小时前
Golang HTTP 路由设计与请求处理
开发语言·http·golang
存在morning17 小时前
【Python 开发实践 一】Python vs Go vs Java 三门语言对比
java·python·golang
SoStraw18 小时前
Go + webrpc 实战:人在外面,远程查家里 NAS 磁盘和目录
go·p2p·nas·cgo·json-rpc·webrpc·无公网ip
大鱼>1 天前
以太坊Layer2扩容:Optimistic vs ZK-Rollup完整对比
区块链
圣殿骑士-Khtangc1 天前
Go字符串高效拼接性能对比与底层原理分析
服务器·前端·golang
汇策研习社1 天前
斐波那契均线交易体系:21/55/89三重均线趋势战法详解
大数据·经验分享·金融·区块链·fastbull
同花顺期货通1 天前
期货新手入门品种筛选:2026年低保证金高流动性品种深度解析
区块链