Skip to content

Commit

Permalink
Merge pull request #40 from k-nuth/feat/improve-type-system
Browse files Browse the repository at this point in the history
feat: improve type system in domain
  • Loading branch information
fpelliccioni authored Nov 21, 2024
2 parents 06153cc + 0db6333 commit bc4027a
Show file tree
Hide file tree
Showing 11 changed files with 60 additions and 69 deletions.
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

0 comments on commit bc4027a

Please sign in to comment.