diff --git a/binding.gyp b/binding.gyp index dd946b1..2d6fe0e 100644 --- a/binding.gyp +++ b/binding.gyp @@ -7,6 +7,7 @@ "src/cryptonote_core/cryptonote_format_utils.cpp", "src/offshore/pricing_record.cpp", "src/zephyr_oracle/pricing_record.cpp", + "src/salvium_oracle/pricing_record.cpp", "src/crypto/tree-hash.c", "src/crypto/crypto.cpp", "src/crypto/crypto-ops.c", diff --git a/package.json b/package.json index 8911d37..442f5d6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cryptoforknote-util", - "version": "15.5.3", + "version": "15.5.4", "author": { "name": "LucasJones", "email": "lucasjonesdev@hotmail.co.uk" diff --git a/src/cryptonote_core/cryptonote_basic.h b/src/cryptonote_core/cryptonote_basic.h index 66b9acd..69f5a51 100644 --- a/src/cryptonote_core/cryptonote_basic.h +++ b/src/cryptonote_core/cryptonote_basic.h @@ -28,6 +28,7 @@ #include "cryptonote_protocol/blobdatatype.h" #include "offshore/pricing_record.h" #include "zephyr_oracle/pricing_record.h" +#include "salvium_oracle/pricing_record.h" namespace cryptonote @@ -1051,6 +1052,7 @@ namespace cryptonote uint64_t nonce8; offshore::pricing_record pricing_record; zephyr_oracle::pricing_record zephyr_pricing_record; + salvium_oracle::pricing_record salvium_pricing_record; crypto::cycle cycle; crypto::cycle40 cycle40; crypto::cycle48 cycle48; @@ -1075,8 +1077,9 @@ namespace cryptonote if (blob_type == BLOB_TYPE_CRYPTONOTE_XTNC || blob_type == BLOB_TYPE_CRYPTONOTE_CUCKOO) FIELD(cycle) if (blob_type == BLOB_TYPE_CRYPTONOTE_TUBE) FIELD(cycle40) if (blob_type == BLOB_TYPE_CRYPTONOTE_XTA) FIELD(cycle48) - if (blob_type == BLOB_TYPE_CRYPTONOTE_XHV || blob_type == BLOB_TYPE_CRYPTONOTE_SALVIUM) FIELD(pricing_record) - if (blob_type == BLOB_TYPE_CRYPTONOTE_ZEPHYR) { + if (blob_type == BLOB_TYPE_CRYPTONOTE_XHV) FIELD(pricing_record) + else if (blob_type == BLOB_TYPE_CRYPTONOTE_SALVIUM) FIELD(salvium_pricing_record) + else if (blob_type == BLOB_TYPE_CRYPTONOTE_ZEPHYR) { if (major_version >= 4) { FIELD_N("pricing_record", zephyr_pricing_record) diff --git a/src/salvium_oracle/asset_types.h b/src/salvium_oracle/asset_types.h new file mode 100644 index 0000000..f8cf135 --- /dev/null +++ b/src/salvium_oracle/asset_types.h @@ -0,0 +1,77 @@ +// Copyright (c) 2021, Haven Protocol +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#pragma once +#include +#include + +namespace salvium_oracle { + + const std::vector ASSET_TYPES = {"SAL", "VSD", "BURN"}; + + class asset_type_counts + { + + public: + + // Fields + uint64_t SAL; + uint64_t VSD; + uint64_t BURN; + + asset_type_counts() noexcept + : SAL(0) + , VSD(0) + , BURN(0) + { + } + + uint64_t operator[](const std::string asset_type) const noexcept + { + if (asset_type == "SAL") { + return SAL; + } else if (asset_type == "VSD") { + return VSD; + } else if (asset_type == "BURN") { + return BURN; + } + + return 0; + } + + void add(const std::string asset_type, const uint64_t val) + { + if (asset_type == "SAL") { + SAL += val; + } else if (asset_type == "VSD") { + VSD += val; + } else if (asset_type == "BURN") { + BURN += val; + } + } + }; +} diff --git a/src/salvium_oracle/pricing_record.cpp b/src/salvium_oracle/pricing_record.cpp new file mode 100644 index 0000000..5c3f117 --- /dev/null +++ b/src/salvium_oracle/pricing_record.cpp @@ -0,0 +1,316 @@ +// Copyright (c) 2019, Haven Protocol +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Portions of this code based upon code Copyright (c) 2019, The Monero Project + +#include +#include "pricing_record.h" + +#include "serialization/keyvalue_serialization.h" +#include "storages/portable_storage.h" + +#include "string_tools.h" +namespace salvium_oracle +{ + + namespace + { + struct asset_data_serialized + { + std::string asset_type; + uint64_t spot_price; + uint64_t ma_price; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(asset_type) + KV_SERIALIZE(spot_price) + KV_SERIALIZE(ma_price) + END_KV_SERIALIZE_MAP() + }; + + struct supply_data_serialized + { + uint64_t SAL; + uint64_t VSD; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(SAL) + KV_SERIALIZE(VSD) + END_KV_SERIALIZE_MAP() + }; + + struct pr_serialized + { + uint64_t pr_version; + uint64_t height; + supply_data supply; + std::vector assets; + uint64_t timestamp; + std::string signature; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(pr_version) + KV_SERIALIZE(height) + KV_SERIALIZE(supply) + KV_SERIALIZE(assets) + KV_SERIALIZE(timestamp) + KV_SERIALIZE(signature) + END_KV_SERIALIZE_MAP() + }; + } + + pricing_record::pricing_record() noexcept + : pr_version(0) + , height(0) + , supply() + , assets() + , timestamp(0) + , signature() + { + } + + pricing_record::~pricing_record() noexcept + { + } + + bool supply_data::_load(epee::serialization::portable_storage& src, epee::serialization::section* hparent) + { + supply_data_serialized in{}; + if (in._load(src, hparent)) + { + // Copy everything into the local instance + sal = in.SAL; + vsd = in.VSD; + return true; + } + // Report error here? + return false; + } + + bool supply_data::store(epee::serialization::portable_storage& dest, epee::serialization::section* hparent) const + { + const supply_data_serialized out{sal, vsd}; + return out.store(dest, hparent); + } + + bool asset_data::_load(epee::serialization::portable_storage& src, epee::serialization::section* hparent) + { + asset_data_serialized in{}; + if (in._load(src, hparent)) + { + // Copy everything into the local instance + asset_type = in.asset_type; + spot_price = in.spot_price; + ma_price = in.ma_price; + return true; + } + // Report error here? + return false; + } + + bool asset_data::store(epee::serialization::portable_storage& dest, epee::serialization::section* hparent) const + { + const asset_data_serialized out{asset_type, spot_price, ma_price}; + return out.store(dest, hparent); + } + + bool pricing_record::_load(epee::serialization::portable_storage& src, epee::serialization::section* hparent) + { + pr_serialized in{}; + if (in._load(src, hparent)) + { + // Copy everything into the local instance + pr_version = in.pr_version; + height = in.height; + supply = in.supply; + assets = in.assets; + timestamp = in.timestamp; + + // Signature arrives in HEX format, but needs to be used in BINARY format - convert it here + signature.resize(0); + assert(in.signature.size()%2 == 0); + signature.reserve(in.signature.size() >> 1); + for (unsigned int i = 0; i < in.signature.size(); i += 2) { + std::string byteString = in.signature.substr(i, 2); + signature.emplace_back((uint8_t)strtol(byteString.c_str(), NULL, 16)); + } + return true; + } + + // Report error here? + return false; + } + + bool pricing_record::store(epee::serialization::portable_storage& dest, epee::serialization::section* hparent) const + { + std::string sig_hex; + for (size_t i=0; iempty()) + return false; + } + + if (this->empty()) + return true; + + if (!verifySignature(get_config(nettype).ORACLE_PUBLIC_KEY)) { + LOG_ERROR("Invalid pricing record signature."); + return false; + } + + // validate the timestmap + if (this->timestamp > bl_timestamp + PRICING_RECORD_VALID_TIME_DIFF_FROM_BLOCK) { + LOG_ERROR("Pricing record timestamp is too far in the future."); + return false; + } + + if (this->timestamp <= last_bl_timestamp) { + LOG_ERROR("Pricing record timestamp: " << this->timestamp << ", block timestamp: " << bl_timestamp); + LOG_ERROR("Pricing record timestamp is too old."); + return false; + } + + return true; + } +} diff --git a/src/salvium_oracle/pricing_record.h b/src/salvium_oracle/pricing_record.h new file mode 100644 index 0000000..4b99523 --- /dev/null +++ b/src/salvium_oracle/pricing_record.h @@ -0,0 +1,160 @@ +// Copyright (c) 2019, Haven Protocol +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Portions of this code based upon code Copyright (c) 2019, The Monero Project + +#pragma once +#include "common/pod-class.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "cryptonote_config.h" +#include "crypto/hash.h" + +namespace epee +{ + namespace serialization + { + class portable_storage; + struct section; + } +} + +namespace salvium_oracle +{ + #pragma pack(push, 1) + POD_CLASS pricing_record_pre { + uint64_t pr_version; + uint64_t price; + uint64_t timestamp; + }; + #pragma pack(pop) + + struct supply_data { + uint64_t sal; + uint64_t vsd; + + //! Load from epee p2p format + bool _load(epee::serialization::portable_storage& src, epee::serialization::section* hparent); + //! Store in epee p2p format + bool store(epee::serialization::portable_storage& dest, epee::serialization::section* hparent) const; + + BEGIN_SERIALIZE_OBJECT() + VARINT_FIELD(sal) + VARINT_FIELD(vsd) + END_SERIALIZE() + }; + + inline bool operator==(const supply_data& a, const supply_data& b) noexcept + { + return (a.sal == b.sal && + a.vsd == b.vsd); + } + + struct asset_data { + std::string asset_type; + uint64_t spot_price; + uint64_t ma_price; + + //! Load from epee p2p format + bool _load(epee::serialization::portable_storage& src, epee::serialization::section* hparent); + //! Store in epee p2p format + bool store(epee::serialization::portable_storage& dest, epee::serialization::section* hparent) const; + + BEGIN_SERIALIZE_OBJECT() + FIELD(asset_type) + VARINT_FIELD(spot_price) + VARINT_FIELD(ma_price) + END_SERIALIZE() + }; + + inline bool operator==(const asset_data& a, const asset_data& b) noexcept + { + return (a.asset_type == b.asset_type && + a.spot_price == b.spot_price && + a.ma_price == b.ma_price); + } + + struct pricing_record + { + // Fields + uint64_t pr_version; + uint64_t height; + supply_data supply; + std::vector assets; + uint64_t timestamp; + std::vector signature; + + // Default c'tor + pricing_record() noexcept; + //! Load from epee p2p format + bool _load(epee::serialization::portable_storage& src, epee::serialization::section* hparent); + //! Store in epee p2p format + bool store(epee::serialization::portable_storage& dest, epee::serialization::section* hparent) const; + pricing_record(const pricing_record& orig) noexcept; + ~pricing_record() noexcept; + bool equal(const pricing_record& other) const noexcept; + bool empty() const noexcept; + bool verifySignature(const std::string& public_key) const; + bool valid(cryptonote::network_type nettype, uint32_t hf_version, uint64_t bl_timestamp, uint64_t last_bl_timestamp) const; + + pricing_record& operator=(const pricing_record& orig) noexcept; + uint64_t operator[](const std::string& asset_type) const; + + BEGIN_SERIALIZE_OBJECT() + VARINT_FIELD(pr_version) + VARINT_FIELD(height) + FIELD(supply) + FIELD(assets) + VARINT_FIELD(timestamp) + FIELD(signature) + END_SERIALIZE() + }; + + inline bool operator==(const pricing_record& a, const pricing_record& b) noexcept + { + return a.equal(b); + } + + inline bool operator!=(const pricing_record& a, const pricing_record& b) noexcept + { + return !a.equal(b); + } + +} // salvium_oracle