-
Notifications
You must be signed in to change notification settings - Fork 0
/
extendedsecretkey.go
128 lines (110 loc) · 3.72 KB
/
extendedsecretkey.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package ergo
/*
#include "ergo.h"
*/
import "C"
import (
"errors"
"runtime"
"unsafe"
)
type ExtendedSecretKey interface {
// Child derives a new ExtendedSecretKey from the provided index
// The index is in the form of soft or hardened indices
// For example: 4 or 4' respectively
Child(index string) (ExtendedSecretKey, error)
// Path returns the DerivationPath of the ExtendedSecretKey
Path() DerivationPath
// SecretKey returns the SecretKey of the ExtendedSecretKey
SecretKey() SecretKey
// ExtendedPublicKey returns the ExtendedPublicKey associated with the ExtendedSecretKey
ExtendedPublicKey() ExtendedPublicKey
// Derive derives a new ExtendedSecretKey from the supplied DerivationPath
Derive(derivationPath DerivationPath) (ExtendedSecretKey, error)
}
type extendedSecretKey struct {
p C.ExtSecretKeyPtr
}
func newExtendedSecretKey(e *extendedSecretKey) ExtendedSecretKey {
runtime.SetFinalizer(e, finalizeExtendedSecretKey)
return e
}
// NewExtendedSecretKey creates a new ExtendedSecretKey from secretKeyBytes, chainCode and derivationPath
// secretKeyBytes needs to be the length of 32 bytes
// chainCode needs to be the length of 32 bytes
func NewExtendedSecretKey(secretKeyBytes []byte, chainCode []byte, derivationPath DerivationPath) (ExtendedSecretKey, error) {
if len(secretKeyBytes) != 32 {
return nil, errors.New("secretKeyBytes must be 32 bytes")
}
if len(chainCode) != 32 {
return nil, errors.New("chainCode must be 32 bytes")
}
secretKeyByteData := C.CBytes(secretKeyBytes)
defer C.free(unsafe.Pointer(secretKeyByteData))
chainCodeByteData := C.CBytes(chainCode)
defer C.free(unsafe.Pointer(chainCodeByteData))
var p C.ExtSecretKeyPtr
errPtr := C.ergo_lib_ext_secret_key_new((*C.uchar)(secretKeyByteData), (*C.uchar)(chainCodeByteData), derivationPath.pointer(), &p)
err := newError(errPtr)
if err.isError() {
return nil, err.error()
}
e := &extendedSecretKey{p: p}
return newExtendedSecretKey(e), nil
}
// DeriveMaster derives root ExtendedSecretKey from seed bytes
func DeriveMaster(seed []byte) (ExtendedSecretKey, error) {
seedByteData := C.CBytes(seed)
defer C.free(unsafe.Pointer(seedByteData))
var p C.ExtSecretKeyPtr
errPtr := C.ergo_lib_ext_secret_key_derive_master((*C.uchar)(seedByteData), &p)
err := newError(errPtr)
if err.isError() {
return nil, err.error()
}
es := &extendedSecretKey{p: p}
return newExtendedSecretKey(es), nil
}
func (e *extendedSecretKey) Child(index string) (ExtendedSecretKey, error) {
indexStr := C.CString(index)
defer C.free(unsafe.Pointer(indexStr))
var p C.ExtSecretKeyPtr
errPtr := C.ergo_lib_ext_secret_key_child(e.p, indexStr, &p)
err := newError(errPtr)
if err.isError() {
return nil, err.error()
}
es := &extendedSecretKey{p: p}
return newExtendedSecretKey(es), nil
}
func (e *extendedSecretKey) Path() DerivationPath {
var p C.DerivationPathPtr
C.ergo_lib_ext_secret_key_path(e.p, &p)
d := &derivationPath{p: p}
return newDerivationPath(d)
}
func (e *extendedSecretKey) SecretKey() SecretKey {
var p C.SecretKeyPtr
C.ergo_lib_ext_secret_key_get_secret_key(e.p, &p)
s := &secretKey{p: p}
return newSecretKey(s)
}
func (e *extendedSecretKey) ExtendedPublicKey() ExtendedPublicKey {
var p C.ExtPubKeyPtr
C.ergo_lib_ext_secret_key_public_key(e.p, &p)
ep := &extendedPublicKey{p: p}
return newExtendedPublicKey(ep)
}
func (e *extendedSecretKey) Derive(derivationPath DerivationPath) (ExtendedSecretKey, error) {
var p C.ExtSecretKeyPtr
errPtr := C.ergo_lib_ext_secret_key_derive(e.p, derivationPath.pointer(), &p)
err := newError(errPtr)
if err.isError() {
return nil, err.error()
}
es := &extendedSecretKey{p: p}
return newExtendedSecretKey(es), nil
}
func finalizeExtendedSecretKey(e *extendedSecretKey) {
C.ergo_lib_ext_secret_key_delete(e.p)
}