Skip to content

Commit 389eef9

Browse files
committed
null safety upgrade
1 parent 5943c9d commit 389eef9

File tree

7 files changed

+161
-122
lines changed

7 files changed

+161
-122
lines changed

example/bip32_example.dart

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1+
import 'dart:typed_data';
12
import '../lib/bip32.dart' as bip32;
23
import 'package:hex/hex.dart';
34

45
main() {
5-
bip32.BIP32 node = bip32.BIP32.fromBase58('xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi');
6+
bip32.BIP32 node = bip32.BIP32.fromBase58(
7+
'xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi');
68

7-
print(HEX.encode(node.privateKey));
9+
print(HEX.encode(node.privateKey!));
810
// => e8f32e723decf4051aefac8e2c93c9c5b214313817cdb01a1494b917c8436b35
911

1012
bip32.BIP32 nodeNeutered = node.neutered();
@@ -21,7 +23,7 @@ main() {
2123
print(child.toBase58());
2224
// => xprv9ww7sMFLzJMzur2oEQDB642fbsMS4q6JRraMVTrM9bTWBq7NDS8ZpmsKVB4YF3mZecqax1fjnsPF19xnsJNfRp4RSyexacULXMKowSACTRc
2325

24-
print(HEX.encode(child.privateKey));
26+
print(HEX.encode(child.privateKey!));
2527
// => f26cf12f89ab91aeeb8d7324a22e8ba080829db15c9245414b073a8c342322aa
2628

2729
bip32.BIP32 childNeutered = child.neutered();
@@ -34,15 +36,19 @@ main() {
3436
print(childNeutered.toBase58());
3537
// => xpub6AvUGrnEpfvJ8L7GLRkBTByQ9uBvUHp9o5VxHrFxhvzV4dSWkySpNaBoLR9FpbnwRmTa69yLHF3QfcaxbWT7gWdwws5k4dpmJvqpEuMWwnj
3638

37-
bip32.BIP32 nodeFromSeed = bip32.BIP32.fromSeed(HEX.decode("000102030405060708090a0b0c0d0e0f"));
39+
bip32.BIP32 nodeFromSeed = bip32.BIP32
40+
.fromSeed(HEX.decode("000102030405060708090a0b0c0d0e0f") as Uint8List);
3841
print(nodeFromSeed.toBase58());
3942
// => xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi
4043

41-
bip32.BIP32 nodeFromPub = bip32.BIP32.fromBase58("xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8");
44+
bip32.BIP32 nodeFromPub = bip32.BIP32.fromBase58(
45+
"xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8");
4246
print(nodeFromPub.toBase58());
4347
// => xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8
4448

45-
var message = HEX.decode("0202020202020202020202020202020202020202020202020202020202020202");
49+
var message = HEX.decode(
50+
"0202020202020202020202020202020202020202020202020202020202020202")
51+
as Uint8List;
4652
var signature = nodeFromSeed.sign(message);
4753
print(signature);
4854
// => [63, 219, 20, 114, 95, 184, 192, 55, 216, 206, 126, 121, 17, 71, 64, 70, 163, 82, 247, 73, 243, 95, 30, 137, 177, 155, 100, 225, 177, 203, 217, 147, 122, 64, 208, 129, 54, 133, 113, 41, 216, 160, 191, 15, 136, 98, 235, 25, 219, 178, 70, 222, 127, 151, 135, 242, 25, 192, 161, 187, 187, 84, 81, 215]

lib/src/bip32_base.dart

Lines changed: 42 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -9,29 +9,25 @@ import 'dart:convert';
99
class Bip32Type {
1010
int public;
1111
int private;
12-
Bip32Type({this.public, this.private});
13-
12+
Bip32Type({required this.public, required this.private});
1413
}
14+
1515
class NetworkType {
1616
int wif;
1717
Bip32Type bip32;
18-
NetworkType({this.wif, this.bip32});
18+
NetworkType({required this.wif, required this.bip32});
1919
}
2020

2121
final _BITCOIN = new NetworkType(
22-
wif: 0x80,
23-
bip32: new Bip32Type(
24-
public: 0x0488b21e,
25-
private: 0x0488ade4
26-
)
27-
);
22+
wif: 0x80, bip32: new Bip32Type(public: 0x0488b21e, private: 0x0488ade4));
2823
const HIGHEST_BIT = 0x80000000;
2924
const UINT31_MAX = 2147483647; // 2^31 - 1
3025
const UINT32_MAX = 4294967295; // 2^32 - 1
26+
3127
/// Checks if you are awesome. Spoiler: you are.
3228
class BIP32 {
33-
Uint8List _d;
34-
Uint8List _Q;
29+
Uint8List? _d;
30+
Uint8List? _Q;
3531
Uint8List chainCode;
3632
int depth = 0;
3733
int index = 0;
@@ -40,11 +36,11 @@ class BIP32 {
4036
BIP32(this._d, this._Q, this.chainCode, this.network);
4137

4238
Uint8List get publicKey {
43-
if (_Q == null) _Q = ecc.pointFromScalar(_d, true);
44-
return _Q;
39+
if (_Q == null) _Q = ecc.pointFromScalar(_d!, true)!;
40+
return _Q!;
4541
}
4642

47-
Uint8List get privateKey => _d;
43+
Uint8List? get privateKey => _d;
4844
Uint8List get identifier => hash160(publicKey);
4945
Uint8List get fingerprint => identifier.sublist(0, 4);
5046

@@ -53,15 +49,17 @@ class BIP32 {
5349
}
5450

5551
BIP32 neutered() {
56-
final neutered = BIP32.fromPublicKey(this.publicKey, this.chainCode, this.network);
52+
final neutered =
53+
BIP32.fromPublicKey(this.publicKey, this.chainCode, this.network);
5754
neutered.depth = this.depth;
5855
neutered.index = this.index;
5956
neutered.parentFingerprint = this.parentFingerprint;
6057
return neutered;
6158
}
6259

6360
String toBase58() {
64-
final version = (!isNeutered()) ? network.bip32.private : network.bip32.public;
61+
final version =
62+
(!isNeutered()) ? network.bip32.private : network.bip32.public;
6563
Uint8List buffer = new Uint8List(78);
6664
ByteData bytes = buffer.buffer.asByteData();
6765
bytes.setUint32(0, version);
@@ -71,7 +69,7 @@ class BIP32 {
7169
buffer.setRange(13, 45, chainCode);
7270
if (!isNeutered()) {
7371
bytes.setUint8(45, 0);
74-
buffer.setRange(46, 78, privateKey);
72+
buffer.setRange(46, 78, privateKey!);
7573
} else {
7674
buffer.setRange(45, 78, publicKey);
7775
}
@@ -83,22 +81,20 @@ class BIP32 {
8381
throw new ArgumentError("Missing private key");
8482
}
8583
return wif.encode(new wif.WIF(
86-
version: network.wif,
87-
privateKey: privateKey,
88-
compressed: true
89-
));
84+
version: network.wif, privateKey: privateKey!, compressed: true));
9085
}
9186

9287
BIP32 derive(int index) {
93-
if (index > UINT32_MAX || index < 0) throw new ArgumentError("Expected UInt32");
88+
if (index > UINT32_MAX || index < 0)
89+
throw new ArgumentError("Expected UInt32");
9490
final isHardened = index >= HIGHEST_BIT;
9591
Uint8List data = new Uint8List(37);
9692
if (isHardened) {
9793
if (isNeutered()) {
9894
throw new ArgumentError("Missing private key for hardened child key");
9995
}
10096
data[0] = 0x00;
101-
data.setRange(1, 33, privateKey);
97+
data.setRange(1, 33, privateKey!);
10298
data.buffer.asByteData().setUint32(33, index);
10399
} else {
104100
data.setRange(0, 33, publicKey);
@@ -112,7 +108,7 @@ class BIP32 {
112108
}
113109
BIP32 hd;
114110
if (!isNeutered()) {
115-
final ki = ecc.privateAdd(privateKey, IL);
111+
final ki = ecc.privateAdd(privateKey!, IL);
116112
if (ki == null) return derive(index + 1);
117113
hd = BIP32.fromPrivateKey(ki, IR, network);
118114
} else {
@@ -127,7 +123,8 @@ class BIP32 {
127123
}
128124

129125
BIP32 deriveHardened(int index) {
130-
if (index > UINT31_MAX || index < 0) throw new ArgumentError("Expected UInt31");
126+
if (index > UINT31_MAX || index < 0)
127+
throw new ArgumentError("Expected UInt31");
131128
return this.derive(index + HIGHEST_BIT);
132129
}
133130

@@ -136,10 +133,11 @@ class BIP32 {
136133
if (!regex.hasMatch(path)) throw new ArgumentError("Expected BIP32 Path");
137134
List<String> splitPath = path.split("/");
138135
if (splitPath[0] == "m") {
139-
if (parentFingerprint != 0) throw new ArgumentError("Expected master, got child");
136+
if (parentFingerprint != 0)
137+
throw new ArgumentError("Expected master, got child");
140138
splitPath = splitPath.sublist(1);
141139
}
142-
return splitPath.fold(this, (BIP32 prevHd,String indexStr) {
140+
return splitPath.fold(this, (BIP32 prevHd, String indexStr) {
143141
int index;
144142
if (indexStr.substring(indexStr.length - 1) == "'") {
145143
index = int.parse(indexStr.substring(0, indexStr.length - 1));
@@ -152,14 +150,14 @@ class BIP32 {
152150
}
153151

154152
sign(Uint8List hash) {
155-
return ecc.sign(hash, privateKey);
153+
return ecc.sign(hash, privateKey!);
156154
}
157155

158156
verify(Uint8List hash, Uint8List signature) {
159157
return ecc.verify(hash, publicKey, signature);
160158
}
161159

162-
factory BIP32.fromBase58(String string, [NetworkType nw]) {
160+
factory BIP32.fromBase58(String string, [NetworkType? nw]) {
163161
Uint8List buffer = bs58check.decode(string);
164162
if (buffer.length != 78) throw new ArgumentError("Invalid buffer length");
165163
NetworkType network = nw ?? _BITCOIN;
@@ -175,7 +173,8 @@ class BIP32 {
175173
// 4 bytes: the fingerprint of the parent's key (0x00000000 if master key)
176174
var parentFingerprint = bytes.getUint32(5);
177175
if (depth == 0) {
178-
if (parentFingerprint != 0x00000000) throw new ArgumentError("Invalid parent fingerprint");
176+
if (parentFingerprint != 0x00000000)
177+
throw new ArgumentError("Invalid parent fingerprint");
179178
}
180179

181180
// 4 bytes: child number. This is the number i in xi = xpar/i, with xi the key being serialized.
@@ -189,7 +188,8 @@ class BIP32 {
189188

190189
// 33 bytes: private key data (0x00 + k)
191190
if (version == network.bip32.private) {
192-
if (bytes.getUint8(45) != 0x00) throw new ArgumentError("Invalid private key");
191+
if (bytes.getUint8(45) != 0x00)
192+
throw new ArgumentError("Invalid private key");
193193
Uint8List k = buffer.sublist(46, 78);
194194
hd = BIP32.fromPrivateKey(k, chainCode, network);
195195
} else {
@@ -203,30 +203,35 @@ class BIP32 {
203203
return hd;
204204
}
205205

206-
factory BIP32.fromPublicKey(Uint8List publicKey, Uint8List chainCode, [NetworkType nw]) {
206+
factory BIP32.fromPublicKey(Uint8List publicKey, Uint8List chainCode,
207+
[NetworkType? nw]) {
207208
NetworkType network = nw ?? _BITCOIN;
208209
if (!ecc.isPoint(publicKey)) {
209210
throw new ArgumentError("Point is not on the curve");
210211
}
211212
return new BIP32(null, publicKey, chainCode, network);
212213
}
213214

214-
factory BIP32.fromPrivateKey(Uint8List privateKey, Uint8List chainCode, [NetworkType nw]) {
215+
factory BIP32.fromPrivateKey(Uint8List privateKey, Uint8List chainCode,
216+
[NetworkType? nw]) {
215217
NetworkType network = nw ?? _BITCOIN;
216-
if (privateKey.length != 32) throw new ArgumentError("Expected property privateKey of type Buffer(Length: 32)");
217-
if (!ecc.isPrivate(privateKey)) throw new ArgumentError("Private key not in range [1, n]");
218+
if (privateKey.length != 32)
219+
throw new ArgumentError(
220+
"Expected property privateKey of type Buffer(Length: 32)");
221+
if (!ecc.isPrivate(privateKey))
222+
throw new ArgumentError("Private key not in range [1, n]");
218223
return new BIP32(privateKey, null, chainCode, network);
219224
}
220225

221-
factory BIP32.fromSeed(Uint8List seed, [NetworkType nw]) {
226+
factory BIP32.fromSeed(Uint8List seed, [NetworkType? nw]) {
222227
if (seed.length < 16) {
223228
throw new ArgumentError("Seed should be at least 128 bits");
224229
}
225230
if (seed.length > 64) {
226231
throw new ArgumentError("Seed should be at most 512 bits");
227232
}
228233
NetworkType network = nw ?? _BITCOIN;
229-
final I = hmacSHA512(utf8.encode("Bitcoin seed"), seed);
234+
final I = hmacSHA512(utf8.encode("Bitcoin seed") as Uint8List, seed);
230235
final IL = I.sublist(0, 32);
231236
final IR = I.sublist(32);
232237
return BIP32.fromPrivateKey(IL, IR, network);

0 commit comments

Comments
 (0)