區塊鏈錢包之BTC錢包地址生成

愛去玩發表於2018-03-25

前面說了一些關於區塊鏈生成錢包地址的方法說了一下, 那麼該如何用程式碼去生成錢包地址呢? 之前我在做錢包的時候, 搜了很多資料, 很少有寫如何去生成錢包地址, 當然英文資料也不多. 最後還是去gayhub裡面看了開源錢包, 才搞清楚了一些方法. 我們這裡使用的是bitcoinj來生成. 一般都是分幾個步驟: 生成助記詞, 根據助記詞生成地址

配置環境

首先我們這裡使用的Android studio 3.0, 直接在app/build.gradle裡面新增依賴

implementation group: 'org.bitcoinj', name: 'bitcoinj-core', version: '0.14.6'
複製程式碼

先填坑, 生成助記詞需要使用到MnemonicUtils這個類, 但是有坑, 載入助記詞列表檔案的方式在Android上面根本不行, 會導致Crash

 private static List<String> populateWordList() {
        URL url = Thread.currentThread().getContextClassLoader()
                .getResource("en-mnemonic-word-list.txt");
        try {
            return readAllLines(url.toURI().getSchemeSpecificPart());
        } catch (Exception e) {
            return Collections.emptyList();
        }
    }
複製程式碼

懂的人都看出來了吧, 這是java的載入資源方式, 但是安卓需要做平臺適配. 我們把en-mnemonic-word-list.txt這個檔案放到assets之下, 然後用符合安卓的姿勢載入. Good, 沒問題了

private fun populateWordList(): List<String> {
        try {
            val fis = App.instance.assets?.open("en-mnemonic-word-list.txt")
            return readAllLines(fis!!)
        } catch (e: IOException) {
            e.printStackTrace()
        }

        return emptyList()
    }
複製程式碼

生成助記詞

生成助記詞需要使用到MnemonicUtils這個類, 要生成助記詞很簡單, 需要如下程式碼生成助記詞, 助記詞的格式就是12個單詞

//average green proud remember advance trick estate oblige trouble when cube person
private val secureRandom = MySecureRandomUtils.secureRandom()
fun makeMnemonic(): String {
        val initialEntropy = ByteArray(16)
        secureRandom.nextBytes(initialEntropy)
        return MyMnemonicUtils.generateMnemonic(initialEntropy)
    }
複製程式碼

生成BTC地址

先根據生成的助記詞, 生成一些列的種, 運用了 BIP32確定性錢包演算法(deterministic wallet algorithm)

private fun createBTCWalletFromWords(words: String): TianWallet {
        //把助記詞切割成陣列
        val wordsList = Arrays.asList(*words.split("\\s+".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray())
        val deterministicSeed = DeterministicSeed(wordsList, null, "", 0)
        val deterministicKeyChain = DeterministicKeyChain.builder().seed(deterministicSeed).build()
        //這裡運用了BIP44裡面提到的演算法, 44'是固定的, 後面的一個0'代表的是幣種BTC
        var privKeyBTC = deterministicKeyChain.getKeyByPath(parsePath("m/44'/0'/0'/0/0"), true).privKey
        //如果是除錯模式, 第二個字串應該填1'
        if (BuildConfig.DEBUG) {
            privKeyBTC = deterministicKeyChain.getKeyByPath(parsePath("m/44'/1'/0'/0/0"), true).privKey
        }
        
        val ecKey = ECKey.fromPrivate(privKeyBTC)
        val publickey = Numeric.toHexStringNoPrefixZeroPadded(BigInteger(ecKey.pubKey), 66)
        //正式環境應該是主網引數
        var privateKey = ecKey.getPrivateKeyEncoded(MainNetParams.get()).toString()
        //如果是測試環境, 應該呼叫測試網引數
        if (BuildConfig.DEBUG) {
            privateKey = ecKey.getPrivateKeyEncoded(TestNet3Params.get()).toString()
            return TianWallet(ecKey.toAddress(TestNet3Params.get()).toString(), publickey, privateKey, words)
        }
        return TianWallet(ecKey.toAddress(MainNetParams.get()).toString(), publickey, privateKey, words)
    }
複製程式碼

下一篇文章我將介紹一下ETH的地址生成方式. 更多教程請訪問愛去玩的個人專欄

相關文章