Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

null-safety #60

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions lib/src/address.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import 'payments/p2pkh.dart';
import 'payments/p2wpkh.dart';

class Address {
static bool validateAddress(String address, [NetworkType nw]) {
static bool validateAddress(String address, [NetworkType? nw]) {
try {
addressToOutputScript(address, nw);
return true;
Expand All @@ -16,7 +16,7 @@ class Address {
}
}

static Uint8List addressToOutputScript(String address, [NetworkType nw]) {
static Uint8List addressToOutputScript(String address, [NetworkType? nw]) {
NetworkType network = nw ?? bitcoin;
var decodeBase58;
var decodeBech32;
Expand All @@ -28,7 +28,7 @@ class Address {
throw new ArgumentError('Invalid version or Network mismatch');
P2PKH p2pkh =
new P2PKH(data: new PaymentData(address: address), network: network);
return p2pkh.data.output;
return p2pkh.data.output!;
} else {
try {
decodeBech32 = segwit.decode(address);
Expand All @@ -40,7 +40,7 @@ class Address {
throw new ArgumentError('Invalid address version');
P2WPKH p2wpkh = new P2WPKH(
data: new PaymentData(address: address), network: network);
return p2wpkh.data.output;
return p2wpkh.data.output!;
}
}
throw new ArgumentError(address + ' has no matching Script');
Expand Down
70 changes: 34 additions & 36 deletions lib/src/bitcoin_flutter_base.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,70 +7,67 @@ import 'models/networks.dart';
import 'payments/index.dart' show PaymentData;
import 'payments/p2pkh.dart';
import 'ecpair.dart';
import 'package:meta/meta.dart';
import 'dart:convert';

/// Checks if you are awesome. Spoiler: you are.
class HDWallet {
bip32.BIP32 _bip32;
P2PKH _p2pkh;
String seed;
bip32.BIP32? _bip32;
P2PKH? _p2pkh;
String? seed;
NetworkType network;

String get privKey {
String? get privKey {
if (_bip32 == null) return null;
try {
return HEX.encode(_bip32.privateKey);
return HEX.encode(_bip32!.privateKey!);
} catch (_) {
return null;
}
}

String get pubKey => _bip32 != null ? HEX.encode(_bip32.publicKey) : null;
String? get pubKey => _bip32 != null ? HEX.encode(_bip32!.publicKey) : null;

String get base58Priv {
String? get base58Priv {
if (_bip32 == null) return null;
try {
return _bip32.toBase58();
return _bip32!.toBase58();
} catch (_) {
return null;
}
}

String get base58 => _bip32 != null ? _bip32.neutered().toBase58() : null;
String? get base58 => _bip32 != null ? _bip32!.neutered().toBase58() : null;

String get wif {
String? get wif {
if (_bip32 == null) return null;
try {
return _bip32.toWIF();
return _bip32!.toWIF();
} catch (_) {
return null;
}
}

String get address => _p2pkh != null ? _p2pkh.data.address : null;
String? get address => _p2pkh != null ? _p2pkh!.data.address : null;

HDWallet(
{@required bip32, @required p2pkh, @required this.network, this.seed}) {
HDWallet({required bip32, required p2pkh, required this.network, this.seed}) {
this._bip32 = bip32;
this._p2pkh = p2pkh;
}

HDWallet derivePath(String path) {
final bip32 = _bip32.derivePath(path);
final bip32 = _bip32!.derivePath(path);
final p2pkh = new P2PKH(
data: new PaymentData(pubkey: bip32.publicKey), network: network);
return HDWallet(bip32: bip32, p2pkh: p2pkh, network: network);
}

HDWallet derive(int index) {
final bip32 = _bip32.derive(index);
final bip32 = _bip32!.derive(index);
final p2pkh = new P2PKH(
data: new PaymentData(pubkey: bip32.publicKey), network: network);
return HDWallet(bip32: bip32, p2pkh: p2pkh, network: network);
}

factory HDWallet.fromSeed(Uint8List seed, {NetworkType network}) {
factory HDWallet.fromSeed(Uint8List seed, {NetworkType? network}) {
network = network ?? bitcoin;
final seedHex = HEX.encode(seed);
final wallet = bip32.BIP32.fromSeed(
Expand All @@ -85,7 +82,7 @@ class HDWallet {
bip32: wallet, p2pkh: p2pkh, network: network, seed: seedHex);
}

factory HDWallet.fromBase58(String xpub, {NetworkType network}) {
factory HDWallet.fromBase58(String xpub, {NetworkType? network}) {
network = network ?? bitcoin;
final wallet = bip32.BIP32.fromBase58(
xpub,
Expand All @@ -100,40 +97,41 @@ class HDWallet {

Uint8List sign(String message) {
Uint8List messageHash = magicHash(message, network);
return _bip32.sign(messageHash);
return _bip32!.sign(messageHash);
}

bool verify({String message, Uint8List signature}) {
bool verify({required String message, required Uint8List signature}) {
Uint8List messageHash = magicHash(message);
return _bip32.verify(messageHash, signature);
return _bip32!.verify(messageHash, signature);
}
}

class Wallet {
ECPair _keyPair;
P2PKH _p2pkh;
ECPair? _keyPair;
P2PKH? _p2pkh;

String get privKey =>
_keyPair != null ? HEX.encode(_keyPair.privateKey) : null;
String? get privKey =>
_keyPair != null ? HEX.encode(_keyPair!.privateKey!) : null;

String get pubKey => _keyPair != null ? HEX.encode(_keyPair.publicKey) : null;
String? get pubKey =>
_keyPair != null ? HEX.encode(_keyPair!.publicKey!) : null;

String get wif => _keyPair != null ? _keyPair.toWIF() : null;
String? get wif => _keyPair != null ? _keyPair!.toWIF() : null;

String get address => _p2pkh != null ? _p2pkh.data.address : null;
String? get address => _p2pkh != null ? _p2pkh!.data.address : null;

NetworkType network;
NetworkType? network;

Wallet(this._keyPair, this._p2pkh, this.network);

factory Wallet.random([NetworkType network]) {
factory Wallet.random([NetworkType? network]) {
final _keyPair = ECPair.makeRandom(network: network);
final _p2pkh = new P2PKH(
data: new PaymentData(pubkey: _keyPair.publicKey), network: network);
return Wallet(_keyPair, _p2pkh, network);
}

factory Wallet.fromWIF(String wif, [NetworkType network]) {
factory Wallet.fromWIF(String wif, [NetworkType? network]) {
network = network ?? bitcoin;
final _keyPair = ECPair.fromWIF(wif, network: network);
final _p2pkh = new P2PKH(
Expand All @@ -143,11 +141,11 @@ class Wallet {

Uint8List sign(String message) {
Uint8List messageHash = magicHash(message, network);
return _keyPair.sign(messageHash);
return _keyPair!.sign(messageHash);
}

bool verify({String message, Uint8List signature}) {
bool verify({required String message, required Uint8List signature}) {
Uint8List messageHash = magicHash(message, network);
return _keyPair.verify(messageHash, signature);
return _keyPair!.verify(messageHash, signature);
}
}
6 changes: 3 additions & 3 deletions lib/src/classify.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,23 @@ const SCRIPT_TYPES = {
'WITNESS_COMMITMENT': 'witnesscommitment'
};

String classifyOutput(Uint8List script) {
String? classifyOutput(Uint8List script) {
if (witnessPubKeyHash.outputCheck(script)) return SCRIPT_TYPES['P2WPKH'];
if (pubkeyhash.outputCheck(script)) return SCRIPT_TYPES['P2PKH'];
final chunks = bscript.decompile(script);
if (chunks == null) throw new ArgumentError('Invalid script');
return SCRIPT_TYPES['NONSTANDARD'];
}

String classifyInput(Uint8List script) {
String? classifyInput(Uint8List script) {
final chunks = bscript.decompile(script);
if (chunks == null) throw new ArgumentError('Invalid script');
if (pubkeyhash.inputCheck(chunks)) return SCRIPT_TYPES['P2PKH'];
if (pubkey.inputCheck(chunks)) return SCRIPT_TYPES['P2PK'];
return SCRIPT_TYPES['NONSTANDARD'];
}

String classifyWitness(List<Uint8List> script) {
String? classifyWitness(List<Uint8List> script) {
final chunks = bscript.decompile(script);
if (chunks == null) throw new ArgumentError('Invalid script');
if (witnessPubKeyHash.inputCheck(chunks)) return SCRIPT_TYPES['P2WPKH'];
Expand Down
41 changes: 23 additions & 18 deletions lib/src/ecpair.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,39 +5,40 @@ import 'package:bip32/src/utils/wif.dart' as wif;
import 'models/networks.dart';

class ECPair {
Uint8List _d;
Uint8List _Q;
Uint8List? _d;
Uint8List? _Q;
NetworkType network;
bool compressed;
ECPair(Uint8List _d, Uint8List _Q, {network, compressed}) {
this._d = _d;
this._Q = _Q;
this.network = network ?? bitcoin;
this.compressed = compressed ?? true;
}
Uint8List get publicKey {
if (_Q == null) _Q = ecc.pointFromScalar(_d, compressed);

ECPair(Uint8List? this._d, Uint8List? this._Q,
{NetworkType? network, bool? compressed})
: network = network ?? bitcoin,
compressed = compressed ?? true {}

Uint8List? get publicKey {
if (_Q == null) _Q = ecc.pointFromScalar(_d!, compressed);
return _Q;
}

Uint8List get privateKey => _d;
Uint8List? get privateKey => _d;

String toWIF() {
if (privateKey == null) {
throw new ArgumentError('Missing private key');
}
return wif.encode(new wif.WIF(
version: network.wif, privateKey: privateKey, compressed: compressed));
version: network.wif, privateKey: privateKey!, compressed: compressed));
}

Uint8List sign(Uint8List hash) {
return ecc.sign(hash, privateKey);
return ecc.sign(hash, privateKey!);
}

bool verify(Uint8List hash, Uint8List signature) {
return ecc.verify(hash, publicKey, signature);
return ecc.verify(hash, publicKey!, signature);
}

factory ECPair.fromWIF(String w, {NetworkType network}) {
factory ECPair.fromWIF(String w, {NetworkType? network}) {
wif.WIF decoded = wif.decode(w);
final version = decoded.version;
// TODO support multi networks
Expand All @@ -57,16 +58,18 @@ class ECPair {
return ECPair.fromPrivateKey(decoded.privateKey,
compressed: decoded.compressed, network: nw);
}

factory ECPair.fromPublicKey(Uint8List publicKey,
{NetworkType network, bool compressed}) {
{NetworkType? network, bool? compressed}) {
if (!ecc.isPoint(publicKey)) {
throw new ArgumentError('Point is not on the curve');
}
return new ECPair(null, publicKey,
network: network, compressed: compressed);
}

factory ECPair.fromPrivateKey(Uint8List privateKey,
{NetworkType network, bool compressed}) {
{NetworkType? network, bool? compressed}) {
if (privateKey.length != 32)
throw new ArgumentError(
'Expected property privateKey of type Buffer(Length: 32)');
Expand All @@ -75,8 +78,9 @@ class ECPair {
return new ECPair(privateKey, null,
network: network, compressed: compressed);
}

factory ECPair.makeRandom(
{NetworkType network, bool compressed, Function rng}) {
{NetworkType? network, bool? compressed, Function? rng}) {
final rfunc = rng ?? _randomBytes;
Uint8List d;
// int beginTime = DateTime.now().millisecondsSinceEpoch;
Expand All @@ -90,6 +94,7 @@ class ECPair {
}

const int _SIZE_BYTE = 255;

Uint8List _randomBytes(int size) {
final rng = Random.secure();
final bytes = Uint8List(size);
Expand Down
16 changes: 7 additions & 9 deletions lib/src/models/networks.dart
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
import 'package:meta/meta.dart';

class NetworkType {
String messagePrefix;
String bech32;
String? bech32;
Bip32Type bip32;
int pubKeyHash;
int scriptHash;
int wif;

NetworkType(
{@required this.messagePrefix,
{required this.messagePrefix,
this.bech32,
@required this.bip32,
@required this.pubKeyHash,
@required this.scriptHash,
@required this.wif});
required this.bip32,
required this.pubKeyHash,
required this.scriptHash,
required this.wif});

@override
String toString() {
Expand All @@ -26,7 +24,7 @@ class Bip32Type {
int public;
int private;

Bip32Type({@required this.public, @required this.private});
Bip32Type({required this.public, required this.private});

@override
String toString() {
Expand Down
14 changes: 7 additions & 7 deletions lib/src/payments/index.dart
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import 'dart:typed_data';

class PaymentData {
String address;
Uint8List hash;
Uint8List output;
Uint8List signature;
Uint8List pubkey;
Uint8List input;
List<Uint8List> witness;
String? address;
Uint8List? hash;
Uint8List? output;
Uint8List? signature;
Uint8List? pubkey;
Uint8List? input;
List<Uint8List>? witness;

PaymentData(
{this.address,
Expand Down
Loading