摘要:本文首發(fā)于深入淺出區(qū)塊鏈社區(qū)原文鏈接以太坊安卓錢包系列通過(guò)助記詞創(chuàng)建賬號(hào)原文已更新,請(qǐng)讀者前往原文閱讀上周我開源了一款錢包,反映很好,一周時(shí)間不到已經(jīng)快到。的功能和類似,它是比特幣協(xié)議的實(shí)現(xiàn),他實(shí)現(xiàn)了及相關(guān)協(xié)議。
本文首發(fā)于深入淺出區(qū)塊鏈社區(qū)
原文鏈接:以太坊(安卓)錢包系列1 - 通過(guò)助記詞創(chuàng)建賬號(hào)原文已更新,請(qǐng)讀者前往原文閱讀
上周我開源了一款錢包,反映很好,一周時(shí)間不到已經(jīng)快到100 Star。接下來(lái)我會(huì)幾篇系列文章把開發(fā)以太坊錢包的核心要點(diǎn)寫出來(lái),也算是對(duì)代碼的一個(gè)解讀。
寫在前面錢包是使用Android安卓平臺(tái)編寫,使用的是原生代碼Java 語(yǔ)言編寫, 是基于Java 1.8 版本,也使用了Java 1.8 中一些較新的語(yǔ)言特性,如 Lambda表達(dá)式等;另外還較多使用了ReactiveX/RxAndroid響應(yīng)式編程用法。
在本系列文章中,重點(diǎn)是介紹以太坊錢包賬號(hào)、交易等邏輯,有時(shí)可能會(huì)假定讀者已經(jīng)了解Android開發(fā)等相關(guān)知識(shí),因?yàn)檫@些內(nèi)容不是文章的重點(diǎn),因此不會(huì)過(guò)多介紹,請(qǐng)海涵。
錢包包含的功能通常一個(gè)錢包會(huì)包含以下功能:
[x] 支持通過(guò)生成助記詞、Keystore文件、私鑰 創(chuàng)建錢包賬號(hào)。
[x] 支持導(dǎo)出錢包賬號(hào)助記詞、私鑰、Keystore文件。
[x] 支持多個(gè)錢包賬號(hào)管理
[x] 賬戶余額查詢及轉(zhuǎn)賬功能(二維碼掃描支持)。
[x] 支持ERC20 代幣(余額顯示、轉(zhuǎn)賬、代幣幣價(jià)顯示)
[x] 支持用法幣(美元和人民幣)實(shí)時(shí)顯示幣價(jià)。
[x] 歷史交易列表顯示
創(chuàng)建賬號(hào)預(yù)備知識(shí)我們先來(lái)介紹第一個(gè)功能:通過(guò)生成助記詞、Keystore文件、私鑰創(chuàng)建錢包賬號(hào)。
本系列中,錢包都是指分層確定性錢包,(HD錢包 Hierarchical Deterministic Wallets), 之前博客有一篇文章分層錢包進(jìn)行了詳細(xì)的介紹,還不熟悉的可以讀一下。
為了保持本文的完整,這里做一個(gè)總結(jié)性回顧:以太坊及比特幣的地址是由隨機(jī)生成的私鑰經(jīng)過(guò)橢圓曲線等算法單向推倒而來(lái) ,BIP32及BIP44是為方便管理私鑰提出的分層推倒方案,BIP39 定義助記詞讓分層種子的備份更方便。
而KeyStore文件是用來(lái)解密以太坊保存私鑰的一種方式,大家可以閱讀下這篇文章: 賬號(hào)Keystore文件導(dǎo)入導(dǎo)出了解更多。
實(shí)現(xiàn)完成的,界面如下圖:
這是一張導(dǎo)入錢包賬號(hào)的截圖(導(dǎo)入和創(chuàng)建,其實(shí)原理一樣),界面仿照ImToken,不過(guò)本文將不會(huì)介紹UI部分的編寫。
Web3j & bitcoinj為了完成創(chuàng)建賬號(hào)功能,我們需要使用到兩個(gè)庫(kù):Web3j 和 bitcoinj
Web3是一套和以太坊通信的封裝庫(kù),Web3j是Java版本的實(shí)現(xiàn),例如發(fā)起交易和智能合約進(jìn)行交互,下圖很好的表達(dá)了其作用。
不過(guò)本文中的功能,主要是使用了web3j中橢圓曲線加密及KeyStore文件的生成與解密。
bitcoinj 的功能和web3類似,它是比特幣協(xié)議的Java實(shí)現(xiàn),他實(shí)現(xiàn)了 BIP32、BIP44及BIP39 相關(guān)協(xié)議。
Android使用Gradle來(lái)構(gòu)建,直接在app/build.gradle文件中加入:
implementation "org.web3j:core:4.1.0-android" implementation "org.bitcoinj:bitcoinj-core:0.14.7"
創(chuàng)建賬號(hào)實(shí)現(xiàn) 通過(guò)助記詞常見錢包賬號(hào)提示: 實(shí)踐中遇到的一個(gè)問(wèn)題,由于bitcoinj 中引入了 com.lambdaworks:scrypt加密庫(kù), 它包含的lib/x86_64/darwin/libscrypt.dylib文件,會(huì)導(dǎo)致在進(jìn)行Android App Bundle 編譯時(shí)會(huì)出現(xiàn)錯(cuò)誤(好像也會(huì)導(dǎo)致某些機(jī)型沒(méi)法安裝),解決辦法是在 build.gradle 加入一下語(yǔ)句,把這個(gè)文件在打包時(shí)排除掉。
packagingOptions {exclude "lib/x86_64/darwin/libscrypt.dylib"}
這是目前錢包客戶端,最常見的一種為用戶常見賬號(hào)的方式,這里會(huì)包含一下幾個(gè)核心步驟:
生成一個(gè)隨機(jī)數(shù)種子;
通過(guò)隨機(jī)數(shù)種子得到助記詞;
通過(guò) 種子 + 路徑 派生生成私鑰;
使用KeyStore保存私鑰;
私鑰推倒出賬號(hào)地址。
大家可以在再次閱讀分層錢包,理解為何這么做的原因。
理解了上面幾點(diǎn),那么代碼就容易明白了,代碼在代碼庫(kù)中的app/src/pro/upchain/wallet/utils/ETHWalletUtils.java中,關(guān)鍵代碼邏輯如下:
// 創(chuàng)建錢包對(duì)象入口函數(shù) public static ETHWallet generateMnemonic(String walletName, String pwd) { String[] pathArray = "m/44"/60"/0"/0/0".split("/"); long creationTimeSeconds = System.currentTimeMillis() / 1000; SecureRandom secureRandom = SecureRandomUtils.secureRandom(); DeterministicSeed ds = new DeterministicSeed(secureRandom, 128, "", creationTimeSeconds); return generateWalletByMnemonic(walletName, ds, pathArray, pwd); } /** * @param walletName 錢包名稱 * @param ds 助記詞加密種子 * @param pathArray 助記詞標(biāo)準(zhǔn) * @param pwd 密碼 * @return */ @Nullable public static ETHWallet generateWalletByMnemonic(String walletName, DeterministicSeed ds, String[] pathArray, String pwd) { //種子 byte[] seedBytes = ds.getSeedBytes(); //助記詞 Listmnemonic = ds.getMnemonicCode(); if (seedBytes == null) return null; // 衍生推倒key DeterministicKey dkKey = HDKeyDerivation.createMasterPrivateKey(seedBytes); for (int i = 1; i < pathArray.length; i++) { ChildNumber childNumber; if (pathArray[i].endsWith(""")) { int number = Integer.parseInt(pathArray[i].substring(0, pathArray[i].length() - 1)); childNumber = new ChildNumber(number, true); } else { int number = Integer.parseInt(pathArray[i]); childNumber = new ChildNumber(number, false); } dkKey = HDKeyDerivation.deriveChildKey(dkKey, childNumber); } ECKeyPair keyPair = ECKeyPair.create(dkKey.getPrivKeyBytes()); ETHWallet ethWallet = generateWallet(walletName, pwd, keyPair); if (ethWallet != null) { ethWallet.setMnemonic(convertMnemonicList(mnemonic)); } return ethWallet; } @Nullable private static ETHWallet generateWallet(String walletName, String pwd, ECKeyPair ecKeyPair) { WalletFile keyStoreFile; try { keyStoreFile = Wallet.create(pwd, ecKeyPair, 1024, 1); // WalletUtils. .generateNewWalletFile(); } catch (Exception e) { e.printStackTrace(); return null; } BigInteger publicKey = ecKeyPair.getPublicKey(); String s = publicKey.toString(); String wallet_dir = AppFilePath.Wallet_DIR; String keystorePath = "keystore_" + walletName + ".json"; File destination = new File(wallet_dir, "keystore_" + walletName + ".json"); //目錄不存在則創(chuàng)建目錄,創(chuàng)建不了則報(bào)錯(cuò) if (!createParentDir(destination)) { return null; } try { objectMapper.writeValue(destination, keyStoreFile); } catch (IOException e) { e.printStackTrace(); return null; } ETHWallet ethWallet = new ETHWallet(); ethWallet.setName(walletName); ethWallet.setAddress(Keys.toChecksumAddress(keyStoreFile.getAddress())); ethWallet.setKeystorePath(destination.getAbsolutePath()); ethWallet.setPassword(Md5Utils.md5(pwd)); return ethWallet; }
上述代碼中,generateMnemonic()是入口函數(shù),最終返回的是一個(gè)ETHWallet 自定義的錢包實(shí)體類,一個(gè)實(shí)例就對(duì)應(yīng)一個(gè)錢包,ETHWallet保存了錢包相關(guān)的屬性,后面會(huì)詳細(xì)介紹,如果對(duì)它序列化保存錢包賬號(hào)及多個(gè)錢包賬號(hào)管理。
幾個(gè)注意事項(xiàng)關(guān)于助記詞及私鑰的保存,有幾點(diǎn)要特別注意,否則有可能和其他錢包無(wú)法兼容或?qū)е滤借€泄漏。
這部分作為訂閱者福利,發(fā)表在我的小專欄,趁還未漲價(jià),趕緊訂閱吧,超值的!
參考文檔web3j API 文檔
bitcoinj 介紹及文檔
加入知識(shí)星球,和一群優(yōu)秀的區(qū)塊鏈從業(yè)者一起學(xué)習(xí)。
深入淺出區(qū)塊鏈 - 系統(tǒng)學(xué)習(xí)區(qū)塊鏈,打造最好的區(qū)塊鏈技術(shù)博客。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/102603.html
摘要:本文首發(fā)于深入淺出區(qū)塊鏈社區(qū)原文鏈接以太坊安卓錢包系列導(dǎo)入賬號(hào)及賬號(hào)管理原文已更新,請(qǐng)讀者前往原文閱讀這是如何開發(fā)一款以太坊安卓錢包系列第篇,如何導(dǎo)入賬號(hào)。提示大家閱讀本文時(shí),最好把代碼庫(kù)克隆到本地對(duì)照閱讀。 本文首發(fā)于深入淺出區(qū)塊鏈社區(qū)原文鏈接:以太坊(安卓)錢包系列2 - 導(dǎo)入賬號(hào)及賬號(hào)管理原文已更新,請(qǐng)讀者前往原文閱讀 這是如何開發(fā)一款以太坊(安卓)錢包系列第2篇,如何導(dǎo)入賬號(hào)。...
摘要:本文首發(fā)于深入淺出區(qū)塊鏈社區(qū)原文鏈接以太坊安卓錢包系列通過(guò)助記詞創(chuàng)建賬號(hào)原文已更新,請(qǐng)讀者前往原文閱讀上周我開源了一款錢包,反映很好,一周時(shí)間不到已經(jīng)快到。的功能和類似,它是比特幣協(xié)議的實(shí)現(xiàn),他實(shí)現(xiàn)了及相關(guān)協(xié)議。 本文首發(fā)于深入淺出區(qū)塊鏈社區(qū)原文鏈接:以太坊(安卓)錢包系列1 - 通過(guò)助記詞創(chuàng)建賬號(hào)原文已更新,請(qǐng)讀者前往原文閱讀 上周我開源了一款錢包,反映很好,一周時(shí)間不到已經(jīng)快到10...
摘要:錢包功能一個(gè)錢包通常主要包含的功能有賬號(hào)管理主要是私鑰的管理創(chuàng)建賬號(hào)賬號(hào)導(dǎo)入導(dǎo)出賬號(hào)信息展示如以太幣余額代幣余額。 本文首發(fā)于深入淺出區(qū)塊鏈社區(qū)原文鏈接:[使用 ethers.js 開發(fā)以太坊 Web 錢包 1 - 創(chuàng)建錢包賬號(hào))](https://learnblockchain.cn/20...,請(qǐng)讀者前往原文閱讀 以太坊去中心化網(wǎng)頁(yè)錢包開發(fā)系列,將從零開始開發(fā)出一個(gè)可以實(shí)際使用的錢...
摘要:引言給迷失在如何學(xué)習(xí)區(qū)塊鏈技術(shù)的同學(xué)一個(gè)指引,區(qū)塊鏈技術(shù)是隨比特幣誕生,因此要搞明白區(qū)塊鏈技術(shù),應(yīng)該先了解下比特幣。但區(qū)塊鏈技術(shù)不單應(yīng)用于比特幣,還有非常多的現(xiàn)實(shí)應(yīng)用場(chǎng)景,想做區(qū)塊鏈應(yīng)用開發(fā),可進(jìn)一步閱讀以太坊系列。 本文始發(fā)于深入淺出區(qū)塊鏈社區(qū), 原文:區(qū)塊鏈技術(shù)學(xué)習(xí)指引 原文已更新,請(qǐng)讀者前往原文閱讀 本章的文章越來(lái)越多,本文是一個(gè)索引帖,方便找到自己感興趣的文章,你也可以使用左側(cè)...
摘要:本文首發(fā)于深入淺出區(qū)塊鏈社區(qū)原文鏈接理解開發(fā)錢包涉及的原文已更新,請(qǐng)讀者前往原文閱讀如果你還在被錢包搞的一頭霧水,來(lái)看看這邊文章吧。所以我們要開發(fā)以太坊錢包同樣需要對(duì)比特幣的錢包提案有所了解。 本文首發(fā)于深入淺出區(qū)塊鏈社區(qū)原文鏈接:理解開發(fā)HD錢包涉及的BIP32、BIP44、BIP39原文已更新,請(qǐng)讀者前往原文閱讀 如果你還在被HD錢包、BIP32、BIP44、BIP39搞的一頭霧水...
閱讀 1884·2021-09-23 11:21
閱讀 726·2019-08-30 15:55
閱讀 867·2019-08-29 15:40
閱讀 584·2019-08-29 12:56
閱讀 3196·2019-08-26 12:00
閱讀 3591·2019-08-23 18:24
閱讀 2282·2019-08-23 17:08
閱讀 1669·2019-08-23 17:03