随着EOS主网即将上线,EOS映射这个事情就必须在主网上线前完成。
什么是EOS映射?
简单地说,目前的EOS实际上是基于ETH主网发行的Token,等到EOS主网上线时,必须有一种机制能够把基于ETH地址的EOS Token给“转移”到EOS主网地址上,这个过程就是映射。
不做映射行不行?
不做映射将导致持有的EOS Token在主网上线后被清零,也就是无偿销毁,给其他EOS持有人做了一点微小的贡献。
那么EOS映射的原理是什么呢?
假设小明持有某个ETH地址的EOS Token,通过映射,到了6月份,小明持有的ETH地址的EOS Token作废,取而代之的是他将在他持有的EOS地址上获得等量的EOS。
EOS Token本身存储在ETH的合约中,因此,任何人都可以获得ETH地址
->EOS数量
的映射表,但是要把ETH地址的EOS转移到将来真正的EOS地址,就还需要一个ETH地址
->EOS地址
的映射表,这个映射表实际上也在ETH的合约中,但是,注册ETH地址
->EOS地址
的过程是手动的,原因是,只有持有ETH地址私钥的人才能注册对应的ETH地址,这样保证了EOS Token持有人才能设置自己的EOS地址。
因此,映射原理简单地来说就是:
小明持有某个ETH地址的私钥(记作eth_priv
)以及对应ETH地址(记作eth_addr
)的EOS Token;
小明必须手动创建一个EOS地址的私钥(记作eos_priv
)以及对应的EOS地址(记作eos_addr
);
最后,小明通过调用合约的注册方法,传入自己的eth_addr
和eos_addr
,完成映射。由于这个过程需要私钥eth_priv
签名,所以其他人不可能把小明的ETH地址映射到自己的EOS地址上。
映射过程中,要保证安全,就要确保创建EOS私钥eos_priv
的过程绝对安全。
EOS官网提供了一个在线创建EOS私钥和对应地址的页面:
点击REGISTER EOS KEY
可以获取一个在线生成的EOS私钥及地址:
以上图为例,我们获取到的EOS私钥是5Jd6Zhcv1DWCZkRHb6pGNjpRAYZ5m2HBDC3u555jCuCD3nmnUgZ
。
做完映射后,最关键的问题是必须保存私钥,并且直到官方钱包可用后,才能把私钥导入到钱包中。在此期间,如果私钥被泄漏,主网上线后的EOS就不属于你了。
能不能用现有的ETH私钥作为EOS私钥?这样,映射完成后,就不必保存私钥,上线后直接导入ETH私钥,这样更方便。
这种方式是可行的。我们来看一下EOS私钥和地址的编码格式。
通过对EOSIO的eosjs-ecc的JavaScript源码分析可知,EOS私钥编码格式和Bitcoin的非压缩格式私钥编码完全一致,而EOS地址的编码就比较奇葩,它的算法是:
地址不是公钥哈希,而是包含公钥,是不是无比山寨?
先不吐槽了,言归正传,现在我们需要共享ETH私钥和EOS私钥,假设我们拥有ETH私钥:
0x6a49b749ee5588e7d8f59e42848072ba0de3484370f23afe12aea1ca16f89761
通过下面的代码就可以正确转换成EOS私钥和EOS地址:
// THE CODE IS PROVIDED ON AN "AS IS" BASIS, AND NO WARRANTY,
// EITHER EXPRESS OR IMPLIED, IS GIVEN.
// YOUR USE OF THE CODE IS AT YOUR SOLE RISK.
const
ethUtil = require('ethereumjs-util'),
bitcoin = require('bitcoinjs-lib'),
wif = require('wif'),
bs58 = require('bs58');
let
ethPriv = '0x6a49b749ee5588e7d8f59e42848072ba0de3484370f23afe12aea1ca16f89761',
rawPriv = Buffer.from(ethPriv.substring(2), 'hex'),
ethAddr = '0x' + ethUtil.privateToAddress(rawPriv).toString('hex'),
btcPriv = wif.encode(0x80, rawPriv, true),
eosPriv = wif.encode(0x80, rawPriv, false);
let
compressedPub = bitcoin.ECPair.fromWIF(btcPriv).getPublicKeyBuffer(),
checksum = bitcoin.crypto.ripemd160(compressedPub),
addr = Buffer.alloc(compressedPub.length + 4);
compressedPub.copy(addr, 0);
checksum.copy(addr, compressedPub.length, 0, 4);
let eosAddr = 'EOS' + bs58.encode(addr);
console.log('Raw Private: ' + rawPriv.toString('hex'));
console.log('ETH Address: ' + ethAddr);
console.log('BTC Private: ' + btcPriv);
console.log('EOS Private: ' + eosPriv);
console.log('EOS Address: ' + eosAddr);
执行结果如下:
Raw Private: 6a49b749ee5588e7d8f59e42848072ba0de3484370f23afe12aea1ca16f89761
ETH Address: 0xb289c33560b6ef88ce481406f61b04a93f6ffaa0
BTC Private: KznKZLHWwxBt3YeCDWfcrwzHf8Gc1JeQ4omnpy1sHXNUAsBzpT7q
EOS Private: 5Jd6Zhcv1DWCZkRHb6pGNjpRAYZ5m2HBDC3u555jCuCD3nmnUgZ
EOS Address: EOS7nmwuAaB8WvYXJuH3YkXHGh7ABk4njitZRkjKCgaFCLcXEpAfA
生成的EOS私钥及EOS地址和官网生成的完全一致,说明转换正确。
对于普通用户来说,把生成的EOS地址作映射,就不必保存EOS私钥。
对于交易所这种拥有大量ETH地址的机构来说,通过计算ETH私钥对应的EOS地址来映射,可以避免额外生成并持有大量EOS私钥。
最后友情提醒:
除了EOS官网,不要使用任何第三方网站在线生成的EOS私钥!
映射过程只需填写EOS地址,不能填写EOS私钥!
本文中的代码可自由使用,但未经全面测试,不承担任何责任。使用本文中的代码造成的任何后果完全自负!