github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/accounts/hd.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 12:09:26</date>
    10  //</624342584537387008>
    11  
    12  
    13  package accounts
    14  
    15  import (
    16  	"errors"
    17  	"fmt"
    18  	"math"
    19  	"math/big"
    20  	"strings"
    21  )
    22  
    23  //DefaultRootDerivationPath是自定义派生终结点的根路径
    24  //被追加。因此,第一个帐户将位于m/44'/60'/0'/0,第二个帐户将位于
    25  //在m/44'/60'/0'/1等处。
    26  var DefaultRootDerivationPath = DerivationPath{0x80000000 + 44, 0x80000000 + 60, 0x80000000 + 0, 0}
    27  
    28  //DefaultBaseDerivationPath是自定义派生终结点的基本路径
    29  //是递增的。因此,第一个帐户将位于m/44'/60'/0'/0,第二个帐户将位于
    30  //在m/44'/60'/0'/1等处。
    31  var DefaultBaseDerivationPath = DerivationPath{0x80000000 + 44, 0x80000000 + 60, 0x80000000 + 0, 0, 0}
    32  
    33  //DefaultLedgerBasederivationPath是自定义派生终结点的基本路径
    34  //是递增的。因此,第一个帐户将位于m/44'/60'/0'/0,第二个帐户将位于
    35  //在m/44'/60'/0'/1等处。
    36  var DefaultLedgerBaseDerivationPath = DerivationPath{0x80000000 + 44, 0x80000000 + 60, 0x80000000 + 0, 0}
    37  
    38  //派生路径表示层次结构的计算机友好版本
    39  //确定的钱包帐户派生路径。
    40  //
    41  //BIP-32规范https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki
    42  //定义派生路径的形式:
    43  //
    44  //M/用途/硬币类型/账户/更改/地址索引
    45  //
    46  //BIP-44规范https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki
    47  //定义加密货币的“用途”为44'(或0x800002c),以及
    48  //slip-44 https://github.com/satoshilabs/slip/blob/master/slip-0044.md分配
    49  //以太坊的“硬币”类型为“60”(或0x8000003c)。
    50  //
    51  //根据规范,以太坊的根路径为m/44'/60'/0'/0
    52  //来自https://github.com/ethereum/eips/issues/84,尽管它不是石头做的
    53  //然而,帐户应该增加最后一个组件还是
    54  //那。我们将使用更简单的方法来增加最后一个组件。
    55  type DerivationPath []uint32
    56  
    57  //ParseDerivationPath将用户指定的派生路径字符串转换为
    58  //内部二进制表示。
    59  //
    60  //完整的派生路径需要以“m/”前缀开头,相对派生
    61  //路径(将附加到默认根路径)不能有前缀
    62  //在第一个元素前面。空白被忽略。
    63  func ParseDerivationPath(path string) (DerivationPath, error) {
    64  	var result DerivationPath
    65  
    66  //处理绝对或相对路径
    67  	components := strings.Split(path, "/")
    68  	switch {
    69  	case len(components) == 0:
    70  		return nil, errors.New("empty derivation path")
    71  
    72  	case strings.TrimSpace(components[0]) == "":
    73  		return nil, errors.New("ambiguous path: use 'm/' prefix for absolute paths, or no leading '/' for relative ones")
    74  
    75  	case strings.TrimSpace(components[0]) == "m":
    76  		components = components[1:]
    77  
    78  	default:
    79  		result = append(result, DefaultRootDerivationPath...)
    80  	}
    81  //其余所有组件都是相对的,逐个附加
    82  	if len(components) == 0 {
    83  return nil, errors.New("empty derivation path") //空的相对路径
    84  	}
    85  	for _, component := range components {
    86  //忽略任何用户添加的空白
    87  		component = strings.TrimSpace(component)
    88  		var value uint32
    89  
    90  //处理硬化路径
    91  		if strings.HasSuffix(component, "'") {
    92  			value = 0x80000000
    93  			component = strings.TrimSpace(strings.TrimSuffix(component, "'"))
    94  		}
    95  //处理非硬化部件
    96  		bigval, ok := new(big.Int).SetString(component, 0)
    97  		if !ok {
    98  			return nil, fmt.Errorf("invalid component: %s", component)
    99  		}
   100  		max := math.MaxUint32 - value
   101  		if bigval.Sign() < 0 || bigval.Cmp(big.NewInt(int64(max))) > 0 {
   102  			if value == 0 {
   103  				return nil, fmt.Errorf("component %v out of allowed range [0, %d]", bigval, max)
   104  			}
   105  			return nil, fmt.Errorf("component %v out of allowed hardened range [0, %d]", bigval, max)
   106  		}
   107  		value += uint32(bigval.Uint64())
   108  
   109  //追加并重复
   110  		result = append(result, value)
   111  	}
   112  	return result, nil
   113  }
   114  
   115  //字符串实现Stringer接口,转换二进制派生路径
   116  //它的规范表示。
   117  func (path DerivationPath) String() string {
   118  	result := "m"
   119  	for _, component := range path {
   120  		var hardened bool
   121  		if component >= 0x80000000 {
   122  			component -= 0x80000000
   123  			hardened = true
   124  		}
   125  		result = fmt.Sprintf("%s/%d", result, component)
   126  		if hardened {
   127  			result += "'"
   128  		}
   129  	}
   130  	return result
   131  }
   132