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