github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/accounts/hd.go (about)

     1  
     2  //此源码被清华学神尹成大魔王专业翻译分析并修改
     3  //尹成QQ77025077
     4  //尹成微信18510341407
     5  //尹成所在QQ群721929980
     6  //尹成邮箱 yinc13@mails.tsinghua.edu.cn
     7  //尹成毕业于清华大学,微软区块链领域全球最有价值专家
     8  //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620
     9  //版权所有2017 Go Ethereum作者
    10  //此文件是Go以太坊库的一部分。
    11  //
    12  //Go-Ethereum库是免费软件:您可以重新分发它和/或修改
    13  //根据GNU发布的较低通用公共许可证的条款
    14  //自由软件基金会,或者许可证的第3版,或者
    15  //(由您选择)任何更高版本。
    16  //
    17  //Go以太坊图书馆的发行目的是希望它会有用,
    18  //但没有任何保证;甚至没有
    19  //适销性或特定用途的适用性。见
    20  //GNU较低的通用公共许可证,了解更多详细信息。
    21  //
    22  //你应该收到一份GNU较低级别的公共许可证副本
    23  //以及Go以太坊图书馆。如果没有,请参见<http://www.gnu.org/licenses/>。
    24  
    25  package accounts
    26  
    27  import (
    28  	"errors"
    29  	"fmt"
    30  	"math"
    31  	"math/big"
    32  	"strings"
    33  )
    34  
    35  //DefaultRootDerivationPath是自定义派生终结点的根路径
    36  //被追加。因此,第一个帐户将位于m/44'/60'/0'/0,第二个帐户将位于
    37  //在m/44'/60'/0'/1等处。
    38  var DefaultRootDerivationPath = DerivationPath{0x80000000 + 44, 0x80000000 + 60, 0x80000000 + 0, 0}
    39  
    40  //DefaultBaseDerivationPath是自定义派生终结点的基本路径
    41  //是递增的。因此,第一个帐户将位于m/44'/60'/0'/0,第二个帐户将位于
    42  //在m/44'/60'/0'/1等处。
    43  var DefaultBaseDerivationPath = DerivationPath{0x80000000 + 44, 0x80000000 + 60, 0x80000000 + 0, 0, 0}
    44  
    45  //DefaultLedgerBasederivationPath是自定义派生终结点的基本路径
    46  //是递增的。因此,第一个帐户将位于m/44'/60'/0'/0,第二个帐户将位于
    47  //在m/44'/60'/0'/1等处。
    48  var DefaultLedgerBaseDerivationPath = DerivationPath{0x80000000 + 44, 0x80000000 + 60, 0x80000000 + 0, 0}
    49  
    50  //派生路径表示层次结构的计算机友好版本
    51  //确定的钱包帐户派生路径。
    52  //
    53  //BIP-32规范https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki
    54  //定义派生路径的形式:
    55  //
    56  //M/用途/硬币类型/账户/更改/地址索引
    57  //
    58  //BIP-44规范https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki
    59  //定义加密货币的“用途”为44'(或0x800002c),以及
    60  //slip-44 https://github.com/satoshilabs/slip/blob/master/slip-0044.md分配
    61  //以太坊的“硬币”类型为“60”(或0x8000003c)。
    62  //
    63  //根据规范,以太坊的根路径为m/44'/60'/0'/0
    64  //来自https://github.com/ethereum/eips/issues/84,尽管它不是石头做的
    65  //然而,帐户应该增加最后一个组件还是
    66  //那。我们将使用更简单的方法来增加最后一个组件。
    67  type DerivationPath []uint32
    68  
    69  //ParseDerivationPath将用户指定的派生路径字符串转换为
    70  //内部二进制表示。
    71  //
    72  //完整的派生路径需要以“m/”前缀开头,相对派生
    73  //路径(将附加到默认根路径)不能有前缀
    74  //在第一个元素前面。空白被忽略。
    75  func ParseDerivationPath(path string) (DerivationPath, error) {
    76  	var result DerivationPath
    77  
    78  //处理绝对或相对路径
    79  	components := strings.Split(path, "/")
    80  	switch {
    81  	case len(components) == 0:
    82  		return nil, errors.New("empty derivation path")
    83  
    84  	case strings.TrimSpace(components[0]) == "":
    85  		return nil, errors.New("ambiguous path: use 'm/' prefix for absolute paths, or no leading '/' for relative ones")
    86  
    87  	case strings.TrimSpace(components[0]) == "m":
    88  		components = components[1:]
    89  
    90  	default:
    91  		result = append(result, DefaultRootDerivationPath...)
    92  	}
    93  //其余所有组件都是相对的,逐个附加
    94  	if len(components) == 0 {
    95  return nil, errors.New("empty derivation path") //空的相对路径
    96  	}
    97  	for _, component := range components {
    98  //忽略任何用户添加的空白
    99  		component = strings.TrimSpace(component)
   100  		var value uint32
   101  
   102  //处理硬化路径
   103  		if strings.HasSuffix(component, "'") {
   104  			value = 0x80000000
   105  			component = strings.TrimSpace(strings.TrimSuffix(component, "'"))
   106  		}
   107  //处理非硬化部件
   108  		bigval, ok := new(big.Int).SetString(component, 0)
   109  		if !ok {
   110  			return nil, fmt.Errorf("invalid component: %s", component)
   111  		}
   112  		max := math.MaxUint32 - value
   113  		if bigval.Sign() < 0 || bigval.Cmp(big.NewInt(int64(max))) > 0 {
   114  			if value == 0 {
   115  				return nil, fmt.Errorf("component %v out of allowed range [0, %d]", bigval, max)
   116  			}
   117  			return nil, fmt.Errorf("component %v out of allowed hardened range [0, %d]", bigval, max)
   118  		}
   119  		value += uint32(bigval.Uint64())
   120  
   121  //追加并重复
   122  		result = append(result, value)
   123  	}
   124  	return result, nil
   125  }
   126  
   127  //字符串实现Stringer接口,转换二进制派生路径
   128  //它的规范表示。
   129  func (path DerivationPath) String() string {
   130  	result := "m"
   131  	for _, component := range path {
   132  		var hardened bool
   133  		if component >= 0x80000000 {
   134  			component -= 0x80000000
   135  			hardened = true
   136  		}
   137  		result = fmt.Sprintf("%s/%d", result, component)
   138  		if hardened {
   139  			result += "'"
   140  		}
   141  	}
   142  	return result
   143  }