From 9986dc3e53079e3952a732db31001d21406f2d30 Mon Sep 17 00:00:00 2001 From: Matthew Mitchell Date: Fri, 9 Feb 2024 21:16:13 +0000 Subject: [PATCH] Add stricter analysis options and fix problems --- coinlib/analysis_options.yaml | 7 ++++++ coinlib/lib/src/common/bytes.dart | 5 ++-- coinlib/lib/src/common/checks.dart | 12 ++++----- coinlib/lib/src/crypto/ec_public_key.dart | 3 +-- coinlib/lib/src/crypto/ecdsa_signature.dart | 2 +- coinlib/lib/src/crypto/message_signature.dart | 4 +-- coinlib/lib/src/crypto/nums_public_key.dart | 8 +++--- coinlib/lib/src/scripts/operations.dart | 4 +-- coinlib/lib/src/scripts/program.dart | 4 +-- coinlib/lib/src/scripts/programs/p2sh.dart | 2 +- coinlib/lib/src/scripts/programs/p2wsh.dart | 2 +- .../lib/src/secp256k1/heap_array_base.dart | 2 +- .../lib/src/secp256k1/heap_array_wasm.dart | 2 +- coinlib/lib/src/secp256k1/secp256k1_base.dart | 25 +++++++++++-------- coinlib/lib/src/secp256k1/secp256k1_web.dart | 6 ++--- coinlib/lib/src/taproot.dart | 3 ++- coinlib/lib/src/tx/inputs/input.dart | 4 +-- .../lib/src/tx/inputs/input_signature.dart | 1 + coinlib/lib/src/tx/inputs/legacy_input.dart | 6 +++-- .../src/tx/inputs/legacy_witness_input.dart | 4 +-- .../src/tx/inputs/p2sh_multisig_input.dart | 1 + coinlib/lib/src/tx/inputs/p2wpkh_input.dart | 1 + coinlib/lib/src/tx/inputs/taproot_input.dart | 4 +-- .../lib/src/tx/inputs/taproot_key_input.dart | 2 +- .../src/tx/inputs/taproot_script_input.dart | 2 +- coinlib/lib/src/tx/outpoint.dart | 4 +-- coinlib/lib/src/tx/output.dart | 1 + coinlib/lib/src/tx/sighash/sighash_type.dart | 4 +-- .../lib/src/tx/sighash/signature_hasher.dart | 4 +-- .../tx/sighash/taproot_signature_hasher.dart | 2 +- coinlib/lib/src/tx/transaction.dart | 9 ++++--- coinlib/test/address_test.dart | 6 ++--- coinlib/test/common/bytes_test.dart | 4 --- coinlib/test/common/serial_test.dart | 2 +- coinlib/test/scripts/common.dart | 2 +- coinlib/test/scripts/script_test.dart | 3 ++- .../tx/sighash/signature_hasher_tester.dart | 2 +- coinlib/test/vectors/hd_keys.dart | 4 +-- coinlib/test/vectors/inputs.dart | 2 +- coinlib/test/vectors/signatures.dart | 3 +-- 40 files changed, 92 insertions(+), 76 deletions(-) diff --git a/coinlib/analysis_options.yaml b/coinlib/analysis_options.yaml index b60fc6b..dcd12d8 100644 --- a/coinlib/analysis_options.yaml +++ b/coinlib/analysis_options.yaml @@ -1,5 +1,11 @@ include: package:lints/recommended.yaml +analyzer: + language: + strict-casts: true + strict-inference: true + strict-raw-types: true + # Lint rules and documentation, see http://dart-lang.github.io/linter/lints linter: rules: @@ -10,3 +16,4 @@ linter: - unrelated_type_equality_checks - valid_regexps - require_trailing_commas + - comment_references diff --git a/coinlib/lib/src/common/bytes.dart b/coinlib/lib/src/common/bytes.dart index eadb57e..56d151c 100644 --- a/coinlib/lib/src/common/bytes.dart +++ b/coinlib/lib/src/common/bytes.dart @@ -16,9 +16,8 @@ Uint8List copyCheckBytes( Uint8List bytes, int length, { String name = "Bytes", } ) => Uint8List.fromList(checkBytes(bytes, length, name: name)); -/// Determines if two objects are equal Uint8List data -bool bytesEqual(Object? a, Object? b) - => (a is Uint8List) && (b is Uint8List) && ListEquality().equals(a, b); +/// Determines if two [Uint8List] lists are equal +bool bytesEqual(Uint8List a, Uint8List b) => ListEquality().equals(a, b); /// Compares two Uint8List bytes from the left-most to right-most byte. If all /// bytes are the same apart from one list being longer, the shortest list comes diff --git a/coinlib/lib/src/common/checks.dart b/coinlib/lib/src/common/checks.dart index e2c9eb0..e2a325f 100644 --- a/coinlib/lib/src/common/checks.dart +++ b/coinlib/lib/src/common/checks.dart @@ -1,25 +1,25 @@ -_checkInt(int i, int min, int max, String type, String name) { +void _checkInt(int i, int min, int max, String type, String name) { if (i < min || i > max) { throw ArgumentError.value(i, name, "must be a $type"); } } -checkUint8(int i, [String name = "i"]) +void checkUint8(int i, [String name = "i"]) => _checkInt(i, 0, 0xff, "uint8", name); -checkUint16(int i, [String name = "i"]) +void checkUint16(int i, [String name = "i"]) => _checkInt(i, 0, 0xffff, "uint16", name); -checkUint32(int i, [String name = "i"]) +void checkUint32(int i, [String name = "i"]) => _checkInt(i, 0, 0xffffffff, "uint32", name); -checkInt32(int i, [String name = "i"]) +void checkInt32(int i, [String name = "i"]) => _checkInt(i, -0x80000000, 0x7fffffff, "int32", name); final BigInt maxUint64 = (BigInt.from(1) << 64) - BigInt.one; -checkUint64(BigInt i, [String name = "i"]) { +void checkUint64(BigInt i, [String name = "i"]) { if (i.isNegative || i > maxUint64) { throw ArgumentError.value(i, name, "must be a uint64"); } diff --git a/coinlib/lib/src/crypto/ec_public_key.dart b/coinlib/lib/src/crypto/ec_public_key.dart index a5a23fa..e7e8cca 100644 --- a/coinlib/lib/src/crypto/ec_public_key.dart +++ b/coinlib/lib/src/crypto/ec_public_key.dart @@ -2,7 +2,6 @@ import 'dart:typed_data'; import 'package:coinlib/src/secp256k1/secp256k1.dart'; import 'package:coinlib/src/common/bytes.dart'; import 'package:coinlib/src/common/hex.dart'; -import 'package:collection/collection.dart'; class InvalidPublicKey implements Exception {} @@ -70,7 +69,7 @@ class ECPublicKey { @override bool operator ==(Object other) - => (other is ECPublicKey) && ListEquality().equals(_data, other._data); + => (other is ECPublicKey) && bytesEqual(_data, other._data); @override int get hashCode => _data[1] | _data[2] << 8 | _data[3] << 16 | _data[4] << 24; diff --git a/coinlib/lib/src/crypto/ecdsa_signature.dart b/coinlib/lib/src/crypto/ecdsa_signature.dart index f0232af..e25edd1 100644 --- a/coinlib/lib/src/crypto/ecdsa_signature.dart +++ b/coinlib/lib/src/crypto/ecdsa_signature.dart @@ -45,7 +45,7 @@ class ECDSASignature { } } - /// Takes a BIP66 DER formatted [signature] as a HEX string. + /// Takes a BIP66 DER formatted signature as a HEX string. /// See [ECDSASignature.fromDer]. factory ECDSASignature.fromDerHex(String hex) => ECDSASignature.fromDer(hexToBytes(hex)); diff --git a/coinlib/lib/src/crypto/message_signature.dart b/coinlib/lib/src/crypto/message_signature.dart index a62786f..aca6c59 100644 --- a/coinlib/lib/src/crypto/message_signature.dart +++ b/coinlib/lib/src/crypto/message_signature.dart @@ -14,7 +14,7 @@ class MagicHash with Writable { final String prefix; MagicHash(this.message, this.prefix); - static _writeUtf8(Writer writer, String msg) + static void _writeUtf8(Writer writer, String msg) => writer.writeVarSlice(utf8.encode(msg)); @override @@ -33,7 +33,7 @@ class MessageSignature { final ECDSARecoverableSignature signature; - static magicHash(String message, String prefix) + static Uint8List magicHash(String message, String prefix) => MagicHash(message, prefix).hash; MessageSignature.fromBase64(String str) diff --git a/coinlib/lib/src/crypto/nums_public_key.dart b/coinlib/lib/src/crypto/nums_public_key.dart index 58cf7be..d17689e 100644 --- a/coinlib/lib/src/crypto/nums_public_key.dart +++ b/coinlib/lib/src/crypto/nums_public_key.dart @@ -4,10 +4,10 @@ import 'package:coinlib/src/crypto/random.dart'; /// A "nothing up my sleeve" [ECPublicKey] that is created from a point with no /// known private key and tweaked with a scalar value named [rTweak]. The key is -/// reproduceable from this scalar using [fromRTweak]. Any of these keys have no -/// known associted private key. Sharing the [rTweak] allows others to verify -/// this. These keys can be used as Taproot internal keys where no key-path -/// spending is desired. +/// reproduceable from this scalar using [fromRTweak()]. Any of +/// these keys have no known associted private key. Sharing the [rTweak] allows +/// others to verify this. These keys can be used as Taproot internal keys where +/// no key-path spending is desired. class NUMSPublicKey extends ECPublicKey { /// To prove that this point does not have an associated private key, the diff --git a/coinlib/lib/src/scripts/operations.dart b/coinlib/lib/src/scripts/operations.dart index 1e2e9e4..095c753 100644 --- a/coinlib/lib/src/scripts/operations.dart +++ b/coinlib/lib/src/scripts/operations.dart @@ -1,9 +1,9 @@ import 'dart:typed_data'; +import 'package:coinlib/src/common/bytes.dart'; import 'package:coinlib/src/common/hex.dart'; import 'package:coinlib/src/common/serial.dart'; import 'package:coinlib/src/crypto/ec_public_key.dart'; import 'package:coinlib/src/tx/inputs/input_signature.dart'; -import 'package:collection/collection.dart'; import 'codes.dart'; class InvalidScriptAsm implements Exception {} @@ -312,7 +312,7 @@ class ScriptPushData implements ScriptOp { @override bool match(ScriptOp other) - => (other is ScriptPushData && ListEquality().equals(_data, other._data)) + => (other is ScriptPushData && bytesEqual(_data, other._data)) || (other is ScriptPushDataMatcher && _data.length == other.size); } diff --git a/coinlib/lib/src/scripts/program.dart b/coinlib/lib/src/scripts/program.dart index 0031246..54a0ec2 100644 --- a/coinlib/lib/src/scripts/program.dart +++ b/coinlib/lib/src/scripts/program.dart @@ -20,8 +20,8 @@ abstract class Program { /// Takes a [script] and constructs a matching Program subclass if one exists, /// or a basic [RawProgram] if there is no match. The script should use - /// minimal pushes. [decompile] can be used directly on compiled scripts or - /// [fromAsm] can be used to match directly against ASM. + /// minimal pushes. [Program.decompile] can be used directly on compiled + /// scripts or [Program.fromAsm] can be used to match directly against ASM. factory Program.match(Script script) { try { diff --git a/coinlib/lib/src/scripts/programs/p2sh.dart b/coinlib/lib/src/scripts/programs/p2sh.dart index 90a713b..fec9bd1 100644 --- a/coinlib/lib/src/scripts/programs/p2sh.dart +++ b/coinlib/lib/src/scripts/programs/p2sh.dart @@ -15,7 +15,7 @@ class P2SH implements Program { late final Uint8List _scriptHash; /// Construct using an output script, not to be confused with the redeem - /// script. For that use [fromRedeemScript]. + /// script. For that use [fromRedeemScript()]. P2SH.fromScript(this.script) { if (!template.match(script)) throw NoProgramMatch(); _scriptHash = (script[1] as ScriptPushData).data; diff --git a/coinlib/lib/src/scripts/programs/p2wsh.dart b/coinlib/lib/src/scripts/programs/p2wsh.dart index 4a7428c..1cf5660 100644 --- a/coinlib/lib/src/scripts/programs/p2wsh.dart +++ b/coinlib/lib/src/scripts/programs/p2wsh.dart @@ -11,7 +11,7 @@ import 'package:coinlib/src/scripts/script.dart'; class P2WSH extends P2Witness { /// Construct using an output script, not to be confused with the witness - /// script. For that use [fromWitnessScript]. + /// script. For that use [P2WSH.fromWitnessScript]. P2WSH.fromScript(super.script) : super.fromScript() { if (data.length != 32 || version != 0) throw NoProgramMatch(); } diff --git a/coinlib/lib/src/secp256k1/heap_array_base.dart b/coinlib/lib/src/secp256k1/heap_array_base.dart index 675aa4a..18dc0f2 100644 --- a/coinlib/lib/src/secp256k1/heap_array_base.dart +++ b/coinlib/lib/src/secp256k1/heap_array_base.dart @@ -4,5 +4,5 @@ import 'dart:typed_data'; abstract class HeapArrayBase { Ptr get ptr; Uint8List get list; - load(Uint8List data); + void load(Uint8List data); } diff --git a/coinlib/lib/src/secp256k1/heap_array_wasm.dart b/coinlib/lib/src/secp256k1/heap_array_wasm.dart index a45ff4a..b3afc7d 100644 --- a/coinlib/lib/src/secp256k1/heap_array_wasm.dart +++ b/coinlib/lib/src/secp256k1/heap_array_wasm.dart @@ -46,6 +46,6 @@ class HeapArrayWasmFactory { HeapArrayWasmFactory(this.memory, this.malloc, this.free); - create(int size) => HeapArrayWasm(size, memory, malloc, free); + HeapArrayWasm create(int size) => HeapArrayWasm(size, memory, malloc, free); } diff --git a/coinlib/lib/src/secp256k1/secp256k1_base.dart b/coinlib/lib/src/secp256k1/secp256k1_base.dart index 9dd85a9..bdbcf9e 100644 --- a/coinlib/lib/src/secp256k1/secp256k1_base.dart +++ b/coinlib/lib/src/secp256k1/secp256k1_base.dart @@ -90,13 +90,16 @@ abstract class Secp256k1Base< ) extSchnorrVerify; // Heap arrays - late HeapArrayBase key32Array; // Used for private keys and x-only public keys - late HeapArrayBase scalarArray; - late HeapArrayBase serializedPubKeyArray; - late HeapArrayBase hashArray; - late HeapArrayBase entropyArray; - late HeapArrayBase serializedSigArray; - late HeapArrayBase derSigArray; + + // Used for private keys and x-only public keys + late HeapArrayBase key32Array; + + late HeapArrayBase scalarArray; + late HeapArrayBase serializedPubKeyArray; + late HeapArrayBase hashArray; + late HeapArrayBase entropyArray; + late HeapArrayBase serializedSigArray; + late HeapArrayBase derSigArray; // Other pointers late CtxPtr ctxPtr; @@ -194,7 +197,7 @@ abstract class Secp256k1Base< Future internalLoad() async {} bool _loaded = false; - _requireLoad() { + void _requireLoad() { if (!_loaded) throw Secp256k1Exception("load() not called"); } @@ -311,7 +314,9 @@ abstract class Secp256k1Base< // Using null as it doesn't require passing an additional constant from // the web and io implementations. nullPtr, - extraEntropy == null ? nullPtr : entropyArray.ptr, + // The pointer is not actually null when entropy is provided but NullPtr + // works for void pointers too + extraEntropy == null ? nullPtr : entropyArray.ptr as NullPtr, ) != 1 ) { throw Secp256k1Exception("Cannot sign message with private key"); @@ -441,7 +446,7 @@ abstract class Secp256k1Base< if ( extSchnorrSign32( ctxPtr, serializedSigArray.ptr, hashArray.ptr, keyPairPtr, - extraEntropy == null ? nullPtr : entropyArray.ptr, + extraEntropy == null ? nullPtr as HeapArrayPtr : entropyArray.ptr, ) != 1 ) { throw Secp256k1Exception("Cannot sign Schnorr signature"); diff --git a/coinlib/lib/src/secp256k1/secp256k1_web.dart b/coinlib/lib/src/secp256k1/secp256k1_web.dart index e343d69..e1572e0 100644 --- a/coinlib/lib/src/secp256k1/secp256k1_web.dart +++ b/coinlib/lib/src/secp256k1/secp256k1_web.dart @@ -31,9 +31,9 @@ class Secp256k1 extends Secp256k1Base< // Dummy WASI imports. No file descriptor support provided. importMap: { "wasi_snapshot_preview1" : { - "fd_close": () => {}, - "fd_seek": () => {}, - "fd_write": () => {}, + "fd_close": () => Object(), + "fd_seek": () => Object(), + "fd_write": () => Object(), }, }, ); diff --git a/coinlib/lib/src/taproot.dart b/coinlib/lib/src/taproot.dart index 0fd44c7..bfdece1 100644 --- a/coinlib/lib/src/taproot.dart +++ b/coinlib/lib/src/taproot.dart @@ -1,4 +1,5 @@ import 'dart:typed_data'; +import 'package:coinlib/src/common/bytes.dart'; import 'package:coinlib/src/common/serial.dart'; import 'package:coinlib/src/crypto/ec_private_key.dart'; import 'package:coinlib/src/crypto/ec_public_key.dart'; @@ -186,7 +187,7 @@ class TapLeaf with Writable implements TapNode { bool operator ==(Object other) => (other is TapLeaf) && version == other.version - && ListEquality().equals(script.compiled, other.script.compiled); + && bytesEqual(script.compiled, other.script.compiled); @override int get hashCode => hash[0] | hash[1] << 8 | hash[2] << 16 | hash[3] << 24; diff --git a/coinlib/lib/src/tx/inputs/input.dart b/coinlib/lib/src/tx/inputs/input.dart index e5178d1..99a63b3 100644 --- a/coinlib/lib/src/tx/inputs/input.dart +++ b/coinlib/lib/src/tx/inputs/input.dart @@ -8,8 +8,8 @@ import 'p2sh_multisig_input.dart'; import 'raw_input.dart'; import 'witness_input.dart'; -/// The base class for all inputs, providing the [match] factory constructor to -/// determine the appropriate subclass from a [RawInput] +/// The base class for all inputs, providing the [Input.match] factory +/// constructor to determine the appropriate subclass from a [RawInput] abstract class Input with Writable { static const sequenceFinal = 0xffffffff; diff --git a/coinlib/lib/src/tx/inputs/input_signature.dart b/coinlib/lib/src/tx/inputs/input_signature.dart index a256374..8e6dba3 100644 --- a/coinlib/lib/src/tx/inputs/input_signature.dart +++ b/coinlib/lib/src/tx/inputs/input_signature.dart @@ -2,6 +2,7 @@ import 'dart:typed_data'; import 'package:coinlib/src/crypto/ecdsa_signature.dart'; import 'package:coinlib/src/crypto/schnorr_signature.dart'; import 'package:coinlib/src/tx/sighash/sighash_type.dart'; +import 'input.dart'; class InvalidInputSignature implements Exception {} diff --git a/coinlib/lib/src/tx/inputs/legacy_input.dart b/coinlib/lib/src/tx/inputs/legacy_input.dart index bbf25a5..0f14a21 100644 --- a/coinlib/lib/src/tx/inputs/legacy_input.dart +++ b/coinlib/lib/src/tx/inputs/legacy_input.dart @@ -6,6 +6,8 @@ import 'package:coinlib/src/tx/sighash/sighash_type.dart'; import 'package:coinlib/src/tx/transaction.dart'; import 'input.dart'; import 'input_signature.dart'; +import 'p2pkh_input.dart'; +import 'p2sh_multisig_input.dart'; import 'raw_input.dart'; /// Inputs that are not witness inputs: [P2PKHInput] and [P2SHMultisigInput]. @@ -24,7 +26,7 @@ abstract class LegacyInput extends RawInput { required Transaction tx, required int inputN, required ECPrivateKey key, - hashType = const SigHashType.all(), + SigHashType hashType = const SigHashType.all(), }); /// Creates a signature for the input. Used by subclasses to implement @@ -34,7 +36,7 @@ abstract class LegacyInput extends RawInput { required int inputN, required ECPrivateKey key, required Script scriptCode, - hashType = const SigHashType.all(), + SigHashType hashType = const SigHashType.all(), }) => ECDSAInputSignature( ECDSASignature.sign( key, diff --git a/coinlib/lib/src/tx/inputs/legacy_witness_input.dart b/coinlib/lib/src/tx/inputs/legacy_witness_input.dart index 908c3a3..242c0b7 100644 --- a/coinlib/lib/src/tx/inputs/legacy_witness_input.dart +++ b/coinlib/lib/src/tx/inputs/legacy_witness_input.dart @@ -27,7 +27,7 @@ abstract class LegacyWitnessInput extends WitnessInput { required int inputN, required ECPrivateKey key, required BigInt value, - hashType = const SigHashType.all(), + SigHashType hashType = const SigHashType.all(), }); /// Creates a signature for the input. Used by subclasses to implement @@ -38,7 +38,7 @@ abstract class LegacyWitnessInput extends WitnessInput { required ECPrivateKey key, required Script scriptCode, required BigInt value, - hashType = const SigHashType.all(), + SigHashType hashType = const SigHashType.all(), }) => ECDSAInputSignature( ECDSASignature.sign( key, diff --git a/coinlib/lib/src/tx/inputs/p2sh_multisig_input.dart b/coinlib/lib/src/tx/inputs/p2sh_multisig_input.dart index 9fb0759..b788636 100644 --- a/coinlib/lib/src/tx/inputs/p2sh_multisig_input.dart +++ b/coinlib/lib/src/tx/inputs/p2sh_multisig_input.dart @@ -5,6 +5,7 @@ import 'package:coinlib/src/crypto/ec_public_key.dart'; import 'package:coinlib/src/scripts/operations.dart'; import 'package:coinlib/src/scripts/program.dart'; import 'package:coinlib/src/scripts/programs/multisig.dart'; +import 'package:coinlib/src/scripts/programs/p2sh.dart'; import 'package:coinlib/src/scripts/script.dart'; import 'package:coinlib/src/tx/sighash/legacy_signature_hasher.dart'; import 'package:coinlib/src/tx/sighash/sighash_type.dart'; diff --git a/coinlib/lib/src/tx/inputs/p2wpkh_input.dart b/coinlib/lib/src/tx/inputs/p2wpkh_input.dart index 9f41e5b..4dcc037 100644 --- a/coinlib/lib/src/tx/inputs/p2wpkh_input.dart +++ b/coinlib/lib/src/tx/inputs/p2wpkh_input.dart @@ -1,6 +1,7 @@ import 'dart:typed_data'; import 'package:coinlib/src/crypto/ec_private_key.dart'; import 'package:coinlib/src/crypto/ec_public_key.dart'; +import 'package:coinlib/src/scripts/programs/p2wpkh.dart'; import 'package:coinlib/src/tx/sighash/sighash_type.dart'; import 'package:coinlib/src/tx/transaction.dart'; import 'input.dart'; diff --git a/coinlib/lib/src/tx/inputs/taproot_input.dart b/coinlib/lib/src/tx/inputs/taproot_input.dart index 0845de6..91ea6ec 100644 --- a/coinlib/lib/src/tx/inputs/taproot_input.dart +++ b/coinlib/lib/src/tx/inputs/taproot_input.dart @@ -27,7 +27,7 @@ abstract class TaprootInput extends WitnessInput { required int inputN, required ECPrivateKey key, required List prevOuts, - hashType = const SigHashType.all(), + SigHashType hashType = const SigHashType.all(), }) => throw CannotSignInput("Unimplemented sign() for {this.runtimeType}"); /// Creates a signature for the input. Used by subclasses to implement @@ -37,7 +37,7 @@ abstract class TaprootInput extends WitnessInput { required int inputN, required ECPrivateKey key, required List prevOuts, - hashType = const SigHashType.all(), + SigHashType hashType = const SigHashType.all(), Uint8List? leafHash, int codeSeperatorPos = 0xFFFFFFFF, }) => SchnorrInputSignature( diff --git a/coinlib/lib/src/tx/inputs/taproot_key_input.dart b/coinlib/lib/src/tx/inputs/taproot_key_input.dart index 4f4407c..ae3a719 100644 --- a/coinlib/lib/src/tx/inputs/taproot_key_input.dart +++ b/coinlib/lib/src/tx/inputs/taproot_key_input.dart @@ -53,7 +53,7 @@ class TaprootKeyInput extends TaprootInput { required int inputN, required ECPrivateKey key, required List prevOuts, - hashType = const SigHashType.all(), + SigHashType hashType = const SigHashType.all(), }) { if (inputN >= prevOuts.length) { diff --git a/coinlib/lib/src/tx/inputs/taproot_script_input.dart b/coinlib/lib/src/tx/inputs/taproot_script_input.dart index 3c9eb4b..f68b45f 100644 --- a/coinlib/lib/src/tx/inputs/taproot_script_input.dart +++ b/coinlib/lib/src/tx/inputs/taproot_script_input.dart @@ -107,7 +107,7 @@ class TaprootScriptInput extends TaprootInput { required int inputN, required ECPrivateKey key, required List prevOuts, - hashType = const SigHashType.all(), + SigHashType hashType = const SigHashType.all(), int codeSeperatorPos = 0xFFFFFFFF, }) => createInputSignature( tx: tx, diff --git a/coinlib/lib/src/tx/outpoint.dart b/coinlib/lib/src/tx/outpoint.dart index fe5a639..e0ebf25 100644 --- a/coinlib/lib/src/tx/outpoint.dart +++ b/coinlib/lib/src/tx/outpoint.dart @@ -3,7 +3,7 @@ import 'package:coinlib/src/common/bytes.dart'; import 'package:coinlib/src/common/checks.dart'; import 'package:coinlib/src/common/hex.dart'; import 'package:coinlib/src/common/serial.dart'; -import 'package:collection/collection.dart'; +import 'output.dart'; /// Reference to an [Output] by transaction hash and index class OutPoint with Writable { @@ -36,7 +36,7 @@ class OutPoint with Writable { @override bool operator ==(Object other) => (other is OutPoint) - && ListEquality().equals(_hash, other._hash) + && bytesEqual(_hash, other._hash) && n == other.n; @override diff --git a/coinlib/lib/src/tx/output.dart b/coinlib/lib/src/tx/output.dart index 20eec2f..0c24acd 100644 --- a/coinlib/lib/src/tx/output.dart +++ b/coinlib/lib/src/tx/output.dart @@ -4,6 +4,7 @@ import 'package:coinlib/src/common/checks.dart'; import 'package:coinlib/src/common/serial.dart'; import 'package:coinlib/src/scripts/program.dart'; import 'package:coinlib/src/scripts/script.dart'; +import 'package:coinlib/src/tx/sighash/sighash_type.dart'; /// A transaction output that carries a [value] and [program] specifying how the /// value can be spent. diff --git a/coinlib/lib/src/tx/sighash/sighash_type.dart b/coinlib/lib/src/tx/sighash/sighash_type.dart index fbaa7f2..5f93b08 100644 --- a/coinlib/lib/src/tx/sighash/sighash_type.dart +++ b/coinlib/lib/src/tx/sighash/sighash_type.dart @@ -19,7 +19,7 @@ class SigHashType { static const anyOneCanPayFlag = 0x80; /// The single byte representation of the sighash type. Use [all], [none], - /// [single] and [anyonecanpay] to extract details of the type. + /// [single] and [anyOneCanPay] to extract details of the type. final int value; /// Returns true if the sighash type value is valid. @@ -30,7 +30,7 @@ class SigHashType { /// Checks if the sighash value is valid and returns an [ArgumentError] if /// not. - static checkValue(int value) { + static void checkValue(int value) { if (!validValue(value)) { throw ArgumentError.value(value, "value", "not a valid hash type"); } diff --git a/coinlib/lib/src/tx/sighash/signature_hasher.dart b/coinlib/lib/src/tx/sighash/signature_hasher.dart index 43ceef2..248e0b5 100644 --- a/coinlib/lib/src/tx/sighash/signature_hasher.dart +++ b/coinlib/lib/src/tx/sighash/signature_hasher.dart @@ -4,13 +4,13 @@ import 'package:coinlib/src/tx/transaction.dart'; abstract interface class SignatureHasher { - static checkInputN(Transaction tx, int inputN) { + static void checkInputN(Transaction tx, int inputN) { if (inputN < 0 || inputN >= tx.inputs.length) { throw RangeError.index(inputN, tx.inputs, "inputN"); } } - static checkSchnorrDisallowed(SigHashType type) { + static void checkSchnorrDisallowed(SigHashType type) { if (type.schnorrDefault) { throw ArgumentError( "Cannot create signature hash for legacy input using default Schnorr" diff --git a/coinlib/lib/src/tx/sighash/taproot_signature_hasher.dart b/coinlib/lib/src/tx/sighash/taproot_signature_hasher.dart index 4fc3b64..b9a2cee 100644 --- a/coinlib/lib/src/tx/sighash/taproot_signature_hasher.dart +++ b/coinlib/lib/src/tx/sighash/taproot_signature_hasher.dart @@ -22,7 +22,7 @@ final class TaprootSignatureHasher with Writable implements SignatureHasher { final int codeSeperatorPos; /// Produces the hash for a Taproot input signature at [inputN]. - /// Unless [SigHashType.anyonecanpay] is true, [prevOuts] must contain the + /// Unless [SigHashType.anyOneCanPay] is true, [prevOuts] must contain the /// full list of previous outputs being spent. /// The [hashType] controls what data is included. If ommitted it will be /// treated as SIGHASH_DEFAULT which includes the same data as SIGHASH_ALL but diff --git a/coinlib/lib/src/tx/transaction.dart b/coinlib/lib/src/tx/transaction.dart index d991e1a..12c5ef6 100644 --- a/coinlib/lib/src/tx/transaction.dart +++ b/coinlib/lib/src/tx/transaction.dart @@ -9,6 +9,9 @@ import 'inputs/input.dart'; import 'inputs/input_signature.dart'; import 'inputs/legacy_input.dart'; import 'inputs/legacy_witness_input.dart'; +import 'inputs/p2pkh_input.dart'; +import 'inputs/p2sh_multisig_input.dart'; +import 'inputs/p2wpkh_input.dart'; import 'inputs/raw_input.dart'; import 'inputs/witness_input.dart'; import 'sighash/sighash_type.dart'; @@ -144,12 +147,12 @@ class Transaction with Writable { } - /// Constructs a transaction from serialised bytes. See [fromReader]. + /// Constructs a transaction from serialised bytes. See [fromReader()]. factory Transaction.fromBytes(Uint8List bytes, { bool? expectWitness }) => Transaction.fromReader(BytesReader(bytes), expectWitness: expectWitness); /// Constructs a transaction from the serialised data encoded as hex. See - /// [fromReader]. + /// [fromReader()]. factory Transaction.fromHex(String hex, { bool? expectWitness }) => Transaction.fromBytes(hexToBytes(hex), expectWitness: expectWitness); @@ -193,7 +196,7 @@ class Transaction with Writable { Transaction sign({ required int inputN, required ECPrivateKey key, - hashType = const SigHashType.all(), + SigHashType hashType = const SigHashType.all(), BigInt? value, List? prevOuts, }) { diff --git a/coinlib/test/address_test.dart b/coinlib/test/address_test.dart index ce10884..95ad137 100644 --- a/coinlib/test/address_test.dart +++ b/coinlib/test/address_test.dart @@ -16,7 +16,7 @@ final wrongNetwork = Network( minOutput: BigInt.from(10000), ); -expectBase58Equal(Base58Address addr, Base58Address expected) { +void expectBase58Equal(Base58Address addr, Base58Address expected) { expect(addr.hash, expected.hash); expect(addr.version, expected.version); expect(addr.toString(), expected.toString()); @@ -27,7 +27,7 @@ expectBase58Equal(Base58Address addr, Base58Address expected) { } } -expectBech32Equal(Bech32Address addr, Bech32Address expected) { +void expectBech32Equal(Bech32Address addr, Bech32Address expected) { expect(addr.data, expected.data); expect(addr.hrp, expected.hrp); expect(addr.toString(), expected.toString()); @@ -42,7 +42,7 @@ expectBech32Equal(Bech32Address addr, Bech32Address expected) { } } -expectValidAddress( +void expectValidAddress( String encoded, Network network, T expected, ) { diff --git a/coinlib/test/common/bytes_test.dart b/coinlib/test/common/bytes_test.dart index 043c85e..8a7f8a4 100644 --- a/coinlib/test/common/bytes_test.dart +++ b/coinlib/test/common/bytes_test.dart @@ -23,14 +23,10 @@ void main() { final li1 = Uint8List.fromList([1,2,3]); final copy = Uint8List.fromList(li1); - final li2 = Uint16List.fromList([1,2,2]); expect(bytesEqual(li1, li1), true); expect(bytesEqual(li1, copy), true); - expect(bytesEqual(li1, li2), false); expect(bytesEqual(li1, li1.sublist(0, 2)), false); - expect(bytesEqual(li1, [1,2,3]), false); - expect(bytesEqual(li1, null), false); }); diff --git a/coinlib/test/common/serial_test.dart b/coinlib/test/common/serial_test.dart index c9b98d6..e421b47 100644 --- a/coinlib/test/common/serial_test.dart +++ b/coinlib/test/common/serial_test.dart @@ -77,7 +77,7 @@ void main() { expect(reader.readVarInt(), BigInt.one); expect(reader.readSlice(32), prevOutHash); expect(reader.readUInt32(), 0); - expect(reader.readVarSlice(), []); + expect(reader.readVarSlice(), Uint8List(0)); expect(reader.readUInt32(), 0xffffffff); // Output diff --git a/coinlib/test/scripts/common.dart b/coinlib/test/scripts/common.dart index fcb97e4..295b57f 100644 --- a/coinlib/test/scripts/common.dart +++ b/coinlib/test/scripts/common.dart @@ -1,7 +1,7 @@ import 'package:coinlib/coinlib.dart'; import 'package:test/test.dart'; -expectScriptOp(ScriptOp op, String asm, String hex, int? number, bool isPush) { +void expectScriptOp(ScriptOp op, String asm, String hex, int? number, bool isPush) { expect(op.asm, asm); expect(bytesToHex(op.compiled), hex); expect(op.number, number); diff --git a/coinlib/test/scripts/script_test.dart b/coinlib/test/scripts/script_test.dart index d36d361..2cf0730 100644 --- a/coinlib/test/scripts/script_test.dart +++ b/coinlib/test/scripts/script_test.dart @@ -1,3 +1,4 @@ +import 'dart:typed_data'; import 'package:test/test.dart'; import 'package:coinlib/coinlib.dart'; import 'common.dart'; @@ -136,7 +137,7 @@ void main() { [hexToBytes("0102030405"), hexToBytes("000000"), hexToBytes("0102")], [hexToBytes("0102030405"), 5], [hexToBytes("0102030405"), [0,0,0]], - [], + Uint8List(0), ]) { expect( () => template.fill(bad), diff --git a/coinlib/test/tx/sighash/signature_hasher_tester.dart b/coinlib/test/tx/sighash/signature_hasher_tester.dart index 5d0bd25..0e94f55 100644 --- a/coinlib/test/tx/sighash/signature_hasher_tester.dart +++ b/coinlib/test/tx/sighash/signature_hasher_tester.dart @@ -3,7 +3,7 @@ import 'package:coinlib/coinlib.dart'; import 'package:test/test.dart'; import '../../vectors/tx.dart'; -signatureHasherTester( +void signatureHasherTester( String name, Uint8List Function(Transaction tx, int inputN, SigHashVector vec) hasher, String Function(SigHashVector vec) hashFromVec, diff --git a/coinlib/test/vectors/hd_keys.dart b/coinlib/test/vectors/hd_keys.dart index 543418d..ac940b7 100644 --- a/coinlib/test/vectors/hd_keys.dart +++ b/coinlib/test/vectors/hd_keys.dart @@ -29,7 +29,7 @@ class HDVector { required this.hardened, }); - expectHDKey(HDKey key) { + void expectHDKey(HDKey key) { late HDPublicKey pubKey; if (key is HDPrivateKey) { @@ -51,7 +51,7 @@ class HDVector { } // Adds a static check to the key type - expectHDPrivateKey(HDPrivateKey key) => expectHDKey(key); + void expectHDPrivateKey(HDPrivateKey key) => expectHDKey(key); } diff --git a/coinlib/test/vectors/inputs.dart b/coinlib/test/vectors/inputs.dart index 85114aa..a73a635 100644 --- a/coinlib/test/vectors/inputs.dart +++ b/coinlib/test/vectors/inputs.dart @@ -14,7 +14,7 @@ final rawWitnessInputBytes = Uint8List.fromList([ 0xed, 0xfe, 0xef, 0xbe, ]); -expectInput(Input input) { +void expectInput(Input input) { expect(input.prevOut.hash, prevOutHash); expect(input.prevOut.n, prevOutN); expect(input.sequence, sequence); diff --git a/coinlib/test/vectors/signatures.dart b/coinlib/test/vectors/signatures.dart index b20d532..4966856 100644 --- a/coinlib/test/vectors/signatures.dart +++ b/coinlib/test/vectors/signatures.dart @@ -1,4 +1,3 @@ - final validSignatures = [ "a951b0cf98bd51c614c802a65a418fa42482dc5c45c9394e39c0d98773c51cd530104fdc36d91582b5757e1de73d982e803cc14d75e82c65daf924e38d27d834", "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", @@ -43,7 +42,7 @@ class RecSigVector { required this.recid, required this.pubkey, }); - get signature => compact.substring(2); + String get signature => compact.substring(2); } final validRecoverableSigs = [