github.com/neatio-net/neatio@v1.7.3-0.20231114194659-f4d7a2226baa/chain/accounts/hd.go (about)

     1  package accounts
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"math"
     7  	"math/big"
     8  	"strings"
     9  )
    10  
    11  var DefaultRootDerivationPath = DerivationPath{0x80000000 + 44, 0x80000000 + 60, 0x80000000 + 0, 0}
    12  
    13  var DefaultBaseDerivationPath = DerivationPath{0x80000000 + 44, 0x80000000 + 60, 0x80000000 + 0, 0, 0}
    14  
    15  var DefaultLedgerBaseDerivationPath = DerivationPath{0x80000000 + 44, 0x80000000 + 60, 0x80000000 + 0, 0}
    16  
    17  type DerivationPath []uint32
    18  
    19  func ParseDerivationPath(path string) (DerivationPath, error) {
    20  	var result DerivationPath
    21  
    22  	components := strings.Split(path, "/")
    23  	switch {
    24  	case len(components) == 0:
    25  		return nil, errors.New("empty derivation path")
    26  
    27  	case strings.TrimSpace(components[0]) == "":
    28  		return nil, errors.New("ambiguous path: use 'm/' prefix for absolute paths, or no leading '/' for relative ones")
    29  
    30  	case strings.TrimSpace(components[0]) == "m":
    31  		components = components[1:]
    32  
    33  	default:
    34  		result = append(result, DefaultRootDerivationPath...)
    35  	}
    36  
    37  	if len(components) == 0 {
    38  		return nil, errors.New("empty derivation path")
    39  	}
    40  	for _, component := range components {
    41  
    42  		component = strings.TrimSpace(component)
    43  		var value uint32
    44  
    45  		if strings.HasSuffix(component, "'") {
    46  			value = 0x80000000
    47  			component = strings.TrimSpace(strings.TrimSuffix(component, "'"))
    48  		}
    49  
    50  		bigval, ok := new(big.Int).SetString(component, 0)
    51  		if !ok {
    52  			return nil, fmt.Errorf("invalid component: %s", component)
    53  		}
    54  		max := math.MaxUint32 - value
    55  		if bigval.Sign() < 0 || bigval.Cmp(big.NewInt(int64(max))) > 0 {
    56  			if value == 0 {
    57  				return nil, fmt.Errorf("component %v out of allowed range [0, %d]", bigval, max)
    58  			}
    59  			return nil, fmt.Errorf("component %v out of allowed hardened range [0, %d]", bigval, max)
    60  		}
    61  		value += uint32(bigval.Uint64())
    62  
    63  		result = append(result, value)
    64  	}
    65  	return result, nil
    66  }
    67  
    68  func (path DerivationPath) String() string {
    69  	result := "m"
    70  	for _, component := range path {
    71  		var hardened bool
    72  		if component >= 0x80000000 {
    73  			component -= 0x80000000
    74  			hardened = true
    75  		}
    76  		result = fmt.Sprintf("%s/%d", result, component)
    77  		if hardened {
    78  			result += "'"
    79  		}
    80  	}
    81  	return result
    82  }