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

feat: improve type system in domain #40

Merged
merged 1 commit into from
Nov 21, 2024
Merged
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
13 changes: 10 additions & 3 deletions include/kth/domain/wallet/ec_private.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,16 +76,23 @@ class KD_API ec_private {
}

/// Constructors.
ec_private();
ec_private(ec_private const& x) = default;
ec_private() = default;

explicit
ec_private(std::string const& wif, uint8_t version = mainnet_p2kh);

explicit
ec_private(wif_compressed const& wif, uint8_t version = mainnet_p2kh);

explicit
ec_private(const wif_uncompressed& wif, uint8_t version = mainnet_p2kh);

/// The version is 16 bits. The most significant byte is the WIF prefix and
/// the least significant byte is the address perfix. 0x8000 by default.
explicit
ec_private(ec_secret const& secret, uint16_t version = mainnet, bool compress = true);

ec_private(ec_private const& x) = default;
ec_private& operator=(ec_private const& x) = default;

/// Operators.
Expand Down Expand Up @@ -147,7 +154,7 @@ class KD_API ec_private {
bool valid_{false};
bool compress_{true};
uint16_t version_{0};
ec_secret secret_;
ec_secret secret_{null_hash};
};

} // namespace kth::domain::wallet
Expand Down
16 changes: 13 additions & 3 deletions include/kth/domain/wallet/ec_public.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,24 @@ class KD_API ec_public {
uint8_t const mainnet_p2kh;

/// Constructors.
ec_public();
ec_public(ec_public const& x);
ec_public() = default;

explicit
ec_public(ec_private const& secret);

explicit
ec_public(data_chunk const& decoded);

explicit
ec_public(std::string const& base16);

explicit
ec_public(ec_compressed const& point, bool compress = true);

explicit
ec_public(ec_uncompressed const& point, bool compress = false);

ec_public(ec_public const& x) = default;
ec_public& operator=(ec_public const& x) = default;

/// Operators.
Expand Down Expand Up @@ -108,7 +118,7 @@ class KD_API ec_public {
bool valid_{false};
bool compress_{true};
uint8_t version_;
ec_compressed point_;
ec_compressed point_ = null_compressed_point;
};

} // namespace kth::domain::wallet
Expand Down
35 changes: 9 additions & 26 deletions src/wallet/ec_private.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,38 +35,21 @@ uint8_t const ec_private::testnet_wif = 0xef;
uint8_t const ec_private::testnet_p2kh = 0x6f;
uint16_t const ec_private::testnet = to_version(testnet_p2kh, testnet_wif);

ec_private::ec_private()
: secret_(null_hash)
{}

// ec_private::ec_private(ec_private const& x)
// : valid_(x.valid_), compress_(x.compress_), version_(x.version_), secret_(x.secret_) {
// }

ec_private::ec_private(std::string const& wif, uint8_t version)
: ec_private(from_string(wif, version)) {
}
: ec_private(from_string(wif, version))
{}

ec_private::ec_private(wif_compressed const& wif, uint8_t version)
: ec_private(from_compressed(wif, version)) {
}
: ec_private(from_compressed(wif, version))
{}

ec_private::ec_private(const wif_uncompressed& wif, uint8_t version)
: ec_private(from_uncompressed(wif, version)) {
}
: ec_private(from_uncompressed(wif, version))
{}

ec_private::ec_private(ec_secret const& secret, uint16_t version, bool compress)
: valid_(true), compress_(compress), version_(version), secret_(secret) {
}

// ec_private& ec_private::operator=(ec_private const& x) {
// valid_ = x.valid_;
// compress_ = x.compress_;
// version_ = x.version_;
// secret_ = x.secret_;
// return *this;
// }

: valid_(true), compress_(compress), version_(version), secret_(secret)
{}

// Validators.
// ----------------------------------------------------------------------------
Expand Down Expand Up @@ -182,7 +165,7 @@ ec_public ec_private::to_public() const {
}

payment_address ec_private::to_payment_address() const {
return {*this};
return payment_address{*this};
}

// Operators.
Expand Down
10 changes: 1 addition & 9 deletions src/wallet/ec_public.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,6 @@ uint8_t const ec_public::mainnet_p2kh = 0x30;
uint8_t const ec_public::mainnet_p2kh = 0x00;
#endif

ec_public::ec_public()
: point_(null_compressed_point)
{}

ec_public::ec_public(ec_public const& x)
: valid_(x.valid_), compress_(x.compress_), point_(x.point_) {
}

ec_public::ec_public(ec_private const& secret)
: ec_public(from_private(secret)) {
}
Expand Down Expand Up @@ -173,7 +165,7 @@ bool ec_public::to_uncompressed(ec_uncompressed& out) const {
}

payment_address ec_public::to_payment_address(uint8_t version) const {
return {*this, version};
return payment_address{*this, version};
}

// Operators.
Expand Down
8 changes: 4 additions & 4 deletions src/wallet/encrypted_keys.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,13 @@ bool address_salt(ek_salt& salt, payment_address const& address) {

static
bool address_salt(ek_salt& salt, ec_compressed const& point, uint8_t version, bool compressed) {
payment_address address({point, compressed}, version);
payment_address address(ec_public{point, compressed}, version);
return address ? address_salt(salt, address) : false;
}

static
bool address_salt(ek_salt& salt, ec_secret const& secret, uint8_t version, bool compressed) {
payment_address address({secret, version, compressed});
payment_address address(ec_private{secret, version, compressed});
return address ? address_salt(salt, address) : false;
}

Expand All @@ -73,13 +73,13 @@ bool address_validate(const ek_salt& salt,

static
bool address_validate(const ek_salt& salt, ec_compressed const& point, uint8_t version, bool compressed) {
payment_address address({point, compressed}, version);
payment_address address(ec_public{point, compressed}, version);
return address ? address_validate(salt, address) : false;
}

static
bool address_validate(const ek_salt& salt, ec_secret const& secret, uint8_t version, bool compressed) {
payment_address address({secret, version, compressed});
payment_address address(ec_private{secret, version, compressed});
return address ? address_validate(salt, address) : false;
}

Expand Down
3 changes: 1 addition & 2 deletions src/wallet/message.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,7 @@ bool verify_message(data_slice message, payment_address const& address, message_
short_hash hash;
auto const message_digest = hash_message(message);
return recover(hash, compressed, compact, recovery_id, message_digest) &&
std::equal(hash.begin(), hash.end(), address.hash20().begin());
// (hash == address.hash20());
hash == address.hash20();
}

} // namespace kth::domain::wallet
2 changes: 1 addition & 1 deletion src/wallet/stealth_receiver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ bool stealth_receiver::derive_address(payment_address& out_address,
return false;
}

out_address = {receiver_public, version_};
out_address = payment_address{ec_public{receiver_public}, version_};
return true;
}

Expand Down
2 changes: 1 addition & 1 deletion src/wallet/stealth_sender.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ void stealth_sender::initialize(ec_secret const& ephemeral_private,
}

if (create_stealth_script(script_, ephemeral_private, filter, seed)) {
address_ = {sender_public, version_};
address_ = wallet::payment_address{ec_public{sender_public}, version_};
}
}

Expand Down
2 changes: 1 addition & 1 deletion test/math/stealth.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ TEST_CASE("stealth round trip", "[stealth]") {

// Both parties therefore have the ability to generate the p2pkh address.
// versioning: stealth_address::main corresponds to payment_address::main_p2pkh
wallet::payment_address address(stealth_public, wallet::payment_address::mainnet_p2kh);
wallet::payment_address address(wallet::ec_public{stealth_public}, wallet::payment_address::mainnet_p2kh);
REQUIRE(address.encoded_legacy() == P2PKH_ADDRESS);
}

Expand Down
36 changes: 18 additions & 18 deletions test/wallet/message.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ TEST_CASE("message magic to recovery id invalid false", "[message recovery m
TEST_CASE("message sign message compressed expected", "[message sign message]") {
auto const compressed = true;
auto const secret = base16_literal(SECRET);
const payment_address address({secret, 0x00, compressed});
payment_address const address(ec_private{secret, 0x00, compressed});
auto const message = to_chunk(std::string("Compressed"));
message_signature out_signature;
REQUIRE(sign_message(out_signature, message, secret, compressed));
Expand All @@ -124,7 +124,7 @@ TEST_CASE("message sign message compressed expected", "[message sign message
TEST_CASE("message sign message uncompressed expected", "[message sign message]") {
auto const compressed = false;
auto const secret = base16_literal(SECRET);
const payment_address address({secret, 0x00, compressed});
payment_address const address(ec_private{secret, 0x00, compressed});
auto const message = to_chunk(std::string("Uncompressed"));
message_signature out_signature;
REQUIRE(sign_message(out_signature, message, secret, compressed));
Expand All @@ -133,7 +133,7 @@ TEST_CASE("message sign message uncompressed expected", "[message sign messa

TEST_CASE("message sign message secret compressed expected", "[message sign message]") {
ec_private secret(WIF_COMPRESSED);
const payment_address address(secret);
payment_address const address(secret);
auto const message = to_chunk(std::string("Compressed"));
message_signature out_signature;
REQUIRE(sign_message(out_signature, message, secret));
Expand All @@ -142,7 +142,7 @@ TEST_CASE("message sign message secret compressed expected", "[message sign

TEST_CASE("message sign message wif compressed expected", "[message sign message]") {
ec_private secret(WIF_COMPRESSED);
const payment_address address(secret);
payment_address const address(secret);
auto const message = to_chunk(std::string("Compressed"));
message_signature out_signature;
REQUIRE(sign_message(out_signature, message, secret, secret.compressed()));
Expand All @@ -151,7 +151,7 @@ TEST_CASE("message sign message wif compressed expected", "[message sign mes

TEST_CASE("message sign message wif uncompressed expected", "[message sign message]") {
ec_private secret(WIF_UNCOMPRESSED);
const payment_address address(secret);
payment_address const address(secret);
auto const message = to_chunk(std::string("Uncompressed"));
message_signature out_signature;
REQUIRE(sign_message(out_signature, message, secret, secret.compressed()));
Expand All @@ -160,54 +160,54 @@ TEST_CASE("message sign message wif uncompressed expected", "[message sign m

// End Test Suite

// Start Test Suite: message verify message
// Start Test Suite: message verify message

TEST_CASE("message verify message compressed expected", "[message verify message]") {
const payment_address address(base16_literal(SECRET));
TEST_CASE("message verify message compressed expected", "[message verify message]") {
payment_address const address(ec_private{base16_literal(SECRET)});
auto const message = to_chunk(std::string("Compressed"));
auto const signature = base16_literal(SIGNATURE_COMPRESSED);
REQUIRE(verify_message(message, address, signature));
}

TEST_CASE("message verify message uncompressed expected", "[message verify message]") {
const payment_address address({base16_literal(SECRET), 0x00, false});
TEST_CASE("message verify message uncompressed expected", "[message verify message]") {
payment_address const address(ec_private{base16_literal(SECRET), 0x00, false});
auto const message = to_chunk(std::string("Uncompressed"));
auto const signature = base16_literal(SIGNATURE_UNCOMPRESSED);
REQUIRE(verify_message(message, address, signature));
}

TEST_CASE("message verify message wif compressed round trip", "[message verify message]") {
TEST_CASE("message verify message wif compressed round trip", "[message verify message]") {
ec_private secret(WIF_COMPRESSED);
const payment_address address(secret);
payment_address const address(secret);
auto const message = to_chunk(std::string("Compressed"));
auto const signature = base16_literal(SIGNATURE_WIF_COMPRESSED);
REQUIRE(verify_message(message, address, signature));
}

TEST_CASE("message verify message wif uncompressed round trip", "[message verify message]") {
TEST_CASE("message verify message wif uncompressed round trip", "[message verify message]") {
ec_private secret(WIF_UNCOMPRESSED);
const payment_address address(secret);
payment_address const address(secret);
auto const message = to_chunk(std::string("Uncompressed"));
auto const signature = base16_literal(SIGNATURE_WIF_UNCOMPRESSED);
REQUIRE(verify_message(message, address, signature));
}

TEST_CASE("message verify message electrum compressed okay", "[message verify message]") {
TEST_CASE("message verify message electrum compressed okay", "[message verify message]") {
message_signature signature;
REQUIRE(decode_base16(signature, ELECTRUM_SIGNATURE));

// Address of the compressed public key of the message signer.
const payment_address address("1PeChFbhxDD9NLbU21DfD55aQBC4ZTR3tE");
payment_address const address("1PeChFbhxDD9NLbU21DfD55aQBC4ZTR3tE");
auto const message = to_chunk(std::string("Nakomoto"));
REQUIRE(verify_message(message, address, signature));
}

TEST_CASE("message verify message electrum incorrect address false", "[message verify message]") {
TEST_CASE("message verify message electrum incorrect address false", "[message verify message]") {
message_signature signature;
REQUIRE(decode_base16(signature, ELECTRUM_SIGNATURE));

// Address of the uncompressed public key of the message signer (incorrect).
const payment_address address("1Em1SX7qQq1pTmByqLRafhL1ypx2V786tP");
payment_address const address("1Em1SX7qQq1pTmByqLRafhL1ypx2V786tP");
auto const message = to_chunk(std::string("Nakomoto"));
REQUIRE( ! verify_message(message, address, signature));
}
Expand Down
2 changes: 1 addition & 1 deletion test/wallet/stealth_receiver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ TEST_CASE("stealth receiver exchange between sender and receiver always round

// The receiver now has the stealth private key and the send address.
REQUIRE(encode_base16(receiver_private) == RECEIVER_PRIVATE);
REQUIRE(payment_address(receiver_public, version) == derived_address);
REQUIRE(payment_address(ec_public{receiver_public}, version) == derived_address);
}

// End Test Suite
Loading