Electrum研究系列【代码结构和助记词生成】

chaimyu(58)
Published in
#cn
Words
848
Reading
4 min
9y
Listen to this post
~6 min

此文档为个人整理学习使用,部分内容来源于网络,也期待能给你带来益处!如果转载,请保留原始链接!
https://steemit.com/@chaimyu

官方文档

http://docs.electrum.org/en/latest/index.html

官方文档肯定是最重要的内容,最左边列表里说的基本就是Electrum的优点和特色了,里面有些内容肯定对代码理解有用,有时间再好好看一下!


代码结构

  • electrum-env

查看文件内容,原来electrum就是用virtualenv来管理的,因为在安装过程中也是同样处理方式,这个文件现在可以直接执行并启动程序了!

里面有一句话说明需要自己装pyqt,却不知道这句话花了很多时间才完成!

# python-qt and its dependencies will still need to be installed with
# your package manager.
  • setup.py

文档里说明用法,用法:
python setup.py sdist --format=zip,gztar

  • gui

顾名思义,这肯定是界面相关处理了

  • icons

顾名思义,图标资源文件了

  • lib

这应该是个重要逻辑处理的目录了,里面有一些看起来重要的文件,如bitcoin.py、blockchain.py、network.py等

  • plugins

插件目录,里面有README说明了,里面有一些子目录,应该是每个插件

* The plugin system of Electrum is designed to allow the development
   of new features without increasing the core code of Electrum.
  • scripts

看起来是一些比较简单的代码文件,很多print调用,应该是测试使用

代码解析

从代码结构中可以看出重要的目录是lib,那开始从其中浏览一些代码,并了解主要是做什么的!

  • mnemonic.py

主要是seed相关处理,类Mnemonic中有生成seed,如下:

    def make_seed(self, seed_type='standard', num_bits=132, custom_entropy=1):
        prefix = version.seed_prefix(seed_type)
        # increase num_bits in order to obtain a uniform distibution for the last word
        bpw = math.log(len(self.wordlist), 2)
        num_bits = int(math.ceil(num_bits/bpw) * bpw)
        # handle custom entropy; make sure we add at least 16 bits
        n_custom = int(math.ceil(math.log(custom_entropy, 2)))
        n = max(16, num_bits - n_custom)
        print_error("make_seed", prefix, "adding %d bits"%n)
        my_entropy = 1
        while my_entropy < pow(2, n - bpw):
            # try again if seed would not contain enough words
            my_entropy = ecdsa.util.randrange(pow(2, n))
        nonce = 0
        while True:
            nonce += 1
            i = custom_entropy * (my_entropy + nonce)
            seed = self.mnemonic_encode(i)
            assert i == self.mnemonic_decode(seed)
            if is_old_seed(seed):
                continue
            if is_new_seed(seed, prefix):
                break
        print_error('%d words'%len(seed.split()))
        return seed

可以通过命令行调用到,执行如下:

(env) Chaim:electrum Chaim$ electrum make_seed --nbits 125
proof banner square actress tissue unfair margin merit ankle page team august
(env) Chaim:electrum Chaim$ electrum make_seed --nbits 125
list degree small teach sweet number thought over during swarm sense depth

可以在electrum目录下建立测试脚本mnemonic_test.py

#!/usr/bin/env python3

from lib.mnemonic import Mnemonic

print(Mnemonic('None').make_seed('standard', 132, 1))

print("\n")

执行如下:

(env) Chaim:electrum Chaim$ python mnemonic_test.py 
language None
wordlist has 2048 words
make_seed 01 adding 132 bits
12 words
segment gold aspect seed artist raven toilet tourist tape oyster card sea

如果要生成中文助记词(seed)的话,如下调用:

print(Mnemonic('zh').make_seed('standard', 132, 1))

执行如下:

(env) Chaim:electrum Chaim$ python mnemonic_test.py 
language zh
wordlist has 2048 words
make_seed 01 adding 132 bits
12 words
举 市 阻 输 货 班 呵 曰 及 欲 雪 皆

支持的语言在i18n.py文件中,用前面的两个字母即可,但是现在真正支持的只有“en、es、zh、ja、pt”,定义在wordlist目录下,各文件里面包含支持语言的一些短语


  • version.py

定义了几种钱包类型前缀,钱包类型如下:

    if seed_type == 'standard':
        return SEED_PREFIX
    elif seed_type == 'segwit':
        return SEED_PREFIX_SW
    elif seed_type == '2fa':
        return SEED_PREFIX_2FA

  • wordlist

支持语言的短语文件,每个文件包括2048个短语,用来生成助记词(seed)

文件内容就是bip39指定的
bip39 Wordlists

支持bip39的钱包生成的助记词在Electrum中可以使用,但是Electrum生成的助记词并不兼容bip39,Electrum认为bip39的安全性还不够好,它增加了版本号


make_seed函数有代码对短语数量做处理,如下:

    bpw = math.log(len(self.wordlist), 2)

此处会得到bpw=11

判断随机数是否能生成足够的助记词,如下:

        while my_entropy < pow(2, n - bpw):
            # try again if seed would not contain enough words
            my_entropy = ecdsa.util.randrange(pow(2, n))

根据随机数和短语表,生成助记词在 mnemonic_encode()中,如下:

    def mnemonic_encode(self, i):
        n = len(self.wordlist)
        words = []
        while i:
            x = i%n
            i = i//n
            print("x:" + str(x) + ",i:" + str(i))
            words.append(self.wordlist[x])
        return ' '.join(words)

以下循环生成助记词,只到是新的助记词才退出循环,如下:

        nonce = 0
        while True:
            nonce += 1
            i = custom_entropy * (my_entropy + nonce)
            seed = self.mnemonic_encode(i)
            assert i == self.mnemonic_decode(seed)
            if is_old_seed(seed):
                continue
            if is_new_seed(seed, prefix):
                break

以上代码会用到bitcoin.py中的两个函数,is_old_seed()和is_new_seed()

更多助记词生成方式描述参见 bip39

Mnemonic Code Converter

概念

  • segwit

英文是Segregated Witness,中文叫隔离见证,能够解决比特币扩容问题。

https://www.zhihu.com/question/52644297/answer/162827401
http://www.360doc.com/content/17/0423/17/34265476_647899819.shtml

  • 闪电网络(Lightning Network)

一种链外交易,用来处理金额较少的交易。

参考

https://steemit.com/programming/@profitgenerator/electrum-bitcoin-wallet-code-audit

http://blog.csdn.net/pony_maggie/article/details/76178228


Electrum研究系列【代码结构和助记词生成】 | Ecency