为何ton4j生成的24助记词钱包地址与Ton链应用地址不符?
我使用ton4j库通过以下24个助记词生成密钥对:artwork、people、where、dolphin、assume、develop、polar、link、company、boil、over、shed、clump、fall、seed、flag、private、opinion、budget、follow、install、skill、agent、garbage,随后创建WalletV4R2钱包并输出地址。但该地址与使用相同助记词在Tonkeeper等Ton区块链应用中创建的钱包地址不一致,请问这是什么原因?
代码片段
public class App { public static void main(String[] args) { try { Pair key = Mnemonic.toKeyPair(Arrays.asList("artwork", "people", "where", "dolphin", "assume", "develop", "polar", "link", "company", "boil", "over", "shed", "clump", "fall", "seed", "flag", "private", "opinion", "budget", "follow", "install", "skill", "agent", "garbage")); // 使用24个助记词生成钱包的公钥和私钥对 TonLibService tonLibService; // TonlibService类实例 tonLibService = new TonLibService(true, key.getSecretKey()); // 传入测试网标识和生成的密钥实例化TonlibService public TonLibService(Boolean isTestNet, byte[] adminWalletSecret) throws InterruptedException { // 用配置文件初始化TonLib tonlib = Tonlib.builder().testnet(isTestNet) .pathToTonlibSharedLib("lib/tonlibjson.dll") .pathToGlobalConfig("lib/testnet-global.config.json") .verbosityLevel(VerbosityLevel.FATAL) .ignoreCache(false) .build(); // 用私钥初始化管理员钱包 adminWallet = WalletV4R2.builder() .tonlib(tonlib) .keyPair(TweetNaclFast.Signature.keyPair_fromSeed(adminWalletSecret)) .build(); System.out.println("Admin Wallet Address:" + adminWallet.getAddress());
地址不一致主要是以下几个常见原因导致的:
主网/测试网环境不匹配
代码里初始化TonLib时指定了testnet(true),连接的是测试网,但Tonkeeper默认创建的是主网钱包。测试网和主网的地址底层网络标识不同,字符串自然不一致。可以把代码里的testnet(true)改成testnet(false),生成主网地址后再对比试试。密钥重复生成逻辑错误
代码里先通过Mnemonic.toKeyPair生成了密钥对,之后又用TweetNaclFast.Signature.keyPair_fromSeed(adminWalletSecret)重新生成了一次密钥对。这属于重复处理,很可能导致最终使用的密钥和助记词推导的标准密钥不一致。直接用Mnemonic生成的key对象初始化钱包就行,修改代码如下:adminWallet = WalletV4R2.builder() .tonlib(tonlib) .keyPair(key) // 直接使用Mnemonic生成的密钥对 .build();助记词推导路径差异
Ton主流应用比如Tonkeeper默认遵循BIP44规范,使用路径m/44'/607'/0'/0/0推导密钥,但ton4j的Mnemonic.toKeyPair可能用了不同的路径,甚至直接把助记词种子当密钥用,没走标准路径。需要检查ton4j的Mnemonic类实现,确认是否按Ton标准BIP44路径生成密钥。地址格式差异
WalletV4R2地址分可退回(bounceable)和不可退回(non-bounceable)两种格式,Tonkeeper默认显示的是不可退回格式,而ton4j的getAddress()可能返回的是可退回格式,反之亦然。可以把两种地址转换为同一格式后再对比。
内容的提问来源于stack exchange,提问作者Feenix Net

