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

Update zephyr-cryptoforknote-util #2

Merged
merged 1 commit into from
Jul 28, 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
18 changes: 16 additions & 2 deletions src/Native/libcryptonote/cryptonote_core/cryptonote_basic.h
Original file line number Diff line number Diff line change
Expand Up @@ -659,10 +659,24 @@ namespace cryptonote
if (blob_type == BLOB_TYPE_CRYPTONOTE_XHV) FIELD(pricing_record)

if (blob_type == BLOB_TYPE_CRYPTONOTE_ZEPHYR) {
if (major_version >= 3)
if (major_version >= 4)
{
FIELD_N("pricing_record", zephyr_pricing_record)
}
else if (major_version >= 3)
{
zephyr_oracle::pricing_record_v2 pr_v2;
if (!typename Archive<W>::is_saving())
{
FIELD(pr_v2)
pr_v2.write_to_pr(zephyr_pricing_record);
}
else
{
pr_v2.read_from_pr(zephyr_pricing_record);
FIELD(pr_v2)
}
}
else
{
zephyr_oracle::pricing_record_v1 pr_v1;
Expand Down Expand Up @@ -777,4 +791,4 @@ VARIANT_TAG(binary_archive, cryptonote::txout_to_tagged_key, 0x3);
VARIANT_TAG(binary_archive, cryptonote::txout_offshore, 0x3);
VARIANT_TAG(binary_archive, cryptonote::txout_xasset, 0x5);
VARIANT_TAG(binary_archive, cryptonote::transaction, 0xcc);
VARIANT_TAG(binary_archive, cryptonote::block, 0xbb);
VARIANT_TAG(binary_archive, cryptonote::block, 0xbb);
75 changes: 63 additions & 12 deletions src/Native/libcryptonote/serialization/zephyr_pricing_record.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,31 +40,46 @@
template <template <bool> class Archive>
bool do_serialize(Archive<false> &ar, zephyr_oracle::pricing_record &pr, uint8_t version)
{
if (version < 3)
if (version >= 4)
{
// very basic sanity check
if (ar.remaining_bytes() < sizeof(zephyr_oracle::pricing_record_v1)) {
if (ar.remaining_bytes() < sizeof(zephyr_oracle::pricing_record)) {
return false;
}

zephyr_oracle::pricing_record_v1 pr_v1;
ar.serialize_blob(&pr_v1, sizeof(zephyr_oracle::pricing_record_v1), "");
ar.serialize_blob(&pr, sizeof(zephyr_oracle::pricing_record), "");
if (!ar.good())
return false;
}
else if (version >= 3)
{
// very basic sanity check
if (ar.remaining_bytes() < sizeof(zephyr_oracle::pricing_record_v2)) {
return false;
}

zephyr_oracle::pricing_record_v2 pr_v2;
ar.serialize_blob(&pr_v2, sizeof(zephyr_oracle::pricing_record_v2), "");
if (!ar.good())
return false;

if (!pr_v1.write_to_pr(pr))
if (!pr_v2.write_to_pr(pr))
return false;
}
else
{
// very basic sanity check
if (ar.remaining_bytes() < sizeof(zephyr_oracle::pricing_record)) {
if (ar.remaining_bytes() < sizeof(zephyr_oracle::pricing_record_v1)) {
return false;
}

ar.serialize_blob(&pr, sizeof(zephyr_oracle::pricing_record), "");
zephyr_oracle::pricing_record_v1 pr_v1;
ar.serialize_blob(&pr_v1, sizeof(zephyr_oracle::pricing_record_v1), "");
if (!ar.good())
return false;

if (!pr_v1.write_to_pr(pr))
return false;
}

return true;
Expand All @@ -76,16 +91,23 @@ bool do_serialize(Archive<true> &ar, zephyr_oracle::pricing_record &pr, uint8_t
{
ar.begin_string();

if (version < 3)
if (version >= 4)
{
zephyr_oracle::pricing_record_v1 pr_v1;
if (!pr_v1.read_from_pr(pr))
ar.serialize_blob(&pr, sizeof(zephyr_oracle::pricing_record), "");
}
else if (version >= 3)
{
zephyr_oracle::pricing_record_v2 pr_v2;
if (!pr_v2.read_from_pr(pr))
return false;
ar.serialize_blob(&pr_v1, sizeof(zephyr_oracle::pricing_record_v1), "");
ar.serialize_blob(&pr_v2, sizeof(zephyr_oracle::pricing_record_v2), "");
}
else
{
ar.serialize_blob(&pr, sizeof(zephyr_oracle::pricing_record), "");
zephyr_oracle::pricing_record_v1 pr_v1;
if (!pr_v1.read_from_pr(pr))
return false;
ar.serialize_blob(&pr_v1, sizeof(zephyr_oracle::pricing_record_v1), "");
}

if (!ar.good())
Expand Down Expand Up @@ -122,5 +144,34 @@ bool do_serialize(Archive<true> &ar, zephyr_oracle::pricing_record_v1 &pr, uint8
return true;
}

// read
template <template <bool> class Archive>
bool do_serialize(Archive<false> &ar, zephyr_oracle::pricing_record_v2 &pr, uint8_t version)
{
// very basic sanity check
if (ar.remaining_bytes() < sizeof(zephyr_oracle::pricing_record_v2)) {
return false;
}

ar.serialize_blob(&pr, sizeof(zephyr_oracle::pricing_record_v2), "");
if (!ar.good())
return false;

return true;
}

// write
template <template <bool> class Archive>
bool do_serialize(Archive<true> &ar, zephyr_oracle::pricing_record_v2 &pr, uint8_t version)
{
ar.begin_string();
ar.serialize_blob(&pr, sizeof(zephyr_oracle::pricing_record_v2), "");
if (!ar.good())
return false;
ar.end_string();
return true;
}

BLOB_SERIALIZER(zephyr_oracle::pricing_record);
BLOB_SERIALIZER(zephyr_oracle::pricing_record_v1);
BLOB_SERIALIZER(zephyr_oracle::pricing_record_v2);
52 changes: 42 additions & 10 deletions src/Native/libcryptonote/zephyr_oracle/pricing_record.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ namespace zephyr_oracle
uint64_t stable_ma;
uint64_t reserve;
uint64_t reserve_ma;
uint64_t reserve_ratio;
uint64_t reserve_ratio_ma;
uint64_t timestamp;
std::string signature;

Expand All @@ -56,6 +58,8 @@ namespace zephyr_oracle
KV_SERIALIZE(stable_ma)
KV_SERIALIZE(reserve)
KV_SERIALIZE(reserve_ma)
KV_SERIALIZE(reserve_ratio)
KV_SERIALIZE(reserve_ratio_ma)
KV_SERIALIZE(timestamp)
KV_SERIALIZE(signature)
END_KV_SERIALIZE_MAP()
Expand All @@ -69,6 +73,8 @@ namespace zephyr_oracle
, stable_ma(0)
, reserve(0)
, reserve_ma(0)
, reserve_ratio(0)
, reserve_ratio_ma(0)
, timestamp(0)
{
std::memset(signature, 0, sizeof(signature));
Expand All @@ -86,6 +92,8 @@ namespace zephyr_oracle
stable_ma = in.stable_ma;
reserve = in.reserve;
reserve_ma = in.reserve_ma;
reserve_ratio = in.reserve_ratio;
reserve_ratio_ma = in.reserve_ratio_ma;
timestamp = in.timestamp;
for (unsigned int i = 0; i < in.signature.length(); i += 2) {
std::string byteString = in.signature.substr(i, 2);
Expand All @@ -106,7 +114,7 @@ namespace zephyr_oracle
ss << std::hex << std::setw(2) << std::setfill('0') << (0xff & signature[i]);
sig_hex += ss.str();
}
const pr_serialized out{spot,moving_average,stable,stable_ma,reserve,reserve_ma,timestamp,sig_hex};
const pr_serialized out{spot,moving_average,stable,stable_ma,reserve,reserve_ma,reserve_ratio,reserve_ratio_ma,timestamp,sig_hex};
return out.store(dest, hparent);
}

Expand All @@ -117,6 +125,8 @@ namespace zephyr_oracle
, stable_ma(orig.stable_ma)
, reserve(orig.reserve)
, reserve_ma(orig.reserve_ma)
, reserve_ratio(orig.reserve_ratio)
, reserve_ratio_ma(orig.reserve_ratio_ma)
, timestamp(orig.timestamp)
{
std::memcpy(signature, orig.signature, sizeof(signature));
Expand All @@ -130,6 +140,8 @@ namespace zephyr_oracle
stable_ma = orig.stable_ma;
reserve = orig.reserve;
reserve_ma = orig.reserve_ma;
reserve_ratio = orig.reserve_ratio;
reserve_ratio_ma = orig.reserve_ratio_ma;
timestamp = orig.timestamp;
::memcpy(signature, orig.signature, sizeof(signature));
return *this;
Expand All @@ -143,6 +155,8 @@ namespace zephyr_oracle
(stable_ma == other.stable_ma) &&
(reserve == other.reserve) &&
(reserve_ma == other.reserve_ma) &&
(reserve_ratio == other.reserve_ratio) &&
(reserve_ratio_ma == other.reserve_ratio_ma) &&
(timestamp == other.timestamp) &&
!::memcmp(signature, other.signature, sizeof(signature)));
}
Expand All @@ -153,7 +167,7 @@ namespace zephyr_oracle
return (*this).equal(empty_pr);
}

bool pricing_record::verifySignature(const std::string& public_key) const
bool pricing_record::verifySignature(const std::string& public_key, const uint8_t hf_version) const
{
CHECK_AND_ASSERT_THROW_MES(!public_key.empty(), "Pricing record verification failed. NULL public key. PK Size: " << public_key.size()); // TODO: is this necessary or the one below already covers this case, meannin it will produce empty pubkey?

Expand All @@ -178,7 +192,9 @@ namespace zephyr_oracle
// Build the JSON string, so that we can verify the signature
std::ostringstream oss;
oss << "{\"spot\":" << spot;
oss << ",\"moving_average\":" << moving_average;
if (hf_version <= 4) {
oss << ",\"moving_average\":" << moving_average;
}
oss << ",\"timestamp\":" << timestamp;
oss << "}";
std::string message = oss.str();
Expand Down Expand Up @@ -210,9 +226,24 @@ namespace zephyr_oracle
return false;
}

bool pricing_record::has_missing_rates() const noexcept
bool pricing_record::has_missing_rates(const uint8_t hf_version) const noexcept
{
bool missing_rates = (spot == 0) || (moving_average == 0) || (stable == 0) || (stable_ma == 0) || (reserve == 0) || (reserve_ma == 0);
if (hf_version <= 3) {
return missing_rates;
} else if (hf_version <= 4) {
return missing_rates || (reserve_ratio == 0);
}
return missing_rates || (reserve_ratio == 0) || (reserve_ratio_ma == 0);
}

bool pricing_record::has_essential_rates(const uint8_t hf_version) const noexcept
{
return (spot == 0) || (moving_average == 0) || (stable == 0) || (stable_ma == 0) || (reserve == 0) || (reserve_ma == 0);
bool essential_rates = (spot != 0) && (stable != 0) && (reserve != 0);
if (hf_version <= 3) {
return essential_rates;
}
return essential_rates && (reserve_ratio != 0);
}

// overload for pr validation for block
Expand All @@ -226,17 +257,19 @@ namespace zephyr_oracle
if (this->empty())
return true;

if (this->has_missing_rates()) {
LOG_ERROR("Pricing record has missing rates.");
return false;
if (this->has_missing_rates(hf_version)) {
if (hf_version < 4 || !this->has_essential_rates(hf_version)) {
LOG_ERROR("Pricing record has missing rates.");
return false;
}
}

std::string const MAINNET_ORACLE_PUBLIC_KEY = "-----BEGIN PUBLIC KEY-----\n"
"MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAO5hVuc6ylYMbj3WhqOMoAcJ0SD4e3zW\n"
"edsUmhQeYwBkelAaFyxhX4ZotP+b/cFr2mX5iuND1znEnMZkyg+YmtkCAwEAAQ==\n"
"-----END PUBLIC KEY-----\n";

if (!verifySignature(MAINNET_ORACLE_PUBLIC_KEY)) {
if (!verifySignature(MAINNET_ORACLE_PUBLIC_KEY, hf_version)) {
LOG_ERROR("Invalid pricing record signature.");
return false;
}
Expand All @@ -256,4 +289,3 @@ namespace zephyr_oracle
return true;
}
}

61 changes: 58 additions & 3 deletions src/Native/libcryptonote/zephyr_oracle/pricing_record.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,16 @@ namespace zephyr_oracle
uint64_t zEPHRSV;
uint64_t timestamp;
};
POD_CLASS pricing_record_pre_v2 {
uint64_t spot;
uint64_t moving_average;
uint64_t stable;
uint64_t stable_ma;
uint64_t reserve;
uint64_t reserve_ma;
uint64_t timestamp;
unsigned char signature[64];
};
#pragma pack(pop)
class pricing_record
{
Expand All @@ -76,6 +86,8 @@ namespace zephyr_oracle
uint64_t stable_ma;
uint64_t reserve;
uint64_t reserve_ma;
uint64_t reserve_ratio;
uint64_t reserve_ratio_ma;
uint64_t timestamp;
unsigned char signature[64];

Expand All @@ -89,8 +101,9 @@ namespace zephyr_oracle
~pricing_record() = default;
bool equal(const pricing_record& other) const noexcept;
bool empty() const noexcept;
bool verifySignature(const std::string& public_key) const;
bool has_missing_rates() const noexcept;
bool verifySignature(const std::string& public_key, const uint8_t hf_version) const;
bool has_missing_rates(const uint8_t hf_version) const noexcept;
bool has_essential_rates(const uint8_t hf_version) const noexcept;
bool valid(uint32_t hf_version, uint64_t bl_timestamp, uint64_t last_bl_timestamp) const;

pricing_record& operator=(const pricing_record& orig) noexcept;
Expand Down Expand Up @@ -137,4 +150,46 @@ namespace zephyr_oracle
};
};

} // oracle
class pricing_record_v2
{

public:
uint64_t spot;
uint64_t moving_average;
uint64_t stable;
uint64_t stable_ma;
uint64_t reserve;
uint64_t reserve_ma;
uint64_t timestamp;
unsigned char signature[64];

bool write_to_pr(zephyr_oracle::pricing_record &pr)
{
pr.spot = spot;
pr.moving_average = moving_average;
pr.stable = stable;
pr.stable_ma = stable_ma;
pr.reserve = reserve;
pr.reserve_ma = reserve_ma;
pr.reserve_ratio = 0;
pr.reserve_ratio_ma = 0;
pr.timestamp = timestamp;
std::memcpy(pr.signature, signature, sizeof(pr.signature));
return true;
};

bool read_from_pr(zephyr_oracle::pricing_record &pr)
{
spot = pr.spot;
moving_average = pr.moving_average;
stable = pr.stable;
stable_ma = pr.stable_ma;
reserve = pr.reserve;
reserve_ma = pr.reserve_ma;
timestamp = pr.timestamp;
std::memcpy(signature, pr.signature, sizeof(signature));
return true;
};
};

} // oracle
Loading