2019-10-01 12:22:30 -03:00

80 lines
1.8 KiB
Go

package libwallet
import (
"strconv"
"strings"
"github.com/pkg/errors"
)
type derivationIndex struct {
i uint32
hardened bool
name string
}
type derivationPath struct {
indexes []derivationIndex
}
const (
hardenedSymbol = "'"
)
// parseDerivationPath parses BIP32 paths
// The following paths are valid:
//
// "" (root key)
// "m" (root key)
// "/" (root key)
// "m/0'" (hardened child #0 of the root key)
// "/0'" (hardened child #0 of the root key)
// "0'" (hardened child #0 of the root key)
// "m/44'/1'/2'" (BIP44 testnet account #2)
// "/44'/1'/2'" (BIP44 testnet account #2)
// "44'/1'/2'" (BIP44 testnet account #2)
// "m/schema:1'" (Muun schema path)
//
// The following paths are invalid:
//
// "m / 0 / 1" (contains spaces)
// "m/b/c" (alphabetical characters instead of numerical indexes)
// "m/1.2^3" (contains illegal characters)
func parseDerivationPath(path string) (*derivationPath, error) {
if path == "m" || path == "/" || path == "" {
return &derivationPath{indexes: make([]derivationIndex, 0)}, nil
}
var indexes []derivationIndex
path = strings.TrimPrefix(path, "m")
path = strings.TrimPrefix(path, "/")
for _, chunk := range strings.Split(path, "/") {
hardened := false
indexText := chunk
if strings.HasSuffix(indexText, hardenedSymbol) {
hardened = true
indexText = strings.TrimSuffix(indexText, hardenedSymbol)
}
parts := strings.Split(indexText, ":")
if len(parts) > 2 {
return nil, errors.New("path is malformed: " + path)
}
var name string
if len(parts) == 2 {
name = parts[0]
}
index, err := strconv.ParseUint(parts[len(parts)-1], 10, 32)
if err != nil {
return nil, errors.New("path is malformed " + err.Error())
}
indexes = append(indexes, derivationIndex{i: uint32(index), hardened: hardened, name: name})
}
return &derivationPath{indexes: indexes}, nil
}