Conflux Golang SDK如何适配CIP37

语言: CN / TW / HK

Conflux base32Check addresses

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

Before CIP37

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

目前 Conflux 有如下三种地址:

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

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

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

CIP37 地址

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

新旧地址对比:

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

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

在新格式地中,同时包含了网络类型信息,目前包括三种:cfx,cfxtest,net[n]

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

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

  • user: CFX:TYPE.USER:AAK2RRA2NJVD77EZWJVX04KKDS9FZAGFE6KU8SCZ91
  • contract: CFX:TYPE.CONTRACT:ACB2RRA2NJVD77EZWJVX04KKDS9FZAGFE640XW9UAE
  • builtin: CFX:TYPE.BUILTIN:AAEJUAAAAAAAAAAAAAAAAAAAAAAAAAAAAJRWUC9JNB
  • null: CFX:TYPE.NULL:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0SFBNJM2

hex40 地址和 CIP37 地址是可以互相转换,转换为 byte 数组是一样的。

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\""
}
复制代码

go-conflux-sdk

Address

创建Address

创建address实例有以下四种方式,每种方式都提供了Mustxxx方法便于快速创建,使用该方法发生错误时会导致panic; 同时也可以用以下方法的返回值error是否为nil判断一个地址是否合法

  • 通过base32 string创建
func NewFromBase32(base32Str string) (cfxAddress Address, err error)
func MustNewFromBase32(base32Str string) (address Address)
复制代码
  • 通过hex40字符串创建
func NewFromHex(hexAddressStr string, networkID ...uint32) (val Address, err error)
func MustNewFromHex(hexAddressStr string, networkID ...uint32) (val Address)
复制代码
  • 通过common.Address创建
func NewFromCommon(commonAddress common.Address, networkID ...uint32) (val Address, err error)
func MustNewFromCommon(commonAddress common.Address, networkID ...uint32) (address Address)
复制代码
  • 通过byte数组创建
func NewFromBytes(hexAddress []byte, networkID ...uint32) (val Address, err error)
func MustNewFromBytes(hexAddress []byte, networkID ...uint32) (address Address)
复制代码

Note: networkID参数是可选的,如果不传会在client中发送rpc请求时自动设置。

Address实例方法
// ToHex returns hex address string and networkID
func (a *Address) ToHex() (hexAddressStr string, networkID uint32, err error)

// ToCommon returns common.Address and networkID
func (a *Address) ToCommon() (address common.Address, networkID uint32, err error) 

// GetBase32Address returns base32 string of address which doesn't include address type
func (a *Address) GetBase32Address() string

// GetVerboseBase32Address returns base32 string of address with address type
func (a *Address) GetVerboseBase32Address() string

// MustGetHexAddress returns hex format address and panic if error
func (a *Address) MustGetHexAddress() string

// MustGetCommonAddress returns common address and panic if error
func (a *Address) MustGetCommonAddress() common.Address

// MustGetNetworkID returns networkID and panic if error
func (a *Address) MustGetNetworkID() uint32

// CompleteByClient will set networkID by client.GetNetworkID() if a.networkID not be 0
func (a *Address) CompleteByClient(client NetworkIDGetter) error

// CompleteByNetworkID will set networkID if current networkID isn't 0
func (a *Address) CompleteByNetworkID(networkID uint32) error

// IsValid return true if address is valid
func (a *Address) IsValid() bool

// MarshalText implements the encoding.TextMarshaler interface.
func (a Address) MarshalText() ([]byte, error)

// UnmarshalJSON implements the json.Unmarshaler interface.
func (a *Address) UnmarshalJSON(data []byte) error
复制代码

NetworkID

Client类新增GetNetworkID方法便于获取NetowrkID

func (client *Client) GetNetworkID() (uint32, error)
复制代码

AccountManager

AccountManager 实例化需要传递 networkId

func NewAccountManager(keydir string, networkID uint32) *AccountManager
复制代码

合约

由于solidity中使用hex40格式地址,所以Contract对象与合约交互时,仍然使用common.Address地址格式。

Event Decode

事件解析也依旧使用common.Address类型

Internal contract

内置合约AdminControl、Sponsor、Staking中的地址相关参数使用Base32Check格式,sdk会帮助做转换。

分享到: