diff --git a/coinlib/lib/src/crypto/ec_public_key.dart b/coinlib/lib/src/crypto/ec_public_key.dart index 43afed2..12c186c 100644 --- a/coinlib/lib/src/crypto/ec_public_key.dart +++ b/coinlib/lib/src/crypto/ec_public_key.dart @@ -34,6 +34,15 @@ class ECPublicKey { ); ECPublicKey.fromXOnlyHex(String hex) : this.fromXOnly(hexToBytes(hex)); + /// Tweaks the public key with a scalar multiplied by the generator point. In + /// the instance a new key cannot be created (practically impossible for + /// random 32-bit scalars), then null will be returned. + ECPublicKey? tweak(Uint8List scalar) { + checkBytes(scalar, 32, name: "Scalar"); + final newKey = secp256k1.pubKeyTweak(_data, scalar, compressed); + return newKey == null ? null : ECPublicKey(newKey); + } + String get hex => bytesToHex(_data); bool get compressed => _data.length == 33; Uint8List get data => Uint8List.fromList(_data); @@ -66,13 +75,4 @@ class ECPublicKey { @override int get hashCode => _data[1] | _data[2] << 8 | _data[3] << 16 | _data[4] << 24; - /// Tweaks the public key with a scalar multiplied by the generator point. In - /// the instance a new key cannot be created (practically impossible for - /// random 32-bit scalars), then null will be returned. - ECPublicKey? tweak(Uint8List scalar) { - checkBytes(scalar, 32, name: "Scalar"); - final newKey = secp256k1.pubKeyTweak(_data, scalar, compressed); - return newKey == null ? null : ECPublicKey(newKey); - } - } diff --git a/coinlib/lib/src/tx/outpoint.dart b/coinlib/lib/src/tx/outpoint.dart index 5be5c73..fe5a639 100644 --- a/coinlib/lib/src/tx/outpoint.dart +++ b/coinlib/lib/src/tx/outpoint.dart @@ -3,6 +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'; /// Reference to an [Output] by transaction hash and index class OutPoint with Writable { @@ -32,4 +33,14 @@ class OutPoint with Writable { /// True if this out point is the type found in a coinbase bool get coinbase => _hash.every((e) => e == 0) && n == 0xffffffff; + @override + bool operator ==(Object other) + => (other is OutPoint) + && ListEquality().equals(_hash, other._hash) + && n == other.n; + + @override + int get hashCode + => _hash[1] | _hash[2] << 8 | _hash[3] << 16 | _hash[4] << 24 | n; + } diff --git a/coinlib/test/crypto/ec_public_key_test.dart b/coinlib/test/crypto/ec_public_key_test.dart index 756379c..e4c4b27 100644 --- a/coinlib/test/crypto/ec_public_key_test.dart +++ b/coinlib/test/crypto/ec_public_key_test.dart @@ -83,7 +83,7 @@ void main() { } }); - test(".equal", () { + test("allows equality comparison", () { for (int i = 0; i < validPubKeys.length; i++) { expect( ECPublicKey.fromHex(validPubKeys[i].hex), diff --git a/coinlib/test/tx/outpoint_test.dart b/coinlib/test/tx/outpoint_test.dart index ebc5e44..228ec48 100644 --- a/coinlib/test/tx/outpoint_test.dart +++ b/coinlib/test/tx/outpoint_test.dart @@ -45,6 +45,24 @@ void main() { expect(op.hash, Uint8List(32)); }); + test("allows equality comparison", () { + + final hash = Uint8List(32); + final outp = OutPoint(hash, 0); + final identical = OutPoint(hash, 0); + + final diff1 = OutPoint(hash, 1); + + hash[0] = 1; + final diff2 = OutPoint(hash, 0); + + expect(outp, identical); + expect(outp, outp); + expect(outp, isNot(equals(diff1))); + expect(outp, isNot(equals(diff2))); + + }); + }); }