Conflux Java-SDK如何适配CIP37

语言: CN / TW / HK

Java-sdk support for CIP37 address

Conflux 做为新一代的公链,不止具有超高的性能,同时保持了对以太坊生态的兼容:使用格式兼容的地址;实现了兼容 EVM 的虚拟机。 保持兼容的好处是降低迁移的成本和门槛。但相似的地址也带来了不少问题,比如通过 shuttleflow 进行跨链操作的时候,经常因为地址相似而混用 并导致资产丢失。资产丢失是一个非常严重的问题,为了优化跨链体验,减少地址用错的问题,Conflux 在CIP37 中尝试引入一种新的地址格式: base32Check。

Before CIP37

Conflux 最初大体沿用了以太坊的地址格式,即十六进制编码,长度为40 的 hex40 地址,但对地址进行了空间划分,包括 0x1开头的普通地址,0x8开头的合约地址,0x0开头的内置合约地址。 只有此三个字符开头的 hex40 地址才是有效的 Conflux 地址。一些以太坊上的地址(0x1开头地址)在 Conflux 上也是有效的,反之,Conflux地址在以太坊上也有1/16的概率可用。

目前 Conflux 有如下三种地址:

  • 普通地址:0x1386b4185a223ef49592233b69291bbe5a80c527
  • 合约地址:0x8269f0add11b4915d78791470d091d25cff73ee5
  • 内置合约:0x0888000000000000000000000000000000000002

正是因为地址的不完全兼容,在跨链的时候使用了错误链的地址,导致资产丢失。另外以太坊在 EIP55 引入了一个带有校验和的地址规范,其将地址中满足某些条件的字符转成大写,从而防止地址输入错误。Conflux 同样引入了改校验规则。

  • 非checksum地址: 0x1386b4185a223ef49592233b69291bbe5a80c527
  • 带checksum地址: 0x1386B4185A223EF49592233b69291bbe5a80C527

CIP37 地址

为了解决地址混淆用错的问题,在 CIP37 引入了全新的 base32 带校验和的地址,该地址除校验和外还可以包含网络,类型等信息。

新旧地址对比:

  • hex40 地址:0x1386b4185a223ef49592233b69291bbe5a80c527
  • base32地址:cfx:aak2rra2njvd77ezwjvx04kkds9fzagfe6ku8scz91

新地址规范采用自定义字符的 base32 编码地址,目前使用的字符如下:abcdefghjkmnprstuvwxyz0123456789(移除了oilq

在新格式地中,同时包含了网络类型信息,目前包括三种:cfx,cfxtest,net[n](中文对应主网,测试网,自定义网络)

  • cfx:aak2rra2njvd77ezwjvx04kkds9fzagfe6ku8scz91
  • cfxtest:aak2rra2njvd77ezwjvx04kkds9fzagfe6d5r8e957
  • net1921:aak2rra2njvd77ezwjvx04kkds9fzagfe65k87kwdf

除此之外地址中还可以包含可选类型信息,目前有四种类型(带类型的地址一般以大写表示):

  • 用户地址: CFX:TYPE.USER:AAK2RRA2NJVD77EZWJVX04KKDS9FZAGFE6KU8SCZ91
  • 合约地址: CFX:TYPE.CONTRACT:ACB2RRA2NJVD77EZWJVX04KKDS9FZAGFE640XW9UAE
  • 内置合约地址: CFX:TYPE.BUILTIN:AAEJUAAAAAAAAAAAAAAAAAAAAAAAAAAAAJRWUC9JNB
  • 零地址: CFX:TYPE.NULL:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0SFBNJM2

hex40 地址和 CIP37 地址是可以互相转换,转换为 byte 数组是一样的。但旧版 hex40 地址(0x开头)转换为base32check地址的时候,需要额外的network id信息。

Conflux fullnode RPC

Conflux-rust 从版本 1.1.1 开始将会使用新地址格式,凡是请求参数,返回结果中包含地址的地方,均使用新格式地址。并且会返回带有类型信息的地址。

RPC 调用时如果你使用了 hex40 地址,会返回如下错误:

{
    "code": -32602,
    "message": "Invalid params: Invalid base32 address: zero or multiple prefixes."
}
复制代码

如果你使用了错误 network 的地址(主网 RPC 服务,使用了测试网的地址),会返回如下错误:

{
    "code": -32602,
    "message": "Invalid parameters: address",
    "data": "\"network prefix unexpected: ours cfx, got cfxtest\""
}
复制代码

Address

Address 类原来只有一个 validate 静态方法,仅用于hex地址格式和类型的校验, 在 1.0 该方法被移动到了 AddressType.validateHexAddress.

创建实例
import conflux.web3j.types.Address;

// 使用新格式地址初始化
Address address = new Address("cfx:aajg4wt2mbmbb44sp6szd783ry0jtad5bea80xdy7p");
// 使用 hex 地址和 netId 初始化
new Address("0x106d49f8505410eb4e671d51f7d96d2c87807b09", 1);
复制代码
实例方法
address.getAddress(); // get a base32 address
// cfx:aajg4wt2mbmbb44sp6szd783ry0jtad5bea80xdy7p
address.getVerboseAddress(); // get a base32 address with type info
// CFX:TYPE.USER:AAJG4WT2MBMBB44SP6SZD783RY0JTAD5BEA80XDY7P
address.getNetworkId();  // get networkId mainnet is 1029, testnet is 1
// 1
address.getType(); // get address type
// user
address.getHexAddress();  // get hex40 address
// 0x106d49f8505410eb4e671d51f7d96d2c87807b09
address.getABIAddress();  // get a org.web3j.abi.datatypes.Address instance
// get a org.web3j.abi.datatypes.Address instance
复制代码

在 1.0 版本 Address 类可以用于地址实例化,并在任何使用地址的地方使用 Address, 包括:

  1. RPC 请求参数和返回结果
  2. Account, AccountManager 相关方法
  3. RawTransaction, TransactionBuilder 相关方法
  4. Call, ContractCall, ERC20, ERC777 相关方法

networkId

从 hex40 地址转换新地址的时候,同时需要 networkId,当前 networkId 跟 chainId 值一样,主网为 1029,测试网为 1

fullnode
  • cfx_getStatus 方法新返回了 networkId 字段
Interface Cfx

增加了从实例获取 chainId, networkId 的方法:

  • getNetworkId()
  • getChainId()
AccountManager

AccountManager 实例化需要传递 networkId

合约交互

合约方法地址参数

如果合约方法调用时需要传递地址,有两种方式:

  1. 创建 Address 实例,然后调用 getABIAddress() 方法,获取可 abi 编码的地址类型
import conflux.web3j.types.Address;
Address a = new Address("0x206d49f8505410eb4e671d51f7d96d2c87807b09", 1);
a.getABIAddress()
复制代码
  1. 如果地址是以太坊地址,需要手动创建可 abi 编码的地址
import org.web3j.abi.datatypes.Address;
new Address("0x206d49f8505410eb4e671d51f7d96d2c87807b09");
复制代码

合约返回结果地址的 decode,也需要使用 org.web3j.abi.datatypes.Address, 然后根据需要,配置 networkId 转为 baseCheck 地址。

分享到: