Skip to content

Commit 1619e0f

Browse files
committed
wallet/ledger: Fix BIP-44 path serialization
1 parent 968a561 commit 1619e0f

File tree

2 files changed

+134
-3
lines changed

2 files changed

+134
-3
lines changed

wallet/ledger/common.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,13 @@ func getSerializedBip44Path(path []uint32) ([]byte, error) {
4747
return nil, fmt.Errorf("path should contain 5 elements")
4848
}
4949

50-
// First three elements are hardened
51-
for index, element := range path[:3] {
50+
for index, element := range path {
5251
pos := index * 4
53-
value := element | 0x80000000 // Harden all components.
52+
value := element
53+
// First three elements are hardened
54+
if index < 3 {
55+
value |= 0x80000000
56+
}
5457
binary.LittleEndian.PutUint32(message[pos:], value)
5558
}
5659
return message, nil

wallet/ledger/common_test.go

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
package ledger
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/require"
7+
)
8+
9+
func TestGetSerializedPath(t *testing.T) {
10+
paths := []struct {
11+
path []uint32
12+
expected []byte
13+
valid bool
14+
}{
15+
{
16+
path: []uint32{44, 474, 0}, // adr8, index 0
17+
expected: []byte{44, 0, 0, 128, 218, 1, 0, 128, 0, 0, 0, 128},
18+
valid: true,
19+
},
20+
{
21+
path: []uint32{44, 474, 1}, // adr8, index 1
22+
expected: []byte{44, 0, 0, 128, 218, 1, 0, 128, 1, 0, 0, 128},
23+
valid: true,
24+
},
25+
{
26+
path: []uint32{44, 474, 0, 0, 0}, // legacy, index 0
27+
expected: []byte{44, 0, 0, 128, 218, 1, 0, 128, 0, 0, 0, 128, 0, 0, 0, 128, 0, 0, 0, 128},
28+
valid: true,
29+
},
30+
{
31+
path: []uint32{44, 474, 0, 0, 1}, // legacy, index 1
32+
expected: []byte{44, 0, 0, 128, 218, 1, 0, 128, 0, 0, 0, 128, 0, 0, 0, 128, 1, 0, 0, 128},
33+
valid: true,
34+
},
35+
{
36+
path: []uint32{}, // wrong length
37+
expected: []byte{},
38+
valid: false,
39+
},
40+
{
41+
path: []uint32{44}, // wrong length
42+
expected: []byte{},
43+
valid: false,
44+
},
45+
{
46+
path: []uint32{44, 474, 0, 0}, // wrong length
47+
expected: []byte{},
48+
valid: false,
49+
},
50+
{
51+
path: []uint32{44, 474, 0, 0, 0, 0}, // wrong length
52+
expected: []byte{},
53+
valid: false,
54+
},
55+
}
56+
57+
for _, p := range paths {
58+
result, err := getSerializedPath(p.path)
59+
if p.valid {
60+
require.Equal(t, p.expected, result)
61+
} else {
62+
require.Error(t, err)
63+
}
64+
}
65+
}
66+
67+
func TestGetSerializedBip44Path(t *testing.T) {
68+
paths := []struct {
69+
path []uint32
70+
expected []byte
71+
valid bool
72+
}{
73+
{
74+
path: []uint32{44, 60, 0, 0, 0}, // bip44, change 0, index 0
75+
expected: []byte{44, 0, 0, 128, 60, 0, 0, 128, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0, 0, 0},
76+
valid: true,
77+
},
78+
{
79+
path: []uint32{44, 60, 0, 0, 1}, // bip44, change 0, index 1
80+
expected: []byte{44, 0, 0, 128, 60, 0, 0, 128, 0, 0, 0, 128, 0, 0, 0, 0, 1, 0, 0, 0},
81+
valid: true,
82+
},
83+
{
84+
path: []uint32{44, 60, 0, 1, 0}, // bip44, change 1, index 0
85+
expected: []byte{44, 0, 0, 128, 60, 0, 0, 128, 0, 0, 0, 128, 1, 0, 0, 0, 0, 0, 0, 0},
86+
valid: true,
87+
},
88+
{
89+
path: []uint32{44, 60, 0, 1, 1}, // bip44, change 1, index 1
90+
expected: []byte{44, 0, 0, 128, 60, 0, 0, 128, 0, 0, 0, 128, 1, 0, 0, 0, 1, 0, 0, 0},
91+
valid: true,
92+
},
93+
{
94+
path: []uint32{}, // wrong length
95+
expected: []byte{},
96+
valid: false,
97+
},
98+
{
99+
path: []uint32{44}, // wrong length
100+
expected: []byte{},
101+
valid: false,
102+
},
103+
{
104+
path: []uint32{44, 60, 0}, // wrong length
105+
expected: []byte{},
106+
valid: false,
107+
},
108+
{
109+
path: []uint32{44, 60, 0, 0}, // wrong length
110+
expected: []byte{},
111+
valid: false,
112+
},
113+
{
114+
path: []uint32{44, 60, 0, 0, 0, 0}, // wrong length
115+
expected: []byte{},
116+
valid: false,
117+
},
118+
}
119+
120+
for _, p := range paths {
121+
result, err := getSerializedBip44Path(p.path)
122+
if p.valid {
123+
require.Equal(t, p.expected, result)
124+
} else {
125+
require.Error(t, err)
126+
}
127+
}
128+
}

0 commit comments

Comments
 (0)