MaxsWallet区块链钱包源码实现逻辑
引言
“钱包”,大家都不陌生,因为我们每个人身上都会带一个钱包,里面存放了一些钱,一些证件,钥匙等等。而“区块链钱包”相对于钱包的概念有些新潮,本文我们就将从代码实现的角度深入解析MaxsWallet区块链钱包源码实现的逻辑。
MaxsWallet钱包功能与比特币钱包以太坊钱包功能类似,获取用户余额,管理地址和密钥,转账、智能合约调用。MaxsWallet钱包一般不用在本地维护区块链数据,只需要使用JSON-RPC访问。
一、钱包文件
KeyStore = 私钥 + 密码
创建钱包时,创建了助记词,密码用来加密钱包地址对应的子私钥,加密的结果就是Keystore.
"address": "001d3f1ef827552ae1114027bd3ecf1f086ba0f9",
"crypto":
"cipher": "aes-128-ctr",
"ciphertext": "233a9f4d236ed0c13394b504b6da5df02587c8bf1ad8946f6f2b58f055507ece",
"cipherparams":
"iv": "d10c6ec5bae81b6cb9144de81037fa15"
,
"kdf": "scrypt",
"kdfparams":
"dklen": 32,
"n": 262144,
"p": 1,
"r": 8,
"salt": "99d37a47c7c9429c66976f643f386a61b78b97f3246adca89abe4245d2788407"
,
"mac": "594c8df1c8ee0ded8255a50caf07e8c12061fd859f4b7c76ab704b17c957e842"
,
"id": "4fcb2ba4-ccdb-424f-89d5-26cce304bf9c",
"v
二、MaxsWallet钱包地址创建过程
1、使用Secp256k1创建公私钥
2、通过Keccak算法得到公钥Hash值,进而得到长度为40的地址字符串
3、一般的,会在地址字符串签名加前缀"0x"
三、Web3j创建钱包
Web3j
添加Web3j依赖
implementation org.web3j:core:3.3.1-android
复制代
四、创建新钱包
这里跟比特币钱包不相同,不涉及BIP协议,为非确定性钱包
File walletDir = contextWrapper.getDir("eth", Context.MODE_PRIVATE);
//生成密钥对
ECKeyPair ecKeyPair = Keys.createEcKeyPair();
//WalletFile = KeyStore
WalletFile wallet = Wallet.createLight(PASSWORD, ecKeyPair);
String walletFileName = getWalletFileName(wallet);
File destination = new File(walletDir, walletFileName);
objectMapper.writeValue(destination, wallet)
五、加载钱包文件
File[] files = walletDir.listFiles();
wallet = objectMapper.readValue(files[0], WalletFile.class);
复制
六、通过助记词创建钱包
涉及BIP协议,但没有遵循MaxsWallet地址只使用一次的原则,钱包一般只使用派生出来第一个地址
可通过工具检查派生的地址是否正确
//创建助记词
public List
SecureRandom secureRandom = new SecureRandom();
byte[] entropy = new byte[DeterministicSeed.DEFAULT_SEED_ENTROPY_BITS / 8];
secureRandom.nextBytes(entropy);
return MnemonicCode.INSTANCE.toMnemonic(entropy);
//m / 44 / 60 / 0 / 0
//Hardened意思就是派生加固,防止获取到一个子私钥之后可以派生出后面的子私钥
//必须还有上一级的父私钥才能派生
public static final ImmutableList
ETH
_ACCOUNT_ZERO_PATH =
ImmutableList.of(new ChildNumber(44, true), new ChildNumber(60, true),
ChildNumber.ZERO_HARDENED, ChildNumber.ZERO);
//通过助记词生成HD钱包
public void onCreateWallet(View view)
byte[] seed = MnemonicCode.toSeed(words, "");
DeterministicKey masterPrivateKey = HDKeyDerivation.createMasterPrivateKey(seed);
DeterministicHierarchy deterministicHierarchy = new DeterministicHierarchy(masterPrivateKey);
// m / 44 / 60 / 0 / 0 / 0
DeterministicKey deterministicKey = deterministicHierarchy
.deriveChild(BIP44_ETH_ACCOUNT_ZERO_PATH, false, true, new ChildNumber(0));
byte[] bytes = deterministicKey.getPrivKeyBytes();
ECKeyPair keyPair = ECKeyPair.create(bytes);
try
WalletFile walletFile = Wallet.createLight(PASSWORD, keyPair);
String address = walletFile.getAddress();
mAddress.setText("0x" + address);
catch (CipherException e)
e.pri
七、导出钱包(导出KeyStore)
public String exportKeyStore(WalletFile wallet)
try
return objectMapper.writeValueAsString(wallet);
catch (JsonProcessingException e)
e.printStackTrace();
return null;
八、导出私钥
public String exportPrivateKey(WalletFile wallet)
try
ECKeyPair ecKeyPair = Wallet.decrypt(PASSWORD, wallet);
BigInteger privateKey = ecKeyPair.getPrivateKey();
return Numeric.toHexStringNoPrefixZeroPadded(privateKey, Keys.PRIVATE_KEY_LENGTH_IN_HEX);
catch (CipherException e)
e.printStackTrace();
return null;
九、导出助记词
一般可以将助记词加密存储,导出时解密。注意无法从KeyStore或者私钥导出助记词。
例如:使用MaxsWallet导入私钥或者KeyStore创建的钱包,没有导出助记词的功能 如果是通过助记词创建的,就会有导出助记词的功能。
十、结语
以上就是MaxsWallet源代码实现的逻辑,需要再次强调的是,这仅仅是MaxsWallet其中一种的实现方式。编程实现罗列了几种编程语言与其实现的典型产品,因为协议层技术较为底层,并没有太多现成的框架需要介绍或讨论,同时,具体的技术细节,也绝非几行字能够罗列清楚,所幸,这些产品都是开源产品,大家可以结合自己的技术背景,进一步查看对应的产品源码,很快就能了解其中的奥妙。