地址
在Conflux中,每个 账户 都与一个公私钥对相关联,并由一个“地址”标识。 本页面介绍地址在core space中的表示和计算方式。
请参考 General-address了解有关地址的基本概念。
Hex地址 和 Base32 地址
在 Conflux-rust v1.1.1
发布之前,Conflux 地址完全以十六进制编码字符串形式呈现,例如 0x1292d4955b47f5153b88c12c7a94048f09839
此格式与Etherum和其他兼容的EVM区块链使用的地址非常相似。 然而,Conflux 采用独特的方法来计算EOA地址, 这意味着由同一私钥生成的地址字符串在Conflux 和 Etherum之间通常是不同的。 这种表面上的相似性,加上计算上的差异, 使得用户很容易将Conflux地址与Ethereum 地址混淆,从而可能导致资产损失。
为了解决这个问题,Conflux在 CIP-37 中引入了一个新的基于 base32 编码地址格式。 新格式直接来自原有的十六进制编码地址,包括一个独特的前缀(例如"cfx")、一个可选的地址类型和一个校验和。 因此,上文提到的Hex编码地址可以转换成更容易识别的base32地址。例如 cfx:aakkfzezns4h8ymx1cgmcnd4x3aev6e2hexz250ym5
, 可选的,也可以表示为详细格式地址,详细格式包含了非必须的地址类型信息, 例如 CFX:TYPE .USER:AAKKFZEZNS4H8YMX1CGMCN4X3AEV6E2HEXZ250YM5
. 这种新格式最大限度地减少了Conflux 和 Etherum地址之间混淆的风险,提供了更安全和更方便的用户体验。
在Conflux Core Space 的生态中,都需要使用Base32地址——但是智能合约 .sol
源代码除外。 在.sol
文件中需要硬编码EIP-55 校验和地址的情况下,开发人员应该选择使用Conflux的十六进制编码地址,而不是Base32格式。
地址计算
本节内容仅供信息参考。 用户或开发者通常不需要自己计算十六进制地址。 建议基于 SDK 或 RPC 的返回值来获取 EOA / 合约地址,使用 SDK 或 在线地址转换器 来转换十六进制和 base32 地址格式。
十六进制地址计算
Base32地址直接由原始的十六进制编码地址派生而来。 因此,我们需要理解十六进制地址的计算方法。
Conflux 十六进制地址是一个20字节的十六进制值,以“0x”开头的包括42个字符的字符串表示。 十六进制编码地址以一个1(3)字符“类型标识”开头,表示地址类型。 目前有三种类型的标识:
(0x)1
: 代表一个EOA 帐户的地址(0x)8
: 代表一个合约的地址(0x)0
: 表示一个在链上实现硬编码逻辑 内置合约, 或一个空地址 (0x0000000000000000000000000000000000000000000000000000
)。
EOA 十六进制地址计算
计算EOA 十六进制地址的规定详见 Conflux protocol specification 3.1: 账户
. 将账户公钥进行Keccak运算得到摘要,账户地址由4位类型标识和该摘要的最右侧156位串联而成。
合约地址计算
可选的,合约可以通过 create2
操作码进行部署。
合约地址的计算方式与以太坊有很大不同。
如果使用 create2
,可以使用以下Python代码计算部署地址:
# using web3.py is also viable
# from web3 import Web3
from conflux_web3 import Web3
# ensure salt is a bytes32 to avoid unmatched result caused by encoding approach
def compute_address_using_salt(salt: bytes, bytecode_hash: bytes, hex_deployer_address: str):
core_part = Web3.solidityKeccak(
["bytes1", "address", "bytes32", "bytes32"],
["0xff", hex_deployer_address, salt, bytecode_hash]
)
return "0x8"+ core_part.hex()[-39:]
如果 create2
未被使用:
# using web3.py is also viable
# from web3 import Web3
from conflux_web3 import Web3
def compute_address_using_nonce(nonce: int, bytecode_hash: bytes, hex_deployer_address: str):
core_part = Web3.solidityKeccak(
["bytes1", "address", "bytes32", "bytes32"],
["0x00", hex_deployer_address, nonce.to_bytes(32, "little"), bytecode_hash]
)
return "0x8"+ core_part.hex()[-39:]
Base32地址计算
Conflux的 base32 地址指由 CIP-37 定义的具有网络前缀的Conflux Base32校验和地址。 该地址由表示该地址有效的网络的网络前缀、一个冒号(":"
) 和一个 Base32 编码的载荷组成,并包含一个校验和,例如cfx:aarc9abycue0hzgyr53m6cxedgccrmybjgh4xg
。 可选的,地址可以在网络前缀和载荷之间包含一组键值对,格式为key.value
,以冒号分隔,例如cfx:type.user:aarc9abycue0hhzgyrr53m6cxedgccrmmyybjgh4xg
。
网络前缀(Network Prefix)
网络前缀
是以下值之一: "cfx"
(代表主网, 对应于网络 ID 1029), "cfxtest"
(测试网, 相对应网络ID 1), "net[n]"
n !=1,1029
(代表私有Conflux网络)
有效的网络前缀示例: "cfx"
, "cfxtest"
, "net17"
无效的网络前缀示例: "bch"
, "conflux"
, "net1"
, "net1029"
地址类型(Address Type)
地址类型是一个可选字段,为地址类型提供可读的信息。 对于空地址 (0x000000000000000000000000000000000000000000
), 地址类型必须是 type. null
。 其他为:
0x0
:type.builtin
0x1
:type.user
0x8
:type.contract
载荷 (Payload)
- 拼接
版本字节(version-byte)
:将版本字节
(0x00
) 与十六进制地址拼接起来,得到一个21字节数组。 - Base32 编码:将以上结果从左到右编码,将每5位序列映射到对应的 ASCII 字符(见下文字母表)。 在结尾补零位(应为2个零位),以完成未完成的任何块。
0x00 => a 0x08 => j 0x10 => u 0x18 => 2
0x01 => b 0x09 => k 0x11 => v 0x19 => 3
0x02 => c 0x0a => m 0x12 => w 0x1a => 4
0x03 => d 0x0b => n 0x13 => x 0x1b => 5
0x04 => e 0x0c => p 0x14 => y 0x1c => 6
0x05 => f 0x0d => r 0x15 => z 0x1d => 7
0x06 => g 0x0e => s 0x16 => 0 0x1e => 8
0x07 => h 0x0f => t 0x17 => 1 0x1f => 9
校验和(Checksum)
- 准备输入校验和输入:
data
被用作校验和函数的输入。 It contains:- The lower 5 bits of each character of the
network-prefix
, e.g."cfx..."
becomes0x03, 0x06, 0x18, ...
- 分隔符(5比特0)。
- 5位一组将载荷分块。 如果需要,使用0在载荷的最右侧进行填充,以便恰好将载荷分为5位1组。
- 八个零作为校验和的"模板"。
- The lower 5 bits of each character of the
- 计算校验和:使用比特币现金校验和算法计算
data
的校验和。 - Base32编码:根据 Payload-Base32编码中的相同步骤编码返回的 40位校验和。
最终结果和示例
连接这些部分就能获得最终地址: [network-prefix]
, ":"
, [payload]
, [checksum]
- 可选的,可以在其中包含address-type:
[network-prefix]
,":"
,[address-type]
,":"
,[payload]
,[checksum]
下面是一个展示了编码各步骤的例子:
encode(0x1a2f80341409639ea6a35bbcab8299066109aa55, "cfx")
1. address-type: "type.user"
2. version-byte: 0x00
3. payload: [0x00, 0x1a, 0x2f, 0x80, 0x34, 0x14, 0x09, 0x63, 0x9e, 0xa6, 0xa3, 0x5b, 0xbc, 0xab, 0x82, 0x99, 0x06, 0x61, 0x09, 0xaa, 0x55]
5-bit parts: [0x00, 0x00, 0x0d, 0x02, 0x1f, 0x00, 0x01, 0x14, 0x02, 0x10, 0x04, 0x16, 0x07, 0x07, 0x15, 0x06, 0x14, 0x0d, 0x0d, 0x1b, 0x19, 0x0a, 0x1c, 0x02, 0x13, 0x04, 0x03, 0x06, 0x02, 0x02, 0x0d, 0x0a, 0x0a, 0x14]
base32-encoded: "aarc9abycue0hhzgyrr53m6cxedgccrmmy"
4. checksum input: [0x03, 0x06, 0x18, 0x00, 0x00, 0x00, 0x0d, 0x02, 0x1f, 0x00, 0x01, 0x14, 0x02, 0x10, 0x04, 0x16, 0x07, 0x07, 0x15, 0x06, 0x14, 0x0d, 0x0d, 0x1b, 0x19, 0x0a, 0x1c, 0x02, 0x13, 0x04, 0x03, 0x06, 0x02, 0x02, 0x0d, 0x0a, 0x0a, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
checksum output: 688543492710
checksum string: "ybjgh4xg"
5. concatenated result: "cfx:type.user:aarc9abycue0hhzgyrr53m6cxedgccrmmyybjgh4xg"