Compare commits

..

1 Commits

Author SHA1 Message Date
Some Random Crypto Guy 861df8283c fixed 'make depends' building 2025-07-18 09:42:24 +01:00
165 changed files with 40969 additions and 52268 deletions
+4 -4
View File
@@ -22,7 +22,7 @@ env:
jobs:
build-cross:
runs-on: ubuntu-22.04
runs-on: ubuntu-20.04
env:
CCACHE_TEMPDIR: /tmp/.ccache-temp
strategy:
@@ -52,10 +52,10 @@ jobs:
packages: "gperf cmake python3-zmq libdbus-1-dev libharfbuzz-dev"
- name: "Cross-Mac x86_64"
host: "x86_64-apple-darwin"
packages: "cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools python3-dev python3-setuptools-git"
packages: "cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools python-dev python3-setuptools-git"
- name: "Cross-Mac aarch64"
host: "aarch64-apple-darwin"
packages: "cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools python3-dev python3-setuptools-git"
packages: "cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools python-dev python3-setuptools-git"
- name: "x86_64 Freebsd"
host: "x86_64-unknown-freebsd"
packages: "clang-8 gperf cmake python3-zmq libdbus-1-dev libharfbuzz-dev"
@@ -105,7 +105,7 @@ jobs:
${{env.CCACHE_SETTINGS}}
make depends target=${{ matrix.toolchain.host }} -j2
- uses: actions/upload-artifact@v4
if: ${{ matrix.toolchain.host == 'x86_64-w64-mingw32' || matrix.toolchain.host == 'x86_64-apple-darwin' || matrix.toolchain.host == 'aarch64-apple-darwin' || matrix.toolchain.host == 'x86_64-unknown-linux-gnu' || matrix.toolchain.host == 'aarch64-linux-gnu' }}
if: ${{ matrix.toolchain.host == 'x86_64-w64-mingw32' || matrix.toolchain.host == 'x86_64-apple-darwin' || matrix.toolchain.host == 'aarch64-apple-darwin' || matrix.toolchain.host == 'x86_64-unknown-linux-gnu' }}
with:
name: ${{ matrix.toolchain.name }}
path: |
-37
View File
@@ -1,37 +0,0 @@
# Use Ubuntu 24.04 as base
FROM ubuntu:24.04 AS builder
ENV DEBIAN_FRONTEND=noninteractive
# Install build dependencies including cross-compilers
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential cmake pkg-config git imagemagick libcap-dev librsvg2-bin libz-dev \
g++-mingw-w64-x86-64 clang gcc-arm-none-eabi binutils-x86-64-linux-gnu libtiff-tools \
g++-x86-64-linux-gnu gcc-x86-64-linux-gnu binutils-aarch64-linux-gnu \
g++-aarch64-linux-gnu gcc-aarch64-linux-gnu crossbuild-essential-amd64 \
libssl-dev libzmq3-dev libunbound-dev libsodium-dev libunwind8-dev liblzma-dev \
libreadline-dev libexpat1-dev libpgm-dev qttools5-dev-tools libhidapi-dev libusb-1.0-0-dev \
libprotobuf-dev protobuf-compiler libudev-dev libboost-all-dev python3 ccache doxygen graphviz \
ca-certificates curl zip libtool gperf automake autoconf \
&& rm -rf /var/lib/apt/lists/*
# Clone the develop branch
WORKDIR /opt
RUN git clone --recursive -b develop https://github.com/salvium/salvium.git
WORKDIR /opt/salvium
# make the script runnable
RUN chmod +x make_releases.sh
# Make sure the output folder exists
RUN mkdir ~/releases
# Expose the releases directory for copying zip files to the host
VOLUME ["~/releases"]
ENTRYPOINT ["/opt/salvium/make_releases.sh"]
# To access the generated zip files on your host, run the container with:
# docker run -v ~/releases:/root/releases <image>
# This will copy the zip files to your host's ~/salvium-releases directory.
+7 -7
View File
@@ -1,6 +1,6 @@
# Salvium One v1.1.1
# Salvium Zero v0.9.9
Copyright (c) 2023-2025, Salvium
Copyright (c) 2023-2024, Salvium
Portions Copyright (c) 2014-2023, The Monero Project
Portions Copyright (c) 2012-2013 The Cryptonote developers.
@@ -47,7 +47,7 @@ As with many development projects, the repository on GitHub is considered to be
## Supporting the project
Salvium is a 100% community-sponsored endeavor. If you want to join our efforts, the easiest thing you can do is support the project financially. Go to [https://salvium.io/donate](https://salvium.io/donate) for more information.
Salvium is a 100% community-sponsored endeavor. If you want to join our efforts, the easiest thing you can do is support the project financially. Go to [https://salvium.io/donate/](https://salvium.io/donate/) for more information.
## License
@@ -172,7 +172,7 @@ invokes cmake commands as needed.
```bash
cd salvium
git checkout v1.1.1
git checkout v0.9.9
make
```
@@ -251,7 +251,7 @@ Tested on a Raspberry Pi Zero with a clean install of minimal Raspbian Stretch (
```bash
git clone https://github.com/salvium/salvium
cd salvium
git checkout v1.1.1
git checkout v0.9.9
```
* Build:
@@ -370,10 +370,10 @@ application.
cd salvium
```
* If you would like a specific [version/tag](https://github.com/salvium/salvium/tags), do a git checkout for that version. eg. 'v1.1.1'. If you don't care about the version and just want binaries from master, skip this step:
* If you would like a specific [version/tag](https://github.com/salvium/salvium/tags), do a git checkout for that version. eg. 'v0.9.9'. If you don't care about the version and just want binaries from master, skip this step:
```bash
git checkout v1.1.1
git checkout v0.9.9
```
* If you are on a 64-bit system, run:
+1 -1
View File
@@ -6,7 +6,7 @@ macro(CHECK_LINKER_FLAG flag VARIABLE)
message(STATUS "Looking for ${flag} linker flag")
endif()
set(_cle_source ${CMAKE_CURRENT_SOURCE_DIR}/cmake/CheckLinkerFlag.c)
set(_cle_source ${CMAKE_SOURCE_DIR}/cmake/CheckLinkerFlag.c)
set(saved_CMAKE_C_FLAGS ${CMAKE_C_FLAGS})
set(CMAKE_C_FLAGS "${flag}")
+1 -1
View File
@@ -19,7 +19,7 @@ mingw32_native_packages :=
mingw32_packages = icu4c libiconv
linux_native_packages :=
linux_packages := eudev
linux_packages :=
freebsd_native_packages := freebsd_base
freebsd_packages :=
-5
View File
@@ -1,5 +0,0 @@
48417220800f174a3613881a56131d25c49d344228fca124c8331e0b58a8ff06 salvium-v1.0.7-ubuntu22.04-linux-x86_64.zip
52226551a9e1842df46cf068292cfa3c1e05328e0695cf6723365d4401af19a6 salvium-v1.0.7-ubuntu22.04-linux-aarch64.zip
b40c3765479c9d5712e766ddd01314b63e5080472b7639d34388e6b74b36142e salvium-v1.0.7-macos-x86_64.zip
60b05548f69040fe901e336e8fc4189a1028a8d7ded09bad555b3c854a0e8d6e salvium-v1.0.7-macos-aarch64.zip
b2c3e0bb8254ad1f62a78d6670c6e5adba1e42bb823919faad1cbf5796d53910 salvium-v1.0.7-win64.zip
-5
View File
@@ -1,5 +0,0 @@
e032e42ebac862bf90d71f0a231d9f3ddb5583e321ec153ee05144d87629980b salvium-v1.1.0-macos-aarch64.zip
0f31f09cf7be38b50a35510172bc94b7a4fb07c7107c79c4f055754c282c99f5 salvium-v1.1.0-macos-x86_64.zip
4424fd93391daab7eee47c54ab7aad7810a16f4c866209d41ba016d984605ffb salvium-v1.1.0-ubuntu22.04-linux-aarch64.zip
d1a5138f892189dfccc1d51d72ce24147fe6f1a2a5d465d350651426a71282a4 salvium-v1.1.0-ubuntu22.04-linux-x86_64.zip
bb9c9175726b82e061a6a332a27a6845805be4779928df3abbbd5c0f54691c9a salvium-v1.1.0-win64.zip
-5
View File
@@ -1,5 +0,0 @@
d0a8b0515ae2ee79849cbc17b0639bb7859e30efcd50e5b058540874cd0919ce salvium-v1.1.0-rc4-ubuntu22.04-linux-x86_64.zip
6528b8b23f09c574fc9383b48b88e87f99609ff5ce1b727872b5554505a69d77 salvium-v1.1.0-rc4-ubuntu22.04-linux-aarch64.zip
00ca183c47f852b8b30e4b87ce3b3536a0e97866e6027bf25d389b4a1bc9c471 salvium-v1.1.0-rc4-macos-x86_64.zip
50480b1043e9b5901576ab45f926b0b51a5d21237c6da549603ad1f13819e6ed salvium-v1.1.0-rc4-macos-aarch64.zip
adf96eee17e16f318fc047721acb5bfa8ae7ed1c0ff8d022da8ab5df64d8ce3f salvium-v1.1.0-rc4-win64.zip
-5
View File
@@ -1,5 +0,0 @@
23a03277e922c3f41ba6ddb0efc7581c3287d9f3faa2ddd19cc2d018a6797701 salvium-v1.1.0-rc5-ubuntu22.04-linux-x86_64.zip
94409b190eae890792b2d04cfffe148828dc23d658cd54a8d7802b12a9f274a4 salvium-v1.1.0-rc5-ubuntu22.04-linux-aarch64.zip
76cc02603cb21cd0729f0e5c9a39bb32310428b15580458ec8d74dcba39c9319 salvium-v1.1.0-rc5-macos-x86_64.zip
dc477718bfb370ecbafebf3e1736df5978200302f13542374f1b1fd43e07ab45 salvium-v1.1.0-rc5-macos-aarch64.zip
0e9b81eeaa32a4709a1cbd4c198721455a3c8cc86c1f1915cfc74af7885f8fee salvium-v1.1.0-rc5-win64.zip
-5
View File
@@ -1,5 +0,0 @@
b712adec8fa6bbcbe461b0748649e4c9e4fb61934fc1adb064779afed28c0758 salvium-v1.1.0-rc6-macos-aarch64.zip
8635955ff784f936a8b8de5be267e5dcdc0b55dfbf0b6f65ba24d098d8b8ab00 salvium-v1.1.0-rc6-macos-x86_64.zip
79b65ba9a074aeba87f03d83a07c3a6c51815d376049b3136a38c1a33260bfac salvium-v1.1.0-rc6-ubuntu22.04-linux-aarch64.zip
9031763ad60d1c8c572c76c5cb51a96b1680b9708c287264388f3d411bda464f salvium-v1.1.0-rc6-ubuntu22.04-linux-x86_64.zip
e3a8e53e092041ed9ed32c98d5d0ecf548f42232402748f862371ba21e1f1f9f salvium-v1.1.0-rc6-win64.zip
-5
View File
@@ -1,5 +0,0 @@
d22bbe19fa5e7eb7ebaf95eee336d73cbd59ded7b5e737213e89a8b84d5791eb salvium-v1.1.1-macos-aarch64.zip
262e2bdffc3c4fee89ec79451a6181175671db5874726d359077c4479754076e salvium-v1.1.1-macos-x86_64.zip
72b37fa30df6b136dba380b88e9ccc4d66804d8286a221a87e944e337f4ba593 salvium-v1.1.1-ubuntu22.04-linux-aarch64.zip
33321419bb426507de0f5de7c1977e436ca34bf4db620fa00eede1fa318b7994 salvium-v1.1.1-ubuntu22.04-linux-x86_64.zip
33e7c1e1bc4e5a1f9c40482eba993a5efb97a8feedfb36dca863bbb5bd9e794f salvium-v1.1.1-win64.zip
+9 -40
View File
@@ -238,7 +238,7 @@ void BlockchainDB::add_transaction(const crypto::hash& blk_hash, const std::pair
LOG_PRINT_L1("Failed to get output unlock time, aborting transaction addition");
throw std::runtime_error("Unexpected error getting output unlock_time, aborting");
}
if (miner_tx && tx.version >= 2)
if (miner_tx && tx.version == 2)
{
cryptonote::tx_out vout = tx.vout[i];
// TODO: avoid multiple expensive zeroCommitVartime call here + get_outs_by_last_locked_block + ver_non_input_consensus
@@ -294,22 +294,7 @@ uint64_t BlockchainDB::add_block( const std::pair<block, blobdata>& blck
time1 = epee::misc_utils::get_tick_count();
uint64_t num_rct_outs = 0;
oracle::asset_type_counts_v2 num_rct_outs_by_asset_type;
// add newly created tokens
for (const std::pair<transaction, blobdata>& tx : txs)
{
if (tx.first.type == cryptonote::transaction_type::CREATE_TOKEN)
{
uint32_t asset_type_id = cryptonote::asset_id_from_type("sal" + tx.first.token_metadata.asset_type);
if (!num_rct_outs_by_asset_type.add_asset_type(asset_type_id))
throw std::runtime_error("Failed to add asset_type 'sal" + tx.first.token_metadata.asset_type + "'");
}
if (!is_tx_paid_for(tx.first))
throw std::runtime_error("TX is not paid for");
}
oracle::asset_type_counts num_rct_outs_by_asset_type;
blobdata miner_bd = tx_to_blob(blk.miner_tx);
add_transaction(blk_hash, std::make_pair(blk.miner_tx, blobdata_ref(miner_bd)));
blobdata protocol_bd = tx_to_blob(blk.protocol_tx);
@@ -324,14 +309,12 @@ uint64_t BlockchainDB::add_block( const std::pair<block, blobdata>& blck
std::string asset_type;
if (!get_output_asset_type(vout, asset_type))
throw std::runtime_error("Failed to get output asset type");
uint32_t asset_type_id = cryptonote::asset_id_from_type(asset_type);
num_rct_outs_by_asset_type.add_asset_type(asset_type_id);
num_rct_outs_by_asset_type.add(asset_type_id, 1);
num_rct_outs_by_asset_type.add(asset_type, 1);
}
}
std::map<std::string, int64_t> slippage_counts;
uint64_t audit_total = 0, token_total = 0, yield_total = 0;
uint64_t audit_total = 0, yield_total = 0;
if (blk.protocol_tx.version >= 2)
{
num_rct_outs += blk.protocol_tx.vout.size();
@@ -343,12 +326,10 @@ uint64_t BlockchainDB::add_block( const std::pair<block, blobdata>& blck
std::string asset_type;
if (!get_output_asset_type(vout, asset_type))
throw std::runtime_error("Failed to get output asset type");
uint32_t asset_type_id = cryptonote::asset_id_from_type(asset_type);
// Update the RCT outs for the asset_type
num_rct_outs_by_asset_type.add_asset_type(asset_type_id);
num_rct_outs_by_asset_type.add(asset_type_id, 1);
// Update the RCT outs
num_rct_outs_by_asset_type.add(asset_type, 1);
// Update the amount tallies by DEDUCTING the minted amount
if (slippage_counts.count(asset_type) == 0)
slippage_counts[asset_type] = 0;
@@ -369,9 +350,7 @@ uint64_t BlockchainDB::add_block( const std::pair<block, blobdata>& blck
throw std::runtime_error("Failed to get output asset type");
if (vout.amount == 0) {
++num_rct_outs;
uint32_t asset_type_id = cryptonote::asset_id_from_type(asset_type);
num_rct_outs_by_asset_type.add_asset_type(asset_type_id);
num_rct_outs_by_asset_type.add(asset_type_id, 1);
num_rct_outs_by_asset_type.add(asset_type, 1);
}
// Is this a CONVERT TX?
@@ -388,16 +367,6 @@ uint64_t BlockchainDB::add_block( const std::pair<block, blobdata>& blck
audit_total += tx.first.amount_burnt;
}
// Is this an create_token TX?
if (tx.first.type == cryptonote::transaction_type::CREATE_TOKEN) {
token_total += tx.first.amount_burnt;
/*
uint32_t asset_type_id = cryptonote::asset_id_from_type(tx.first.token_metadata.asset_type);
if (!num_rct_outs_by_asset_type.add_asset_type(asset_type_id))
throw std::runtime_error("Failed to add asset_type '" + tx.first.token_metadata.asset_type + "' to RCT outputs");
*/
}
// Is this a STAKE TX?
if (tx.first.type == cryptonote::transaction_type::STAKE) {
yield_total += tx.first.amount_burnt;
@@ -451,7 +420,7 @@ uint64_t BlockchainDB::add_block( const std::pair<block, blobdata>& blck
// call out to subclass implementation to add the block & metadata
time1 = epee::misc_utils::get_tick_count();
add_block(blk, block_weight, long_term_block_weight, cumulative_difficulty, coins_generated, num_rct_outs, num_rct_outs_by_asset_type, blk_hash, slippage_total, yield_total, audit_total, token_total, nettype, ybi, abi);
add_block(blk, block_weight, long_term_block_weight, cumulative_difficulty, coins_generated, num_rct_outs, num_rct_outs_by_asset_type, blk_hash, slippage_total, yield_total, audit_total, nettype, ybi, abi);
TIME_MEASURE_FINISH(time1);
time_add_block1 += time1;
+1 -43
View File
@@ -207,29 +207,6 @@ typedef struct yield_tx_info {
crypto::public_key return_pubkey;
} yield_tx_info;
typedef struct yield_tx_info_carrot {
uint64_t block_height;
uint8_t version;
crypto::hash tx_hash;
uint64_t locked_coins;
crypto::public_key return_address;
crypto::public_key return_pubkey;
carrot::view_tag_t return_view_tag;
carrot::encrypted_janus_anchor_t return_anchor_enc;
} yield_tx_info_carrot;
typedef struct token_tx_info_carrot {
uint64_t block_height;
uint8_t version;
crypto::hash tx_hash;
uint64_t locked_coins;
crypto::public_key return_address;
crypto::public_key return_pubkey;
carrot::view_tag_t return_view_tag;
carrot::encrypted_janus_anchor_t return_anchor_enc;
uint32_t asset_type_id;
} token_tx_info_carrot;
#define DBF_SAFE 1
#define DBF_FAST 2
#define DBF_FASTEST 4
@@ -449,12 +426,11 @@ private:
const difficulty_type& cumulative_difficulty,
const uint64_t& coins_generated,
uint64_t num_rct_outs,
oracle::asset_type_counts_v2& cum_rct_by_asset_type,
oracle::asset_type_counts& cum_rct_by_asset_type,
const crypto::hash& blk_hash,
uint64_t slippage_total,
uint64_t yield_total,
uint64_t audit_total,
uint64_t token_total,
const cryptonote::network_type nettype,
cryptonote::yield_block_info& ybi,
cryptonote::audit_block_info& abi
@@ -1225,20 +1201,6 @@ public:
virtual std::map<std::string, uint64_t> get_circulating_supply() const = 0;
/**
* @brief fetch the tokens from the blockchain
*
* @return the current token values
*/
virtual std::map<std::string, cryptonote::token_metadata_t> get_tokens() const = 0;
/**
* @brief determine if a TX has been paid for
*
* @return the current token values
*/
virtual bool is_tx_paid_for(const cryptonote::transaction& tx) const = 0;
/**
* <!--
* TODO: Rewrite (if necessary) such that all calls to remove_* are
@@ -1962,10 +1924,6 @@ public:
virtual int get_yield_block_info(const uint64_t height, yield_block_info& ybi) const = 0;
virtual int get_yield_tx_info(const uint64_t height, std::vector<yield_tx_info>& yti_container) const = 0;
virtual int get_carrot_yield_tx_info(const uint64_t height, std::vector<yield_tx_info_carrot>& yti_container) const = 0;
virtual int get_token_tx_info(const uint64_t height, std::vector<token_tx_info_carrot>& tti_container) const = 0;
/**
* @brief set whether or not to automatically remove logs
File diff suppressed because it is too large Load Diff
+2 -50
View File
@@ -80,16 +80,7 @@ typedef struct mdb_txn_cursors
MDB_cursor *m_txc_yield_blocks;
MDB_cursor *m_txc_audit_txs;
MDB_cursor *m_txc_audit_blocks;
MDB_cursor *m_txc_carrot_yield_txs;
MDB_cursor *m_txc_token_txs;
MDB_cursor *m_txc_tokens;
MDB_cursor *m_txc_asset_type_counts;
MDB_cursor *m_txc_rct_count_info;
MDB_cursor *m_txc_rollup_tx_info;
} mdb_txn_cursors;
#define m_cur_blocks m_cursors->m_txc_blocks
@@ -117,15 +108,6 @@ typedef struct mdb_txn_cursors
#define m_cur_yield_blocks m_cursors->m_txc_yield_blocks
#define m_cur_audit_txs m_cursors->m_txc_audit_txs
#define m_cur_audit_blocks m_cursors->m_txc_audit_blocks
#define m_cur_carrot_yield_txs m_cursors->m_txc_carrot_yield_txs
#define m_cur_token_txs m_cursors->m_txc_token_txs
#define m_cur_tokens m_cursors->m_txc_tokens
#define m_cur_asset_type_counts m_cursors->m_txc_asset_type_counts
#define m_cur_rct_count_info m_cursors->m_txc_rct_count_info
#define m_cur_rollup_tx_info m_cursors->m_txc_rollup_tx_info
typedef struct mdb_rflags
{
@@ -155,16 +137,6 @@ typedef struct mdb_rflags
bool m_rf_yield_blocks;
bool m_rf_audit_txs;
bool m_rf_audit_blocks;
bool m_rf_carrot_yield_txs;
bool m_rf_token_txs;
bool m_rf_tokens;
bool m_rf_asset_type_counts;
bool m_rf_rct_count_info;
bool m_rf_rollup_tx_info;
} mdb_rflags;
typedef struct mdb_threadinfo
@@ -267,8 +239,6 @@ public:
virtual cryptonote::blobdata get_block_blob_from_height(const uint64_t& height) const;
virtual std::pair<std::vector<uint64_t>, uint64_t> get_block_cumulative_rct_outputs_old(const std::vector<uint64_t> &heights, const std::string asset_type) const;
virtual std::pair<std::vector<uint64_t>, uint64_t> get_block_cumulative_rct_outputs(const std::vector<uint64_t> &heights, const std::string asset_type) const;
virtual uint64_t get_block_timestamp(const uint64_t& height) const;
@@ -304,10 +274,6 @@ public:
virtual uint64_t height() const;
virtual std::map<std::string, uint64_t> get_circulating_supply() const;
virtual std::map<std::string, cryptonote::token_metadata_t> get_tokens() const;
virtual bool is_tx_paid_for(const cryptonote::transaction& tx) const;
virtual bool tx_exists(const crypto::hash& h) const;
virtual bool tx_exists(const crypto::hash& h, uint64_t& tx_index) const;
@@ -437,12 +403,11 @@ private:
const difficulty_type& cumulative_difficulty,
const uint64_t& coins_generated,
uint64_t num_rct_outs,
oracle::asset_type_counts_v2& cum_rct_by_asset_type,
oracle::asset_type_counts& cum_rct_by_asset_type,
const crypto::hash& blk_hash,
uint64_t slippage_total,
uint64_t yield_total,
uint64_t audit_total,
uint64_t token_total,
const cryptonote::network_type nettype,
cryptonote::yield_block_info& ybi,
cryptonote::audit_block_info& abi
@@ -509,9 +474,6 @@ private:
virtual int get_yield_block_info(const uint64_t height, yield_block_info& ybi) const;
virtual int get_yield_tx_info(const uint64_t height, std::vector<yield_tx_info>& yti_container) const;
virtual int get_carrot_yield_tx_info(const uint64_t height, std::vector<yield_tx_info_carrot>& yti_container) const;
virtual int get_token_tx_info(const uint64_t height, std::vector<token_tx_info_carrot>& tti_container) const;
private:
MDB_env* m_env;
@@ -549,20 +511,10 @@ private:
MDB_dbi m_yield_txs;
MDB_dbi m_yield_blocks;
MDB_dbi m_audit_txs;
MDB_dbi m_audit_blocks;
MDB_dbi m_carrot_yield_txs;
MDB_dbi m_token_txs;
MDB_dbi m_tokens;
MDB_dbi m_asset_type_counts;
MDB_dbi m_rct_count_info;
MDB_dbi m_rollup_tx_info;
mutable uint64_t m_cum_size; // used in batch size estimation
mutable unsigned int m_cum_count;
std::string m_folder;
+1 -7
View File
@@ -145,7 +145,6 @@ public:
virtual int get_yield_block_info(const uint64_t height, yield_block_info& ybi) const override { return 0; }
virtual int get_yield_tx_info(const uint64_t height, std::vector<yield_tx_info>& yti_container) const override { return 0; }
virtual int get_carrot_yield_tx_info(const uint64_t height, std::vector<yield_tx_info_carrot>& yti_container) const override { return 0; }
virtual cryptonote::blobdata get_txpool_tx_blob(const crypto::hash& txid, relay_category tx_category) const override { return ""; }
virtual bool for_all_txpool_txes(std::function<bool(const crypto::hash&, const cryptonote::txpool_tx_meta_t&, const cryptonote::blobdata_ref*)>, bool include_blob = false, relay_category category = relay_category::broadcasted) const override { return false; }
@@ -156,20 +155,15 @@ public:
const difficulty_type& cumulative_difficulty,
const uint64_t& coins_generated,
uint64_t num_rct_outs,
oracle::asset_type_counts_v2& cum_rct_by_asset_type,
oracle::asset_type_counts& cum_rct_by_asset_type,
const crypto::hash& blk_hash,
uint64_t slippage_total,
uint64_t yield_total,
uint64_t audit_total,
uint64_t token_total,
const cryptonote::network_type nettype,
cryptonote::yield_block_info& ybi,
cryptonote::audit_block_info& abi
) override { }
virtual std::map<std::string, cryptonote::token_metadata_t> get_tokens() const override { return {}; }
virtual bool is_tx_paid_for(const cryptonote::transaction& tx) const override { return true; }
virtual int get_token_tx_info(const uint64_t height, std::vector<token_tx_info_carrot>& tti_container) const override { return 0; }
virtual cryptonote::block get_block_from_height(const uint64_t& height) const override { return cryptonote::block(); }
virtual void set_hard_fork_version(uint64_t height, uint8_t version) override {}
virtual uint8_t get_hard_fork_version(uint64_t height) const override { return 0; }
+13 -10
View File
@@ -214,9 +214,11 @@ plot 'stats.csv' index "DATA" using (timecolumn(1,"%Y-%m-%d")):4 with lines, ''
#define MAX_RINGS 0xffffffff
struct tm prevtm = {0}, currtm;
// uint64_t currsz = 0;
// uint64_t currtxs = 0;
// uint64_t currblks = 0;
uint64_t prevsz = 0, currsz = 0;
uint64_t prevtxs = 0, currtxs = 0;
uint64_t currblks = 0;
uint32_t txhr[24] = {0};
unsigned int i;
const std::map<uint8_t, std::pair<uint64_t, std::pair<std::string, std::string>>> audit_hard_forks = get_config(net_type).AUDIT_HARD_FORKS;
@@ -244,7 +246,9 @@ plot 'stats.csv' index "DATA" using (timecolumn(1,"%Y-%m-%d")):4 with lines, ''
prevtm = currtm;
}
skip:
// currsz += bd.size();
currsz += bd.size();
uint64_t coinbase_amount;
uint64_t tx_fee_amount = 0;
std::set<std::string> used_assets, miner_tx_assets, protocol_tx_assets;
std::map<size_t, std::vector<std::string>> used_tx_versions;
used_assets.insert("SAL");
@@ -321,11 +325,10 @@ skip:
std::cout << timebuf << "" << delimiter << "" << h << "" << delimiter << "" << tx_id << "" << delimiter << "invalid TX detected" << delimiter << std::endl;
continue;
}
// currsz += bd.size();
// if (db->get_prunable_tx_blob(tx_id, bd))
// currsz += bd.size();
// currtxs++;
db->get_prunable_tx_blob(tx_id, bd);
currsz += bd.size();
if (db->get_prunable_tx_blob(tx_id, bd))
currsz += bd.size();
currtxs++;
if (tx.type != cryptonote::transaction_type::TRANSFER &&
tx.type != cryptonote::transaction_type::BURN &&
@@ -371,7 +374,7 @@ skip:
}
}
// currblks++;
currblks++;
if (stop_requested)
break;
@@ -211,15 +211,8 @@ int main(int argc, char* argv[])
throw std::runtime_error("Failed to initialize a database");
}
boost::filesystem::path folder(opt_data_dir);
if (opt_stagenet) {
folder /= std::to_string(STAGENET_VERSION);
} else if (opt_testnet) {
folder /= std::to_string(TESTNET_VERSION);
}
folder /= db->get_db_name();
LOG_PRINT_L0("Loading blockchain from folder " << folder << " ...");
const std::string filename = folder.string();
const std::string filename = (boost::filesystem::path(opt_data_dir) / db->get_db_name()).string();
LOG_PRINT_L0("Loading blockchain from folder " << filename << " ...");
try
{
Binary file not shown.
-1
View File
@@ -29,7 +29,6 @@
set(carrot_core_sources
account_secrets.cpp
address_utils.cpp
account.cpp
carrot_enote_types.cpp
core_types.cpp
destination.cpp
-242
View File
@@ -1,242 +0,0 @@
// Copyright (c) 2025, The Monero Project
//
// 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 "account_secrets.h"
#include "address_utils.h"
#include "destination.h"
#include "device_ram_borrowed.h"
#include "enote_utils.h"
#include "carrot_impl/subaddress_index.h"
#include "cryptonote_basic/account.h"
#include "cryptonote_basic/subaddress_index.h"
//----------------------------------------------------------------------------------------------------------------------
static constexpr std::uint32_t MAX_SUBADDRESS_MAJOR_INDEX = 5;
static constexpr std::uint32_t MAX_SUBADDRESS_MINOR_INDEX = 20;
namespace carrot
{
struct return_output_info_t {
input_context_t input_context;
crypto::public_key K_o; // output onetime address
crypto::public_key K_change; // change output onetime address
crypto::public_key K_spend_pubkey; // change output spend pubkey
crypto::key_image key_image;
crypto::secret_key sum_g;
crypto::secret_key sender_extension_t;
return_output_info_t() {
// Default constructor for serialization
input_context = input_context_t();
K_o = crypto::public_key();
K_change = crypto::public_key();
K_spend_pubkey = crypto::public_key();
key_image = crypto::key_image();
sum_g = crypto::secret_key();
sender_extension_t = crypto::secret_key();
}
return_output_info_t(
const input_context_t &input_context,
const crypto::public_key &K_o,
const crypto::public_key &K_change,
const crypto::public_key &K_spend_pubkey,
const crypto::key_image &key_image,
const crypto::secret_key &sum_g,
const crypto::secret_key &sender_extension_t):
input_context(input_context),
K_o(K_o),
K_change(K_change),
K_spend_pubkey(K_spend_pubkey),
key_image(key_image),
sum_g(sum_g),
sender_extension_t(sender_extension_t) {}
BEGIN_SERIALIZE_OBJECT()
FIELD(input_context)
FIELD(K_o)
FIELD(K_change)
FIELD(K_spend_pubkey)
FIELD(key_image)
FIELD(sum_g)
FIELD(sender_extension_t)
END_SERIALIZE()
};
// Old return_output_info_t format (for deserializing version 2 wallet caches)
struct return_output_info_retired_t {
input_context_t input_context;
crypto::public_key K_o;
crypto::public_key K_change;
crypto::key_image key_image;
crypto::secret_key x;
crypto::secret_key y;
return_output_info_retired_t() {
input_context = input_context_t();
K_o = crypto::public_key();
K_change = crypto::public_key();
key_image = crypto::key_image();
x = crypto::secret_key();
y = crypto::secret_key();
}
BEGIN_SERIALIZE_OBJECT()
FIELD(input_context)
FIELD(K_o)
FIELD(K_change)
FIELD(key_image)
FIELD(x)
FIELD(y)
END_SERIALIZE()
};
class carrot_and_legacy_account : public cryptonote::account_base
{
public:
view_incoming_key_ram_borrowed_device k_view_incoming_dev;
view_balance_secret_ram_borrowed_device s_view_balance_dev;
generate_address_secret_ram_borrowed_device s_generate_address_dev;
AddressDeriveType default_derive_type;
carrot_and_legacy_account(): k_view_incoming_dev(get_keys().k_view_incoming),
s_view_balance_dev(get_keys().s_view_balance),
s_generate_address_dev(get_keys().s_generate_address)
{}
void set_keys(const cryptonote::account_keys& keys, bool copy_spend_secret_keys);
carrot_and_legacy_account(const carrot_and_legacy_account &k) = delete;
carrot_and_legacy_account(carrot_and_legacy_account&&) = delete;
carrot_and_legacy_account& operator=(const carrot_and_legacy_account&) = delete;
carrot_and_legacy_account& operator=(carrot_and_legacy_account&&) = delete;
CarrotDestinationV1 cryptonote_address(const payment_id_t payment_id = null_payment_id,
const AddressDeriveType derive_type = AddressDeriveType::Auto) const;
CarrotDestinationV1 subaddress(const subaddress_index_extended &subaddress_index) const;
const std::unordered_map<crypto::public_key, cryptonote::subaddress_index> get_subaddress_map_cn() const;
const std::unordered_map<crypto::public_key, subaddress_index_extended>& get_subaddress_map_ref() const;
const std::unordered_map<crypto::public_key, return_output_info_t>& get_return_output_map_ref() const;
// brief: opening_for_subaddress - return (k^g_a, k^t_a) for j s.t. K^j_s = (k^g_a * G + k^t_a * T)
void opening_for_subaddress(const subaddress_index_extended &subaddress_index,
crypto::secret_key &address_privkey_g_out,
crypto::secret_key &address_privkey_t_out,
crypto::public_key &address_spend_pubkey_out) const;
bool try_searching_for_opening_for_subaddress(const crypto::public_key &address_spend_pubkey,
crypto::secret_key &address_privkey_g_out,
crypto::secret_key &address_privkey_t_out) const;
bool try_searching_for_opening_for_onetime_address(const crypto::public_key &address_spend_pubkey,
const crypto::secret_key &sender_extension_g,
const crypto::secret_key &sender_extension_t,
crypto::secret_key &x_out,
crypto::secret_key &y_out) const;
bool can_open_fcmp_onetime_address(const crypto::public_key &address_spend_pubkey,
const crypto::secret_key &sender_extension_g,
const crypto::secret_key &sender_extension_t,
const crypto::public_key &onetime_address) const;
crypto::key_image derive_key_image(const crypto::public_key &address_spend_pubkey,
const crypto::secret_key &sender_extension_g,
const crypto::secret_key &sender_extension_t,
const crypto::public_key &onetime_address) const;
crypto::key_image derive_key_image_view_only(const crypto::public_key &address_spend_pubkey,
const crypto::secret_key &sender_extension_g,
const crypto::secret_key &sender_extension_t,
const crypto::public_key &onetime_address) const;
void generate_subaddress_map(const std::pair<size_t, size_t>& lookahead_size);
crypto::secret_key generate(
const crypto::secret_key& recovery_key = crypto::secret_key(),
bool recover = false,
bool two_random = false,
const AddressDeriveType default_derive_type = AddressDeriveType::Carrot
);
void create_from_svb_key(const cryptonote::account_public_address& address, const crypto::secret_key& svb_key);
void set_carrot_keys(const AddressDeriveType default_derive_type = AddressDeriveType::Carrot);
void insert_subaddresses(const std::unordered_map<crypto::public_key, subaddress_index_extended>& subaddress_map);
void insert_return_output_info(
const std::unordered_map<crypto::public_key, return_output_info_t>& input_context_map
);
AddressDeriveType resolve_derive_type(const AddressDeriveType derive_type) const;
private:
std::unordered_map<crypto::public_key, subaddress_index_extended> subaddress_map;
// Kr -> return_output_info
std::unordered_map<crypto::public_key, return_output_info_t> return_output_map;
};
}
namespace boost
{
namespace serialization
{
template <class Archive>
inline typename std::enable_if<!Archive::is_loading::value, void>::type initialize_transfer_details(Archive &a, carrot::return_output_info_t &x, const boost::serialization::version_type ver)
{
}
template <class Archive>
inline typename std::enable_if<Archive::is_loading::value, void>::type initialize_transfer_details(Archive &a, carrot::return_output_info_t &x, const boost::serialization::version_type ver)
{
x.input_context = carrot::input_context_t();
x.K_o = crypto::public_key();
x.K_change = crypto::public_key();
x.K_spend_pubkey = crypto::public_key();
x.key_image = crypto::key_image();
x.sum_g = crypto::secret_key();
x.sender_extension_t = crypto::secret_key();
}
template <class Archive>
inline void serialize(Archive &a, carrot::return_output_info_t &x, const boost::serialization::version_type ver)
{
a & x.input_context;
a & x.K_o;
a & x.K_change;
a & x.K_spend_pubkey;
a & x.key_image;
a & x.sum_g;
a & x.sender_extension_t;
}
}
}
-2
View File
@@ -75,8 +75,6 @@ struct CarrotEnoteV1 final
mx25519_pubkey enote_ephemeral_pubkey;
/// L_0
crypto::key_image tx_first_key_image;
// transaction output keys
std::vector<crypto::public_key> tx_output_keys;
};
/// equality operators
+1 -2
View File
@@ -70,11 +70,10 @@ static constexpr const unsigned char CARROT_DOMAIN_SEP_SUBADDRESS_SCALAR[] = "Ca
static constexpr const unsigned int CARROT_MIN_TX_OUTPUTS = 2;
static constexpr const unsigned int CARROT_MAX_TX_OUTPUTS = 8;
static constexpr const unsigned int CARROT_MIN_TX_INPUTS = 1;
static constexpr const unsigned int CARROT_MAX_TX_INPUTS = 64;
static constexpr const unsigned int CARROT_MAX_TX_INPUTS = 128;
// SPARC addressing protocol domain separators
static constexpr const unsigned char SPARC_DOMAIN_SEP_RETURN_PUBKEY_ENCRYPTION_MASK[] = "SPARC return pubkey encryption mask";
static constexpr const unsigned char SPARC_DOMAIN_SEP_RETURN_ADDRESS_SCALAR[] = "SPARC return address scalar";
static constexpr const unsigned char SPARC_DOMAIN_SEP_RETURN_INDEX_SCALAR[] = "SPARC return index scalar";
} //namespace carrot
-5
View File
@@ -122,11 +122,6 @@ bool operator==(const view_tag_t &a, const view_tag_t &b)
return memcmp(&a, &b, sizeof(view_tag_t)) == 0;
}
//-------------------------------------------------------------------------------------------------------------------
bool operator==(const rollup_binding_tag_t &a, const rollup_binding_tag_t &b)
{
return memcmp(&a, &b, sizeof(rollup_binding_tag_t)) == 0;
}
//-------------------------------------------------------------------------------------------------------------------
janus_anchor_t gen_janus_anchor()
{
return crypto::rand<janus_anchor_t>();
-11
View File
@@ -106,13 +106,6 @@ struct encrypted_return_pubkey_t final
unsigned char bytes[ENCRYPTED_RETURN_PUBKEY_BYTES];
};
/// Salvium rollup binding tag
constexpr std::size_t ROLLUP_BINDING_TAG_BYTES{8};
struct rollup_binding_tag_t final
{
unsigned char bytes[ROLLUP_BINDING_TAG_BYTES];
};
/// overloaded operators: address tag
bool operator==(const janus_anchor_t &a, const janus_anchor_t &b);
static inline bool operator!=(const janus_anchor_t &a, const janus_anchor_t &b) { return !(a == b); }
@@ -146,10 +139,6 @@ bool operator==(const encrypted_return_pubkey_t &a, const encrypted_return_pubke
static inline bool operator!=(const encrypted_return_pubkey_t &a, const encrypted_return_pubkey_t &b) { return !(a == b); }
encrypted_return_pubkey_t operator^(const encrypted_return_pubkey_t &a, const encrypted_return_pubkey_t &b);
/// overloaded operators: rollup binding tag
bool operator==(const rollup_binding_tag_t &a, const rollup_binding_tag_t &b);
static inline bool operator!=(const rollup_binding_tag_t &a, const rollup_binding_tag_t &b) { return !(a == b); }
/// generate a random janus anchor
janus_anchor_t gen_janus_anchor();
/// generate a random (non-null) payment ID
-4
View File
@@ -134,10 +134,6 @@ struct view_incoming_key_device
const crypto::public_key &onetime_address,
janus_anchor_t &anchor_special_out) const = 0;
virtual void make_internal_return_privkey(const input_context_t &input_context,
const crypto::public_key &onetime_address,
crypto::secret_key &return_privkey_out) const = 0;
virtual ~view_incoming_key_device() = default;
};
-7
View File
@@ -55,13 +55,6 @@ bool view_incoming_key_ram_borrowed_device::view_key_scalar_mult_x25519(const mx
return make_carrot_uncontextualized_shared_key_receiver(m_k_view_incoming, D, kvD);
}
//-------------------------------------------------------------------------------------------------------------------
void view_incoming_key_ram_borrowed_device::make_internal_return_privkey(const input_context_t &input_context,
const crypto::public_key &onetime_address,
crypto::secret_key &return_privkey_out) const
{
make_sparc_return_privkey(to_bytes(m_k_view_incoming), input_context, onetime_address, return_privkey_out);
}
//-------------------------------------------------------------------------------------------------------------------
void view_incoming_key_ram_borrowed_device::make_janus_anchor_special(
const mx25519_pubkey &enote_ephemeral_pubkey,
const input_context_t &input_context,
-4
View File
@@ -60,10 +60,6 @@ public:
const crypto::public_key &onetime_address,
janus_anchor_t &anchor_special_out) const override;
void make_internal_return_privkey(const input_context_t &input_context,
const crypto::public_key &onetime_address,
crypto::secret_key &return_privkey_out) const override;
protected:
const crypto::secret_key &m_k_view_incoming;
};
+14 -53
View File
@@ -39,7 +39,6 @@ extern "C"
#include "crypto/wallet/crypto.h"
#include "hash_functions.h"
#include "int-util.h"
#include "string_tools.h"
#include "misc_language.h"
#include "ringct/rctOps.h"
#include "transcript_fixed.h"
@@ -212,17 +211,6 @@ void make_sparc_return_privkey(const unsigned char s_sender_receiver_unctx[32],
derive_scalar(transcript.data(), transcript.size(), s_sender_receiver_unctx, &return_privkey_out);
}
//-------------------------------------------------------------------------------------------------------------------
void make_sparc_return_index(const unsigned char s_sender_receiver_unctx[32],
const input_context_t &input_context,
const crypto::public_key &onetime_address,
const uint64_t idx,
crypto::secret_key &return_index_out)
{
// k_idx = H_32(s_sr || input_context || Ko || idx)
const auto transcript = sp::make_fixed_transcript<SPARC_DOMAIN_SEP_RETURN_INDEX_SCALAR>(input_context, onetime_address, idx);
derive_scalar(transcript.data(), transcript.size(), s_sender_receiver_unctx, &return_index_out);
}
//-------------------------------------------------------------------------------------------------------------------
void make_sparc_return_pubkey_encryption_mask(const unsigned char s_sender_receiver_unctx[32],
const input_context_t &input_context,
const crypto::public_key &onetime_address,
@@ -234,50 +222,22 @@ void make_sparc_return_pubkey_encryption_mask(const unsigned char s_sender_recei
}
//-------------------------------------------------------------------------------------------------------------------
void make_sparc_return_pubkey(const unsigned char s_sender_receiver_unctx[32],
const input_context_t &input_context,
const view_balance_secret_device *s_view_balance_dev,
const crypto::public_key &onetime_address,
const uint64_t idx,
encrypted_return_pubkey_t &return_pubkey_out)
const input_context_t &input_context,
const view_balance_secret_device *s_view_balance_dev,
const crypto::public_key &onetime_address,
encrypted_return_pubkey_t &return_pubkey_out)
{
// compute k_return
// K_return = k_return G ^ m_return
crypto::secret_key k_return;
s_view_balance_dev->make_internal_return_privkey(input_context, onetime_address, k_return);
// compute k_idx
crypto::secret_key k_idx;
make_sparc_return_index(s_sender_receiver_unctx, input_context, onetime_address, idx, k_idx);
// compute m_return
crypto::public_key return_pub;
encrypted_return_pubkey_t K_return;
encrypted_return_pubkey_t m_return;
make_sparc_return_pubkey_encryption_mask(s_sender_receiver_unctx,
input_context,
onetime_address,
m_return);
#if 1
// compute SPARC K_return = k_return * G
crypto::public_key K_return;
crypto::secret_key_to_public_key(k_return, K_return);
// compute return_enc
encrypted_return_pubkey_t return_pub;
static_assert(sizeof(K_return.data) == sizeof(return_pub.bytes), "Size mismatch");
memcpy(return_pub.bytes, K_return.data, sizeof(encrypted_return_pubkey_t));
#else
// compute SPARC K_return = k_return * G + k_idx * T
rct::key K_return;
rct::addKeys2(K_return,
rct::sk2rct(k_return),
rct::sk2rct(k_idx),
rct::pk2rct(crypto::get_T()));
// compute return_enc
encrypted_return_pubkey_t return_pub;
static_assert(sizeof(K_return.bytes) == sizeof(return_pub.bytes), "Size mismatch");
memcpy(return_pub.bytes, K_return.bytes, sizeof(encrypted_return_pubkey_t));
#endif
return_pubkey_out = return_pub ^ m_return;
s_view_balance_dev->make_internal_return_privkey(input_context, onetime_address, k_return);
crypto::secret_key_to_public_key(k_return, return_pub);
static_assert(sizeof(K_return.bytes) == sizeof(return_pub.data), "Size mismatch");
memcpy(K_return.bytes, return_pub.data, sizeof(encrypted_return_pubkey_t));
make_sparc_return_pubkey_encryption_mask(s_sender_receiver_unctx, input_context, onetime_address, m_return);
return_pubkey_out = K_return ^ m_return;
}
//-------------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------------------
@@ -510,6 +470,7 @@ bool test_carrot_view_tag(const unsigned char s_sender_receiver_unctx[32],
// vt' = H_3(s_sr || input_context || Ko)
view_tag_t nominal_view_tag;
make_carrot_view_tag(s_sender_receiver_unctx, input_context, onetime_address, nominal_view_tag);
// vt' ?= vt
return nominal_view_tag == view_tag;
}
+4 -19
View File
@@ -138,20 +138,6 @@ void make_sparc_return_privkey(const unsigned char s_sender_receiver_unctx[32],
const crypto::public_key &onetime_address,
crypto::secret_key &return_privkey_out);
/**
* brief: make_sparc_return_index - return index, given non-secret data
* m_return = H_32(s_sr || input_context || Ko || idx)
* param: s_sender_receiver_unctx - s_sr
* param: input_context - input_context
* param: onetime_address - Ko
* param: idx - idx
* outparam: return_index_out - m_return
*/
void make_sparc_return_index(const unsigned char s_sender_receiver_unctx[32],
const input_context_t &input_context,
const crypto::public_key &onetime_address,
const uint64_t idx,
crypto::secret_key &return_index_out);
/**
* brief: make_sparc_return_pubkey_encryption_mask - used for hiding return pubkey
* m_return = H_32(s_sr || input_context || Ko)
* param: s_sender_receiver_unctx - s_sr
@@ -173,11 +159,10 @@ void make_sparc_return_pubkey_encryption_mask(const unsigned char s_sender_recei
* outparam: return_pubkey_mask_out - K_return
*/
void make_sparc_return_pubkey(const unsigned char s_sender_receiver_unctx[32],
const input_context_t &input_context,
const view_balance_secret_device *s_view_balance_dev,
const crypto::public_key &onetime_address,
const uint64_t idx,
encrypted_return_pubkey_t &return_pubkey_out);
const input_context_t &input_context,
const view_balance_secret_device *s_view_balance_dev,
const crypto::public_key &onetime_address,
encrypted_return_pubkey_t &return_pubkey_out);
/**
* brief: make_carrot_input_context_coinbase - input context for a sender-receiver secret (coinbase txs)
* input_context = "C" || IntToBytes256(block_index)
+3 -3
View File
@@ -41,9 +41,9 @@
namespace carrot
{
#define CARROT_DEFINE_SIMPLE_ERROR_TYPE(e, b) class e: public b { using b::b; };
#define CARROT_DEFINE_SIMPLE_ERROR_TYPE(e, b) class e: b { using b::b; };
class carrot_logic_error: public std::logic_error { using std::logic_error::logic_error; };
class carrot_logic_error: std::logic_error { using std::logic_error::logic_error; };
CARROT_DEFINE_SIMPLE_ERROR_TYPE(bad_address_type, carrot_logic_error)
CARROT_DEFINE_SIMPLE_ERROR_TYPE(component_out_of_order, carrot_logic_error)
@@ -55,7 +55,7 @@ CARROT_DEFINE_SIMPLE_ERROR_TYPE(too_few_outputs, carrot_logic_error)
CARROT_DEFINE_SIMPLE_ERROR_TYPE(too_many_outputs, carrot_logic_error)
CARROT_DEFINE_SIMPLE_ERROR_TYPE(invalid_tx_type, carrot_logic_error)
class carrot_runtime_error: public std::runtime_error { using std::runtime_error::runtime_error; };
class carrot_runtime_error: std::runtime_error { using std::runtime_error::runtime_error; };
CARROT_DEFINE_SIMPLE_ERROR_TYPE(crypto_function_failed, carrot_runtime_error)
CARROT_DEFINE_SIMPLE_ERROR_TYPE(not_enough_money, carrot_runtime_error)
+14 -25
View File
@@ -77,7 +77,7 @@ std::optional<AdditionalOutputType> get_additional_output_type(const size_t num_
}
else if (!need_change_output)
{
return AdditionalOutputType::CHANGE_UNIQUE;
return AdditionalOutputType::DUMMY;
}
else // num_selfsend == 1 && need_change_output
{
@@ -159,7 +159,6 @@ void get_output_enote_proposals(const std::vector<CarrotPaymentProposalV1> &norm
const view_incoming_key_device *k_view_dev,
const crypto::key_image &tx_first_key_image,
std::vector<RCTOutputEnoteProposal> &output_enote_proposals_out,
RCTOutputEnoteProposal &return_enote_out,
encrypted_payment_id_t &encrypted_payment_id_out,
cryptonote::transaction_type tx_type,
size_t &change_index_out,
@@ -174,14 +173,7 @@ void get_output_enote_proposals(const std::vector<CarrotPaymentProposalV1> &norm
// assert payment proposals numbers
const size_t num_selfsend_proposals = selfsend_payment_proposals.size();
const size_t num_proposals = normal_payment_proposals.size() + num_selfsend_proposals;
if (tx_type == cryptonote::transaction_type::STAKE ||
tx_type == cryptonote::transaction_type::BURN ||
tx_type == cryptonote::transaction_type::CREATE_TOKEN ||
tx_type == cryptonote::transaction_type::ROLLUP) {
CARROT_CHECK_AND_THROW(num_proposals == 1, too_few_outputs, "tx doesn't have correct number of proposals");
} else {
CARROT_CHECK_AND_THROW(num_proposals >= CARROT_MIN_TX_OUTPUTS, too_few_outputs, "too few payment proposals");
}
CARROT_CHECK_AND_THROW(num_proposals >= CARROT_MIN_TX_OUTPUTS, too_few_outputs, "too few payment proposals");
CARROT_CHECK_AND_THROW(num_proposals <= CARROT_MAX_TX_OUTPUTS, too_many_outputs, "too many payment proposals");
CARROT_CHECK_AND_THROW(num_selfsend_proposals, too_few_outputs, "no selfsend payment proposal");
@@ -219,17 +211,16 @@ void get_output_enote_proposals(const std::vector<CarrotPaymentProposalV1> &norm
// construct normal enotes
for (size_t i = 0; i < normal_payment_proposals.size(); ++i)
{
auto &output_entry = sortable_data.emplace_back();
auto &output_entry = tools::add_element(sortable_data);
output_entry.second = {false, i};
encrypted_payment_id_t encrypted_payment_id;
if (tx_type == cryptonote::transaction_type::RETURN) {
const uint64_t idx = 0;
get_output_proposal_return_v1(normal_payment_proposals[i],
tx_first_key_image,
s_view_balance_dev,
output_entry.first,
encrypted_payment_id);
tx_first_key_image,
s_view_balance_dev,
output_entry.first,
encrypted_payment_id);
} else {
get_output_proposal_normal_v1(normal_payment_proposals[i],
tx_first_key_image,
@@ -274,7 +265,7 @@ void get_output_enote_proposals(const std::vector<CarrotPaymentProposalV1> &norm
{
const CarrotPaymentProposalSelfSendV1 &selfsend_payment_proposal = selfsend_payment_proposals.at(i);
auto &output_entry = sortable_data.emplace_back();
auto &output_entry = tools::add_element(sortable_data);
output_entry.second = {true, i};
if (s_view_balance_dev != nullptr)
@@ -283,8 +274,6 @@ void get_output_enote_proposals(const std::vector<CarrotPaymentProposalV1> &norm
*s_view_balance_dev,
tx_first_key_image,
other_enote_ephemeral_pubkey,
tx_type,
return_enote_out,
output_entry.first);
}
else if (k_view_dev != nullptr)
@@ -365,11 +354,11 @@ void get_output_enote_proposals(const std::vector<CarrotPaymentProposalV1> &norm
component_out_of_order, "this set contains duplicate onetime addresses");
// assert all K_o lie in prime order subgroup
// for (const RCTOutputEnoteProposal &output_enote_proposal : output_enote_proposals_out)
// {
// CARROT_CHECK_AND_THROW(rct::isInMainSubgroup(rct::pk2rct(output_enote_proposal.enote.onetime_address)),
// invalid_point, "this set contains an invalid onetime address");
// }
for (const RCTOutputEnoteProposal &output_enote_proposal : output_enote_proposals_out)
{
CARROT_CHECK_AND_THROW(rct::isInMainSubgroup(rct::pk2rct(output_enote_proposal.enote.onetime_address)),
invalid_point, "this set contains an invalid onetime address");
}
// assert unique and non-trivial k_a
memcmp_set<crypto::secret_key> amount_blinding_factors;
@@ -420,7 +409,7 @@ void get_coinbase_output_enotes(const std::vector<CarrotPaymentProposalV1> &norm
{
get_coinbase_output_proposal_v1(normal_payment_proposals[i],
block_index,
output_coinbase_enotes_out.emplace_back());
tools::add_element(output_coinbase_enotes_out));
}
// assert uniqueness and non-trivial-ness of D_e
@@ -109,7 +109,6 @@ void get_output_enote_proposals(const std::vector<CarrotPaymentProposalV1> &norm
const view_incoming_key_device *k_view_dev,
const crypto::key_image &tx_first_key_image,
std::vector<RCTOutputEnoteProposal> &output_enote_proposals_out,
RCTOutputEnoteProposal &return_enote_out,
encrypted_payment_id_t &encrypted_payment_id_out,
cryptonote::transaction_type tx_type,
size_t &change_index_out,
+8 -129
View File
@@ -36,7 +36,6 @@
#include "misc_language.h"
#include "misc_log_ex.h"
#include "ringct/rctOps.h"
#include "crypto/generators.h"
//third party headers
@@ -180,7 +179,7 @@ static void get_external_output_proposal_parts(const mx25519_pubkey &s_sender_re
encrypted_amount_t &encrypted_amount_out,
encrypted_payment_id_t &encrypted_payment_id_out,
view_tag_t &view_tag_out,
encrypted_return_pubkey_t &return_pubkey_out)
encrypted_return_pubkey_t return_pubkey_out)
{
// 1. s^ctx_sr = H_32(s_sr, D_e, input_context)
make_carrot_sender_receiver_secret(s_sender_receiver_unctx.data,
@@ -209,11 +208,10 @@ static void get_external_output_proposal_parts(const mx25519_pubkey &s_sender_re
// 4. construct the return pubkey
if (s_view_balance_dev != nullptr)
make_sparc_return_pubkey(s_sender_receiver_unctx.data,
input_context,
s_view_balance_dev,
onetime_address_out,
0,
return_pubkey_out);
input_context,
s_view_balance_dev,
onetime_address_out,
return_pubkey_out);
}
//-------------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------------------
@@ -221,7 +219,6 @@ bool operator==(const CarrotPaymentProposalV1 &a, const CarrotPaymentProposalV1
{
return a.destination == b.destination &&
a.amount == b.amount &&
a.asset_type == b.asset_type &&
a.randomness == b.randomness;
}
//-------------------------------------------------------------------------------------------------------------------
@@ -231,7 +228,6 @@ bool operator==(const CarrotPaymentProposalSelfSendV1 &a, const CarrotPaymentPro
a.amount == b.amount &&
a.enote_type == b.enote_type &&
a.internal_message == b.internal_message &&
a.asset_type == b.asset_type &&
0 == memcmp(&a.enote_ephemeral_pubkey, &b.enote_ephemeral_pubkey, sizeof(mx25519_pubkey));
}
//-------------------------------------------------------------------------------------------------------------------
@@ -335,7 +331,7 @@ void get_output_proposal_normal_v1(const CarrotPaymentProposalV1 &proposal,
CarrotEnoteType::PAYMENT,
output_enote_out.enote.enote_ephemeral_pubkey,
input_context,
s_view_balance_dev, // we need it to calculate the return pubkey
s_view_balance_dev,
false, // coinbase_amount_commitment
s_sender_receiver,
output_enote_out.amount_blinding_factor,
@@ -425,95 +421,11 @@ void get_output_proposal_special_v1(const CarrotPaymentProposalSelfSendV1 &propo
// 8. save the enote ephemeral pubkey, first tx key image, and amount
output_enote_out.enote.enote_ephemeral_pubkey = enote_ephemeral_pubkey;
output_enote_out.enote.tx_first_key_image = tx_first_key_image;
output_enote_out.enote.asset_type = proposal.asset_type;
output_enote_out.enote.asset_type = "SAL1";
output_enote_out.enote.return_enc = crypto::rand<carrot::encrypted_return_pubkey_t>();
output_enote_out.amount = proposal.amount;
}
//-------------------------------------------------------------------------------------------------------------------
void get_output_proposal_paymentchannel_v1(const CarrotPaymentProposalV1 &proposal,
const crypto::key_image &tx_first_key_image,
const view_balance_secret_device *s_view_balance_dev,
const crypto::public_key &K_o,
const uint64_t idx,
RCTOutputEnoteProposal &output_enote_out,
encrypted_payment_id_t &encrypted_payment_id_out)
{
// 1. sanity checks
CARROT_CHECK_AND_THROW(proposal.randomness != null_anchor,
missing_randomness, "invalid randomness for janus anchor (zero).");
// 2. input context: input_context = "R" || KI_1
const input_context_t input_context = make_carrot_input_context(tx_first_key_image);
/*
// K_v = K_return - k_idx * T
CarrotPaymentProposalV1 proposal_with_kv = proposal;
const bool is_sparc = (k_idx != crypto::null_skey) && sc_isnonzero(to_bytes(k_idx)); // check here! for zero its not needed
if (is_sparc)
{
// Calculate K_v = K_return - k_idx * T
const rct::key K_return_rct = rct::pk2rct(proposal.destination.address_view_pubkey);
const rct::key k_idx_T = rct::scalarmultKey(rct::pk2rct(crypto::get_T()), rct::sk2rct(k_idx));
rct::key K_v_rct;
rct::subKeys(K_v_rct, K_return_rct, k_idx_T);
proposal_with_kv.destination.address_view_pubkey = rct::rct2pk(K_v_rct);
}
*/
mx25519_pubkey s_sender_receiver_unctx; auto dhe_wiper = auto_wiper(s_sender_receiver_unctx);
get_normal_proposal_ecdh_parts(proposal,
input_context,
output_enote_out.enote.enote_ephemeral_pubkey,
s_sender_receiver_unctx);
// 4. build the output enote address pieces
crypto::hash s_sender_receiver; auto q_wiper = auto_wiper(s_sender_receiver);
encrypted_return_pubkey_t return_pubkey;
get_external_output_proposal_parts(
s_sender_receiver_unctx,
proposal.destination.address_spend_pubkey,
proposal.destination.payment_id,
proposal.amount,
CarrotEnoteType::PAYMENT,
output_enote_out.enote.enote_ephemeral_pubkey,
input_context,
s_view_balance_dev,
false, // coinbase_amount_commitment
s_sender_receiver,
output_enote_out.amount_blinding_factor,
output_enote_out.enote.amount_commitment,
output_enote_out.enote.onetime_address,
output_enote_out.enote.amount_enc,
encrypted_payment_id_out,
output_enote_out.enote.view_tag,
return_pubkey
);
// Override the onetime address
crypto::secret_key k_idx;
make_sparc_return_index(s_sender_receiver_unctx.data, input_context, K_o, idx, k_idx);
rct::key K_r = rct::addKeys(rct::pk2rct(proposal.destination.address_spend_pubkey),rct::pk2rct(proposal.destination.address_view_pubkey));
rct::key K_idx = rct::scalarmultKey(rct::pk2rct(crypto::get_T()), rct::sk2rct(k_idx));
output_enote_out.enote.onetime_address = rct::rct2pk(rct::addKeys(K_r, K_idx));
// Recalculate the view tag : vt = H_3(s_sr || input_context || Ksra)
make_carrot_view_tag(s_sender_receiver_unctx.data, input_context, output_enote_out.enote.onetime_address, output_enote_out.enote.view_tag);
// Recalculate a_enc = BytesToInt64(a) XOR m_a
output_enote_out.enote.amount_enc = encrypt_carrot_amount(proposal.amount, s_sender_receiver, output_enote_out.enote.onetime_address);
// Recalculate anchor_enc = anchor XOR m_anchor
output_enote_out.enote.anchor_enc = encrypt_carrot_anchor(proposal.randomness, s_sender_receiver, output_enote_out.enote.onetime_address);
// Recalculate the pid_enc = pid XOR m_pid
encrypted_payment_id_out = encrypt_legacy_payment_id(proposal.destination.payment_id, s_sender_receiver, output_enote_out.enote.onetime_address);
// 6. save the amount & first key image & asset type
output_enote_out.amount = proposal.amount;
output_enote_out.enote.asset_type = proposal.asset_type;
output_enote_out.enote.tx_first_key_image = tx_first_key_image;
// disable returning an already returned tx.
output_enote_out.enote.return_enc = crypto::rand<carrot::encrypted_return_pubkey_t>();
}
//-------------------------------------------------------------------------------------------------------------------
void get_output_proposal_return_v1(const CarrotPaymentProposalV1 &proposal,
const crypto::key_image &tx_first_key_image,
const view_balance_secret_device *s_view_balance_dev,
@@ -587,8 +499,6 @@ void get_output_proposal_internal_v1(const CarrotPaymentProposalSelfSendV1 &prop
const view_balance_secret_device &s_view_balance_dev,
const crypto::key_image &tx_first_key_image,
const std::optional<mx25519_pubkey> &other_enote_ephemeral_pubkey,
const cryptonote::transaction_type tx_type,
RCTOutputEnoteProposal &return_enote_out,
RCTOutputEnoteProposal &output_enote_out)
{
// 1. sanity checks
@@ -647,40 +557,9 @@ void get_output_proposal_internal_v1(const CarrotPaymentProposalSelfSendV1 &prop
// 9. save the enote ephemeral pubkey, first tx key image, and amount
output_enote_out.enote.enote_ephemeral_pubkey = enote_ephemeral_pubkey;
output_enote_out.enote.tx_first_key_image = tx_first_key_image;
output_enote_out.enote.asset_type = proposal.asset_type;
output_enote_out.enote.asset_type = "SAL1";
output_enote_out.enote.return_enc = crypto::rand<carrot::encrypted_return_pubkey_t>();
output_enote_out.amount = proposal.amount;
// 10. construct the stake return enote
if (tx_type == cryptonote::transaction_type::STAKE || tx_type == cryptonote::transaction_type::CREATE_TOKEN) {
// make k_return
crypto::secret_key k_return;
s_view_balance_dev.make_internal_return_privkey(input_context, output_enote_out.enote.onetime_address, k_return);
// compute K_return = k_return * G
crypto::public_key return_pub;
crypto::secret_key_to_public_key(k_return, return_pub);
// Make a destination address for the return
CarrotDestinationV1 return_destination;
make_carrot_main_address_v1(output_enote_out.enote.onetime_address, return_pub, return_destination);
// Create the return proposal, using the return address and the amount
const CarrotPaymentProposalV1 proposal_return = CarrotPaymentProposalV1{
.destination = return_destination,
.amount = 0,
.randomness = gen_janus_anchor()
};
encrypted_payment_id_t encrypted_payment_id_return;
get_output_proposal_return_v1(
proposal_return,
tx_first_key_image,
nullptr, // s_view_balance_dev
return_enote_out,
encrypted_payment_id_return
);
}
}
//-------------------------------------------------------------------------------------------------------------------
CarrotPaymentProposalV1 gen_carrot_payment_proposal_v1(const bool is_subaddress,
+4 -23
View File
@@ -82,8 +82,6 @@ struct CarrotPaymentProposalSelfSendV1 final
std::optional<mx25519_pubkey> enote_ephemeral_pubkey;
/// anchor: arbitrary, pre-encrypted message for _internal_ selfsends
std::optional<janus_anchor_t> internal_message;
/// asset type
std::string asset_type;
};
struct RCTOutputEnoteProposal
@@ -139,21 +137,6 @@ void get_output_proposal_normal_v1(const CarrotPaymentProposalV1 &proposal,
RCTOutputEnoteProposal &output_enote_out,
encrypted_payment_id_t &encrypted_payment_id_out);
/**
* brief: get_output_proposal_paymentchannel_v1 - convert the carrot proposal to an output proposal
* param: proposal -
* param: tx_first_key_image -
* param: k_view_dev -
* outparam: output_enote_out -
* outparam: encrypted_payment_id_out - pid_enc
*/
void get_output_proposal_paymentchannel_v1(const CarrotPaymentProposalV1 &proposal,
const crypto::key_image &tx_first_key_image,
const view_balance_secret_device *s_view_balance_dev,
const crypto::public_key &K_o,
const uint64_t idx,
RCTOutputEnoteProposal &output_enote_out,
encrypted_payment_id_t &encrypted_payment_id_out);
/**
* brief: get_output_proposal_return_v1 - convert the carrot proposal to an output proposal
* param: proposal -
* param: tx_first_key_image -
@@ -162,10 +145,10 @@ void get_output_proposal_paymentchannel_v1(const CarrotPaymentProposalV1 &propos
* outparam: encrypted_payment_id_out - pid_enc
*/
void get_output_proposal_return_v1(const CarrotPaymentProposalV1 &proposal,
const crypto::key_image &tx_first_key_image,
const view_balance_secret_device *s_view_balance_dev,
RCTOutputEnoteProposal &output_enote_out,
encrypted_payment_id_t &encrypted_payment_id_out);
const crypto::key_image &tx_first_key_image,
const view_balance_secret_device *s_view_balance_dev,
RCTOutputEnoteProposal &output_enote_out,
encrypted_payment_id_t &encrypted_payment_id_out);
/**
* brief: get_output_proposal_special_v1 - convert the carrot proposal to an output proposal (external selfsend)
* param: proposal -
@@ -192,8 +175,6 @@ void get_output_proposal_internal_v1(const CarrotPaymentProposalSelfSendV1 &prop
const view_balance_secret_device &s_view_balance_dev,
const crypto::key_image &tx_first_key_image,
const std::optional<mx25519_pubkey> &other_enote_ephemeral_pubkey,
const cryptonote::transaction_type tx_type,
RCTOutputEnoteProposal &return_enote_out,
RCTOutputEnoteProposal &output_enote_out);
/**
* brief: gen_jamtis_payment_proposal_v1 - generate a random proposal
+21 -189
View File
@@ -70,104 +70,6 @@ static crypto::secret_key make_enote_ephemeral_privkey_sender(const janus_anchor
return enote_ephemeral_privkey;
}
//-------------------------------------------------------------------------------------------------------------------
bool scan_return_output(
const crypto::public_key &return_onetime_address,
const mx25519_pubkey &return_ephemeral_pubkey,
const carrot::view_tag_t &return_view_tag,
const carrot::encrypted_janus_anchor_t &return_anchor_enc,
const carrot::encrypted_amount_t &return_amount_enc,
const std::optional<rct::key> amount_commitment,
const carrot::input_context_t &return_input_context,
carrot::carrot_and_legacy_account &account,
crypto::public_key &address_spend_pubkey_out,
rct::xmr_amount &amount_out,
crypto::secret_key &amount_blinding_factor_out
) {
const auto &return_output_map = account.get_return_output_map_ref();
CHECK_AND_ASSERT_MES(return_output_map.count(return_onetime_address), false, "return output not found");
const auto &origin_tx = return_output_map.at(return_onetime_address);
// 1. make k_return
crypto::secret_key k_return;
account.s_view_balance_dev.make_internal_return_privkey(origin_tx.input_context, origin_tx.K_o, k_return);
// 2. compute K_return' = k_return * G
crypto::public_key K_return;
crypto::secret_key_to_public_key(k_return, K_return);
// 3. ssr
mx25519_pubkey shared_secret_return_unctx;
crypto::hash shared_secret_return;
carrot::make_carrot_uncontextualized_shared_key_receiver(k_return, return_ephemeral_pubkey, shared_secret_return_unctx);
carrot::make_carrot_sender_receiver_secret(
shared_secret_return_unctx.data,
return_ephemeral_pubkey,
return_input_context,
shared_secret_return
);
// 4. verify the view_tag
CHECK_AND_ASSERT_MES(
carrot::test_carrot_view_tag(
shared_secret_return_unctx.data,
return_input_context,
return_onetime_address,
return_view_tag
),
false,
"view tag verification failed for carrot coinbase enote"
);
// 5. compute anchor_return
carrot::janus_anchor_t recovered_anchor_return =
carrot::decrypt_carrot_anchor(return_anchor_enc, shared_secret_return, return_onetime_address);
// 6. compute d_e'
crypto::secret_key recovered_ephemeral_privkey_return;
carrot::make_carrot_enote_ephemeral_privkey(
recovered_anchor_return,
return_input_context,
origin_tx.K_change,
carrot::null_payment_id,
recovered_ephemeral_privkey_return
);
// 7. compute D_e'
mx25519_pubkey recovered_ephemeral_pubkey_return;
carrot::make_carrot_enote_ephemeral_pubkey(
recovered_ephemeral_privkey_return,
origin_tx.K_change,
false,
recovered_ephemeral_pubkey_return
);
// 8. verify the enote ephemeral pubkey
CHECK_AND_ASSERT_MES(
memcmp(recovered_ephemeral_pubkey_return.data, return_ephemeral_pubkey.data, sizeof(mx25519_pubkey)) == 0,
false,
"carrot coinbase enote protection verification failed"
);
amount_out = carrot::decrypt_carrot_amount(return_amount_enc, shared_secret_return, return_onetime_address);
address_spend_pubkey_out = origin_tx.K_change;
if (amount_commitment)
{
CHECK_AND_ASSERT_MES(
carrot::try_recompute_carrot_amount_commitment(shared_secret_return,
amount_out,
address_spend_pubkey_out,
carrot::CarrotEnoteType::PAYMENT,
amount_commitment.value(),
amount_blinding_factor_out
),
false,
"failed to recompute carrot amount commitment for return output"
);
}
return true;
}
//-------------------------------------------------------------------------------------------------------------------
static bool try_scan_carrot_coinbase_enote_checked(
const CarrotCoinbaseEnoteV1 &enote,
const mx25519_pubkey &s_sender_receiver_unctx,
@@ -387,11 +289,6 @@ bool try_scan_carrot_enote_external_sender(const CarrotEnoteV1 &enote,
CarrotEnoteType &enote_type_out,
const bool check_pid)
{
epee::span<const crypto::public_key> main_address_spend_pubkeys;
if (destination.is_subaddress)
main_address_spend_pubkeys = {};
else
main_address_spend_pubkeys = {&destination.address_spend_pubkey, 1};
crypto::public_key recovered_address_spend_pubkey;
payment_id_t recovered_payment_id;
CarrotEnoteType recovered_enote_type;
@@ -400,7 +297,7 @@ bool try_scan_carrot_enote_external_sender(const CarrotEnoteV1 &enote,
if (!try_scan_carrot_enote_external_normal_checked(enote,
encrypted_payment_id,
s_sender_receiver_unctx,
main_address_spend_pubkeys,
{&destination.address_spend_pubkey, 1},
sender_extension_g_out,
sender_extension_t_out,
recovered_address_spend_pubkey,
@@ -464,108 +361,43 @@ bool try_scan_carrot_enote_external_receiver(const CarrotEnoteV1 &enote,
}
//-------------------------------------------------------------------------------------------------------------------
bool try_scan_carrot_enote_internal_receiver(const CarrotEnoteV1 &enote,
carrot::carrot_and_legacy_account &account,
const view_balance_secret_device &s_view_balance_dev,
crypto::secret_key &sender_extension_g_out,
crypto::secret_key &sender_extension_t_out,
crypto::public_key &address_spend_pubkey_out,
rct::xmr_amount &amount_out,
crypto::secret_key &amount_blinding_factor_out,
CarrotEnoteType &enote_type_out,
janus_anchor_t &internal_message_out,
crypto::public_key &return_address_out,
bool &is_return_out)
janus_anchor_t &internal_message_out)
{
// Determine whether this is a full wallet or a watch-only wallet
const cryptonote::account_keys &keys = account.get_keys();
// input_context
const input_context_t input_context = make_carrot_input_context(enote.tx_first_key_image);
// assume that the enote is not a return output
is_return_out = false;
// vt = H_3(s_sr || input_context || Ko)
view_tag_t nominal_view_tag;
account.s_view_balance_dev.make_internal_view_tag(input_context, enote.onetime_address, nominal_view_tag);
s_view_balance_dev.make_internal_view_tag(input_context, enote.onetime_address, nominal_view_tag);
// test view tag
if (nominal_view_tag == enote.view_tag) {
// s^ctx_sr = H_32(s_vb, D_e, input_context)
crypto::hash s_sender_receiver;
account.s_view_balance_dev.make_internal_sender_receiver_secret(enote.enote_ephemeral_pubkey,
input_context,
s_sender_receiver);
if (!try_scan_carrot_enote_internal_burnt(enote,
s_sender_receiver,
sender_extension_g_out,
sender_extension_t_out,
address_spend_pubkey_out,
amount_out,
amount_blinding_factor_out,
enote_type_out,
internal_message_out))
return false;
// we received a change output
// save the Kr = K_change + K_return to out subaddress map
for (const auto &output_key : enote.tx_output_keys) {
// make k_return
crypto::secret_key k_return;
const carrot::input_context_t input_context = carrot::make_carrot_input_context(enote.tx_first_key_image);
account.s_view_balance_dev.make_internal_return_privkey(input_context, output_key, k_return);
// compute K_return = k_return * G
crypto::public_key K_return;
crypto::secret_key_to_public_key(k_return, K_return);
// compute K_r = K_return + K_o
crypto::public_key K_r = rct::rct2pk(rct::addKeys(rct::pk2rct(K_return), rct::pk2rct(enote.onetime_address)));
// calculate the key image for the return output
crypto::secret_key sum_g;
sc_add(to_bytes(sum_g), to_bytes(sender_extension_g_out), to_bytes(k_return));
crypto::key_image key_image = account.derive_key_image_view_only(address_spend_pubkey_out,
sum_g,
sender_extension_t_out,
K_r
);
// HERE BE DRAGONS!!!
// SRCG: test whether this will even work for return_payment detection
account.insert_return_output_info({{K_r, {input_context, output_key, enote.onetime_address, address_spend_pubkey_out, key_image, sum_g, sender_extension_t_out}}});
//account.insert_return_output_info({{K_r, {input_context, output_key, address_spend_pubkey_out, key_image, sum_g, sender_extension_t_out}}});
// LAND AHOY!!!
}
// janus protection checks are not needed for internal scans
return true;
}
// check for known return addresses
const auto &return_map = account.get_return_output_map_ref();
if (return_map.find(enote.onetime_address) == return_map.end())
if (nominal_view_tag != enote.view_tag)
return false;
// scan the return output
if (!scan_return_output(
enote.onetime_address,
enote.enote_ephemeral_pubkey,
enote.view_tag,
enote.anchor_enc,
enote.amount_enc,
enote.amount_commitment,
carrot::make_carrot_input_context(enote.tx_first_key_image),
account,
address_spend_pubkey_out,
amount_out,
amount_blinding_factor_out))
return false;
// s^ctx_sr = H_32(s_vb, D_e, input_context)
crypto::hash s_sender_receiver;
s_view_balance_dev.make_internal_sender_receiver_secret(enote.enote_ephemeral_pubkey,
input_context,
s_sender_receiver);
// if we come here, we have a return output
is_return_out = true;
return_address_out = enote.onetime_address;
return true;
return try_scan_carrot_enote_internal_burnt(enote,
s_sender_receiver,
sender_extension_g_out,
sender_extension_t_out,
address_spend_pubkey_out,
amount_out,
amount_blinding_factor_out,
enote_type_out,
internal_message_out);
// janus protection checks are not needed for internal scans
}
//-------------------------------------------------------------------------------------------------------------------
} //namespace carrot
+2 -19
View File
@@ -39,7 +39,6 @@
#include "carrot_enote_types.h"
#include "device.h"
#include "span.h"
#include "account.h"
//third party headers
@@ -179,30 +178,14 @@ bool try_scan_carrot_enote_external_receiver(const CarrotEnoteV1 &enote,
* return: true iff the scan process succeeded
*/
bool try_scan_carrot_enote_internal_receiver(const CarrotEnoteV1 &enote,
carrot::carrot_and_legacy_account &account,
const view_balance_secret_device &s_view_balance_dev,
crypto::secret_key &sender_extension_g_out,
crypto::secret_key &sender_extension_t_out,
crypto::public_key &address_spend_pubkey_out,
rct::xmr_amount &amount_out,
crypto::secret_key &amount_blinding_factor_out,
CarrotEnoteType &enote_type_out,
janus_anchor_t &internal_message_out,
crypto::public_key &return_address_out,
bool &is_return_out);
janus_anchor_t &internal_message_out);
//! @TODO: try_scan_carrot_enote_internal_sender(): can't validate burning w/o passing s_sr = s_vb
bool scan_return_output(
const crypto::public_key &return_onetime_address,
const mx25519_pubkey &return_ephemeral_pubkey,
const carrot::view_tag_t &return_view_tag,
const carrot::encrypted_janus_anchor_t &return_anchor_enc,
const carrot::encrypted_amount_t &return_amount_enc,
const std::optional<rct::key> amount_commitment,
const carrot::input_context_t &return_input_context,
carrot::carrot_and_legacy_account &account,
crypto::public_key &address_spend_pubkey_out,
rct::xmr_amount &amount_out,
crypto::secret_key &amount_blinding_factor_out
);
} //namespace carrot
+1
View File
@@ -27,6 +27,7 @@
# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
set(carrot_impl_sources
account.cpp
address_device_ram_borrowed.cpp
address_utils_compat.cpp
format_utils.cpp
@@ -110,7 +110,7 @@ CarrotDestinationV1 carrot_and_legacy_account::subaddress(const subaddress_index
return addr;
}
//----------------------------------------------------------------------------------------------------------------------
const std::unordered_map<crypto::public_key, cryptonote::subaddress_index> carrot_and_legacy_account::get_subaddress_map_cn() const
std::unordered_map<crypto::public_key, cryptonote::subaddress_index> carrot_and_legacy_account::get_subaddress_map_cn() const
{
std::unordered_map<crypto::public_key, cryptonote::subaddress_index> res;
for (const auto &p : subaddress_map)
@@ -120,15 +120,10 @@ const std::unordered_map<crypto::public_key, cryptonote::subaddress_index> carro
return res;
}
//----------------------------------------------------------------------------------------------------------------------
const std::unordered_map<crypto::public_key, subaddress_index_extended>& carrot_and_legacy_account::get_subaddress_map_ref() const {
std::unordered_map<crypto::public_key, subaddress_index_extended>& carrot_and_legacy_account::get_subaddress_map_ref() {
return subaddress_map;
}
//----------------------------------------------------------------------------------------------------------------------
const std::unordered_map<crypto::public_key, return_output_info_t>&
carrot_and_legacy_account::get_return_output_map_ref() const {
return return_output_map;
}
//----------------------------------------------------------------------------------------------------------------------
void carrot_and_legacy_account::opening_for_subaddress(const subaddress_index_extended &subaddress_index,
crypto::secret_key &address_privkey_g_out,
crypto::secret_key &address_privkey_t_out,
@@ -282,62 +277,13 @@ crypto::key_image carrot_and_legacy_account::derive_key_image(const crypto::publ
return L;
}
//----------------------------------------------------------------------------------------------------------------------
crypto::key_image carrot_and_legacy_account::derive_key_image_view_only(const crypto::public_key &address_spend_pubkey,
const crypto::secret_key &sender_extension_g,
const crypto::secret_key &sender_extension_t,
const crypto::public_key &onetime_address) const
{
const auto it = subaddress_map.find(address_spend_pubkey);
CHECK_AND_ASSERT_THROW_MES(it != subaddress_map.cend(),
"carrot and legacy account: derive key image view only: cannot find subaddress");
const bool is_subaddress = it->second.index.is_subaddress();
const uint32_t major_index = it->second.index.major;
const uint32_t minor_index = it->second.index.minor;
const cryptonote::account_keys &keys = get_keys();
crypto::secret_key address_index_generator;
crypto::secret_key subaddress_scalar;
crypto::secret_key subaddress_extension;
crypto::secret_key address_privkey_g;
crypto::secret_key x;
CHECK_AND_ASSERT_THROW_MES(it->second.derive_type == AddressDeriveType::Carrot,
"carrot and legacy account: derive key image view only: not a Carrot address");
// s^j_gen = H_32[s_ga](j_major, j_minor)
make_carrot_index_extension_generator(keys.s_generate_address, major_index, minor_index, address_index_generator);
if (is_subaddress)
{
// k^j_subscal = H_n(K_s, j_major, j_minor, s^j_gen)
make_carrot_subaddress_scalar(keys.m_carrot_account_address.m_spend_public_key, address_index_generator, major_index, minor_index, subaddress_scalar);
}
else
{
// k^j_subscal = 1
sc_1(to_bytes(subaddress_scalar));
}
// k^g_a = k_gi * k^j_subscal
sc_mul(to_bytes(address_privkey_g), to_bytes(keys.k_generate_image), to_bytes(subaddress_scalar));
// x = k^{j,g}_addr + k^g_o
sc_add(to_bytes(x), to_bytes(address_privkey_g), to_bytes(sender_extension_g));
crypto::key_image L;
crypto::generate_key_image(onetime_address, x, L);
return L;
}
//----------------------------------------------------------------------------------------------------------------------
void carrot_and_legacy_account::generate_subaddress_map(const std::pair<size_t, size_t>& lookahead_size)
void carrot_and_legacy_account::generate_subaddress_map()
{
const std::vector<AddressDeriveType> derive_types{AddressDeriveType::Carrot, AddressDeriveType::PreCarrot};
for (uint32_t major_index = 0; major_index <= lookahead_size.first; ++major_index)
for (uint32_t major_index = 0; major_index <= MAX_SUBADDRESS_MAJOR_INDEX; ++major_index)
{
for (uint32_t minor_index = 0; minor_index <= lookahead_size.second; ++minor_index)
for (uint32_t minor_index = 0; minor_index <= MAX_SUBADDRESS_MINOR_INDEX; ++minor_index)
{
for (const AddressDeriveType derive_type : derive_types)
{
@@ -364,64 +310,6 @@ crypto::secret_key carrot_and_legacy_account::generate(
return retval;
}
//----------------------------------------------------------------------------------------------------------------------
void carrot_and_legacy_account::set_keys(const cryptonote::account_keys& keys, bool copy_spend_secret_keys)
{
// CN keys
m_keys.m_account_address = keys.m_account_address;
if (copy_spend_secret_keys) m_keys.m_spend_secret_key = keys.m_spend_secret_key;
m_keys.m_view_secret_key = keys.m_view_secret_key;
if (copy_spend_secret_keys) m_keys.m_multisig_keys = keys.m_multisig_keys;
m_keys.m_device = keys.m_device;
m_keys.m_encryption_iv = keys.m_encryption_iv;
// Carrot keys
if (copy_spend_secret_keys) m_keys.s_master = keys.s_master;
if (copy_spend_secret_keys) m_keys.k_prove_spend = keys.k_prove_spend;
m_keys.s_view_balance = keys.s_view_balance;
m_keys.k_view_incoming = keys.k_view_incoming;
m_keys.k_generate_image = keys.k_generate_image;
m_keys.s_generate_address = keys.s_generate_address;
m_keys.m_carrot_account_address = keys.m_carrot_account_address;
m_keys.m_carrot_main_address = keys.m_carrot_main_address;
}
//----------------------------------------------------------------------------------------------------------------------
void carrot_and_legacy_account::create_from_svb_key(const cryptonote::account_public_address& address, const crypto::secret_key& svb_key)
{
// top level keys
m_keys.s_master = crypto::null_skey;
make_carrot_provespend_key(m_keys.s_master, m_keys.k_prove_spend);
m_keys.s_view_balance = svb_key;
// view balance keys
make_carrot_viewincoming_key(m_keys.s_view_balance, m_keys.k_view_incoming);
make_carrot_generateimage_key(m_keys.s_view_balance, m_keys.k_generate_image);
make_carrot_generateaddress_secret(m_keys.s_view_balance, m_keys.s_generate_address);
// carrot account address - use the provided address spend pubkey
m_keys.m_carrot_account_address = address;
k_view_incoming_dev.view_key_scalar_mult_ed25519(m_keys.m_carrot_account_address.m_spend_public_key,
m_keys.m_carrot_account_address.m_view_public_key
);
// carrot main wallet address
m_keys.m_carrot_main_address = address;
k_view_incoming_dev.view_key_scalar_mult_ed25519(crypto::get_G(),
m_keys.m_carrot_main_address.m_view_public_key
);
// Store fields for Carrot
m_keys.m_spend_secret_key = crypto::null_skey;
m_keys.m_view_secret_key = crypto::null_skey;
m_keys.m_account_address = {crypto::null_pkey, crypto::null_pkey, false};
// Update ALL addresses to be Carrot-only
m_keys.m_carrot_account_address.m_is_carrot = true;
m_keys.m_carrot_main_address.m_is_carrot = true;
// Set the default derive type for addresses
this->default_derive_type = AddressDeriveType::Carrot;
}
//----------------------------------------------------------------------------------------------------------------------
void carrot_and_legacy_account::set_carrot_keys(const AddressDeriveType default_derive_type)
{
// top level keys
@@ -440,7 +328,6 @@ void carrot_and_legacy_account::set_carrot_keys(const AddressDeriveType default_
m_keys.m_carrot_account_address.m_spend_public_key,
m_keys.m_carrot_account_address.m_view_public_key
);
m_keys.m_carrot_account_address.m_is_carrot = true;
// carrot main wallet address
m_keys.m_carrot_main_address.m_spend_public_key = m_keys.m_carrot_account_address.m_spend_public_key;
@@ -448,29 +335,17 @@ void carrot_and_legacy_account::set_carrot_keys(const AddressDeriveType default_
crypto::get_G(),
m_keys.m_carrot_main_address.m_view_public_key
);
m_keys.m_carrot_main_address.m_is_carrot = true;
this->default_derive_type = default_derive_type;
generate_subaddress_map();
}
//----------------------------------------------------------------------------------------------------------------------
void carrot_and_legacy_account::insert_subaddresses(const std::unordered_map<crypto::public_key, subaddress_index_extended>& subaddress_map_cn)
{
for (const auto &p : subaddress_map_cn) {
subaddress_map.insert({p.first, {{p.second.index.major, p.second.index.minor}, p.second.derive_type, p.second.is_return_spend_key}});
if (p.second.derive_type == AddressDeriveType::PreCarrot) {
// Create a matching Carrot address
const subaddress_index_extended subaddr_index{{p.second.index.major, p.second.index.minor}, AddressDeriveType::Carrot, p.second.is_return_spend_key};
const CarrotDestinationV1 addr = subaddress(subaddr_index);
subaddress_map.insert({addr.address_spend_pubkey, subaddr_index});
}
}
}
//----------------------------------------------------------------------------------------------------------------------
void carrot_and_legacy_account::insert_return_output_info(const std::unordered_map<crypto::public_key, return_output_info_t>& roi_map)
{
for (const auto &p : roi_map)
return_output_map.insert({p.first, p.second});
for (const auto &p : subaddress_map_cn)
subaddress_map.insert({p.first, {{p.second.index.major, p.second.index.minor}, p.second.derive_type, p.second.is_return_spend_key}});
}
//----------------------------------------------------------------------------------------------------------------------
AddressDeriveType carrot_and_legacy_account::resolve_derive_type(const AddressDeriveType derive_type) const
{
+117
View File
@@ -0,0 +1,117 @@
// Copyright (c) 2025, The Monero Project
//
// 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 "carrot_core/account_secrets.h"
#include "carrot_core/address_utils.h"
#include "carrot_core/destination.h"
#include "carrot_core/device_ram_borrowed.h"
#include "carrot_core/enote_utils.h"
#include "carrot_impl/subaddress_index.h"
#include "cryptonote_basic/account.h"
#include "cryptonote_basic/subaddress_index.h"
//----------------------------------------------------------------------------------------------------------------------
static constexpr std::uint32_t MAX_SUBADDRESS_MAJOR_INDEX = 5;
static constexpr std::uint32_t MAX_SUBADDRESS_MINOR_INDEX = 20;
namespace carrot
{
class carrot_and_legacy_account : public cryptonote::account_base
{
public:
view_incoming_key_ram_borrowed_device k_view_incoming_dev;
view_balance_secret_ram_borrowed_device s_view_balance_dev;
generate_address_secret_ram_borrowed_device s_generate_address_dev;
AddressDeriveType default_derive_type;
carrot_and_legacy_account(): k_view_incoming_dev(get_keys().k_view_incoming),
s_view_balance_dev(get_keys().s_view_balance),
s_generate_address_dev(get_keys().s_generate_address)
{}
carrot_and_legacy_account(const carrot_and_legacy_account &k) = delete;
carrot_and_legacy_account(carrot_and_legacy_account&&) = delete;
carrot_and_legacy_account& operator=(const carrot_and_legacy_account&) = delete;
carrot_and_legacy_account& operator=(carrot_and_legacy_account&&) = delete;
CarrotDestinationV1 cryptonote_address(const payment_id_t payment_id = null_payment_id,
const AddressDeriveType derive_type = AddressDeriveType::Auto) const;
CarrotDestinationV1 subaddress(const subaddress_index_extended &subaddress_index) const;
std::unordered_map<crypto::public_key, cryptonote::subaddress_index> get_subaddress_map_cn() const;
std::unordered_map<crypto::public_key, subaddress_index_extended>& get_subaddress_map_ref();
// brief: opening_for_subaddress - return (k^g_a, k^t_a) for j s.t. K^j_s = (k^g_a * G + k^t_a * T)
void opening_for_subaddress(const subaddress_index_extended &subaddress_index,
crypto::secret_key &address_privkey_g_out,
crypto::secret_key &address_privkey_t_out,
crypto::public_key &address_spend_pubkey_out) const;
bool try_searching_for_opening_for_subaddress(const crypto::public_key &address_spend_pubkey,
crypto::secret_key &address_privkey_g_out,
crypto::secret_key &address_privkey_t_out) const;
bool try_searching_for_opening_for_onetime_address(const crypto::public_key &address_spend_pubkey,
const crypto::secret_key &sender_extension_g,
const crypto::secret_key &sender_extension_t,
crypto::secret_key &x_out,
crypto::secret_key &y_out) const;
bool can_open_fcmp_onetime_address(const crypto::public_key &address_spend_pubkey,
const crypto::secret_key &sender_extension_g,
const crypto::secret_key &sender_extension_t,
const crypto::public_key &onetime_address) const;
crypto::key_image derive_key_image(const crypto::public_key &address_spend_pubkey,
const crypto::secret_key &sender_extension_g,
const crypto::secret_key &sender_extension_t,
const crypto::public_key &onetime_address) const;
void generate_subaddress_map();
crypto::secret_key generate(
const crypto::secret_key& recovery_key = crypto::secret_key(),
bool recover = false,
bool two_random = false,
const AddressDeriveType default_derive_type = AddressDeriveType::Carrot
);
void set_carrot_keys(const AddressDeriveType default_derive_type = AddressDeriveType::Carrot);
void insert_subaddresses(const std::unordered_map<crypto::public_key, subaddress_index_extended>& subaddress_map);
AddressDeriveType resolve_derive_type(const AddressDeriveType derive_type) const;
private:
std::unordered_map<crypto::public_key, subaddress_index_extended> subaddress_map;
};
}
@@ -86,12 +86,6 @@ inline void serialize(Archive &a, carrot::encrypted_return_pubkey_t &x, const bo
}
//---------------------------------------------------
template <class Archive>
inline void serialize(Archive &a, carrot::rollup_binding_tag_t &x, const boost::serialization::version_type ver)
{
a & x.bytes;
}
//---------------------------------------------------
template <class Archive>
inline void serialize(Archive &a, carrot::CarrotDestinationV1 &x, const boost::serialization::version_type ver)
{
a & x.address_spend_pubkey;
@@ -42,4 +42,3 @@ BLOB_SERIALIZER(carrot::view_tag_t);
BLOB_SERIALIZER(carrot::encrypted_janus_anchor_t);
BLOB_SERIALIZER(carrot::encrypted_payment_id_t);
BLOB_SERIALIZER(carrot::encrypted_return_pubkey_t);
BLOB_SERIALIZER(carrot::rollup_binding_tag_t);
+17 -67
View File
@@ -33,6 +33,7 @@
#include "carrot_core/enote_utils.h"
#include "carrot_core/exceptions.h"
#include "carrot_core/payment_proposal.h"
#include "common/container_helpers.h"
#include "cryptonote_basic/cryptonote_format_utils.h"
#include "cryptonote_core/cryptonote_tx_utils.h"
#include "cryptonote_config.h"
@@ -193,51 +194,25 @@ bool try_load_carrot_extra_v1(
}
//-------------------------------------------------------------------------------------------------------------------
cryptonote::transaction store_carrot_to_transaction_v1(const std::vector<CarrotEnoteV1> &enotes,
const std::vector<crypto::key_image> &key_images,
const std::vector<cryptonote::tx_source_entry> &sources,
const rct::xmr_amount fee,
const cryptonote::transaction_type tx_type,
const rct::xmr_amount tx_amount_burnt,
const std::vector<uint8_t> &change_masks,
const cryptonote::token_metadata_t &token,
const carrot::RCTOutputEnoteProposal &return_enote,
const encrypted_payment_id_t encrypted_payment_id,
const uint8_t hf_version)
const std::vector<crypto::key_image> &key_images,
const std::vector<cryptonote::tx_source_entry> &sources,
const rct::xmr_amount fee,
const cryptonote::transaction_type tx_type,
const std::vector<uint8_t> change_masks,
const encrypted_payment_id_t encrypted_payment_id)
{
const size_t nins = key_images.size();
const size_t nouts = enotes.size();
CHECK_AND_ASSERT_THROW_MES(nins == sources.size(), "invalid inputs/sources size");
CHECK_AND_ASSERT_THROW_MES(change_masks.size() == nouts, "invalid change masks size. Expected: " << nouts - 1 << " got: " << change_masks.size());
// Sanity check asset types - all enotes and sources must be the same
std::string asset_type = "";
for (const auto &enote: enotes) {
if (asset_type == "")
asset_type = enote.asset_type;
else
CHECK_AND_ASSERT_THROW_MES(enote.asset_type == asset_type, "invalid asset_type in enote. Expected: " << asset_type << " got: " << enote.asset_type);
}
for (const auto &source: sources) {
if (asset_type == "")
asset_type = source.asset_type;
else
CHECK_AND_ASSERT_THROW_MES(source.asset_type == asset_type, "invalid asset_type in source. Expected: " << asset_type << " got: " << source.asset_type);
}
cryptonote::transaction tx;
tx.pruned = true;
tx.version = TRANSACTION_VERSION_N_OUTS;
tx.unlock_time = 0;
tx.source_asset_type = asset_type;
tx.destination_asset_type = asset_type;
tx.version = (hf_version >= HF_VERSION_ENABLE_TOKENS) ? TRANSACTION_VERSION_ENABLE_TOKENS : TRANSACTION_VERSION_CARROT;
tx.type =
tx_type == cryptonote::transaction_type::RETURN ? cryptonote::transaction_type::TRANSFER : tx_type;
tx.amount_burnt = (
tx.type == cryptonote::transaction_type::STAKE ||
tx.type == cryptonote::transaction_type::BURN ||
tx.type == cryptonote::transaction_type::CREATE_TOKEN ||
tx.type == cryptonote::transaction_type::ROLLUP
) ? tx_amount_burnt : 0;
tx.source_asset_type = "SAL1";
tx.destination_asset_type = "SAL1";
tx.type = tx_type == cryptonote::transaction_type::RETURN ? cryptonote::transaction_type::TRANSFER : tx_type;
tx.return_address_change_mask.assign(change_masks.begin(), change_masks.end());
tx.vin.reserve(nins);
tx.vout.reserve(nouts);
@@ -259,7 +234,7 @@ cryptonote::transaction store_carrot_to_transaction_v1(const std::vector<CarrotE
//L
tx.vin.emplace_back(cryptonote::txin_to_key{ //@TODO: can save 2 bytes by using slim input type
.amount = 0,
.asset_type = asset_type,
.asset_type = "SAL1",
.key_offsets = cryptonote::absolute_output_offsets_to_relative(key_offsets),
.k_image = key_images.at(i)
});
@@ -277,35 +252,18 @@ cryptonote::transaction store_carrot_to_transaction_v1(const std::vector<CarrotE
}});
//a_enc
rct::ecdhTuple &ecdh_tuple = tx.rct_signatures.ecdhInfo.emplace_back();
rct::ecdhTuple &ecdh_tuple = tools::add_element(tx.rct_signatures.ecdhInfo);
memcpy(ecdh_tuple.amount.bytes, enote.amount_enc.bytes, sizeof(ecdh_tuple.amount));
//C_a
tx.rct_signatures.outPk.push_back(rct::ctkey{rct::key{}, enote.amount_commitment});
//K_return
if (tx_type != cryptonote::transaction_type::STAKE && tx_type != cryptonote::transaction_type::CREATE_TOKEN) {
crypto::public_key K_return;
memcpy(K_return.data, enote.return_enc.bytes, sizeof(crypto::public_key));
tx.return_address_list.push_back(K_return);
}
crypto::public_key K_return;
memcpy(K_return.data, enote.return_enc.bytes, sizeof(crypto::public_key));
tx.return_address_list.push_back(K_return);
}
// store the return pubkey for stake txs
if (tx_type == cryptonote::transaction_type::STAKE || tx_type == cryptonote::transaction_type::CREATE_TOKEN)
{
tx.protocol_tx_data.version = 1;
memcpy(tx.protocol_tx_data.return_address.data, return_enote.enote.onetime_address.data, sizeof(crypto::public_key));
memcpy(tx.protocol_tx_data.return_pubkey.data, return_enote.enote.enote_ephemeral_pubkey.data, sizeof(crypto::public_key));
tx.protocol_tx_data.return_view_tag = return_enote.enote.view_tag;
tx.protocol_tx_data.return_anchor_enc = return_enote.enote.anchor_enc;
}
if (tx_type == cryptonote::transaction_type::CREATE_TOKEN) {
tx.token_metadata = token;
} else {
tx.token_metadata = cryptonote::token_metadata_t{};
}
//ephemeral pubkeys: D_e
store_carrot_ephemeral_pubkeys_to_extra(enotes, tx.extra);
@@ -379,14 +337,6 @@ bool try_load_carrot_enote_from_transaction_v1(const cryptonote::transaction &tx
//D_e
enote_out.enote_ephemeral_pubkey = enote_ephemeral_pubkeys[ephemeral_pubkey_index];
// save all output keys in order to calculate Kr values.
for (const auto& out: tx.vout) {
const cryptonote::txout_to_carrot_v1 * const carrot_out = boost::strict_get<cryptonote::txout_to_carrot_v1>(&out.target);
if (carrot_out) {
enote_out.tx_output_keys.push_back(carrot_out->key);
}
}
return true;
}
@@ -445,7 +395,7 @@ cryptonote::transaction store_carrot_to_coinbase_transaction_v1(
cryptonote::transaction tx;
tx.type = tx_type;
tx.pruned = false;
tx.version = TRANSACTION_VERSION_CARROT;
tx.version = 2;
tx.unlock_time = CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW;
tx.vin.reserve(1);
tx.vout.reserve(nouts);
+6 -11
View File
@@ -35,7 +35,6 @@
#include "cryptonote_basic/cryptonote_basic.h"
#include "cryptonote_basic/tx_extra.h"
#include "cryptonote_core/cryptonote_tx_utils.h"
#include "carrot_core/payment_proposal.h"
//third party headers
@@ -102,16 +101,12 @@ bool try_load_carrot_extra_v1(
* return: a fully populated, pruned, non-coinbase transaction containing given Carrot information
*/
cryptonote::transaction store_carrot_to_transaction_v1(const std::vector<CarrotEnoteV1> &enotes,
const std::vector<crypto::key_image> &key_images,
const std::vector<cryptonote::tx_source_entry> &sources,
const rct::xmr_amount fee,
const cryptonote::transaction_type tx_type,
const rct::xmr_amount tx_amount_burnt,
const std::vector<uint8_t> &change_masks,
const cryptonote::token_metadata_t &token,
const RCTOutputEnoteProposal &return_enote,
const encrypted_payment_id_t encrypted_payment_id,
const uint8_t hf_version);
const std::vector<crypto::key_image> &key_images,
const std::vector<cryptonote::tx_source_entry> &sources,
const rct::xmr_amount fee,
const cryptonote::transaction_type tx_type,
const std::vector<uint8_t> change_masks,
const encrypted_payment_id_t encrypted_payment_id);
/**
* brief: try_load_carrot_enote_from_transaction_v1 - load one non-coinbase Carrot enote from a cryptonote::transaction
* param: tx -
+23 -30
View File
@@ -88,8 +88,7 @@ static std::pair<std::size_t, boost::multiprecision::uint128_t> input_count_for_
const epee::span<const InputCandidate> input_candidates,
const std::set<std::size_t> &selectable_inputs,
std::size_t max_num_input_count,
const std::map<std::size_t, rct::xmr_amount> &fee_by_input_count,
const bool is_token_transfer)
const std::map<std::size_t, rct::xmr_amount> &fee_by_input_count)
{
// Returns (N, X) where the X is the sum of the amounts of the greatest N <= max_num_input_count
// inputs from selectable_inputs, maximizing X - F(N). F(N) is the fee for this transaction,
@@ -97,7 +96,6 @@ static std::pair<std::size_t, boost::multiprecision::uint128_t> input_count_for_
// the fee, but greater than or equal to the difference of the fee compared to excluding that
// input. If this function returns N == 0, then there aren't enough usable funds, i.e. no N
// exists such that X - F(N) > 0.
// For token transfers, fee is paid separately in SAL1 so we just accumulate all inputs.
if (fee_by_input_count.empty() || selectable_inputs.empty())
return {0, 0};
@@ -127,15 +125,6 @@ static std::pair<std::size_t, boost::multiprecision::uint128_t> input_count_for_
{
const rct::xmr_amount amount = *amount_it;
const rct::xmr_amount current_fee = fee_by_input_count.at(num_ins + 1);
// For token transfers, fee is paid separately in SAL1 - just accumulate inputs
if (is_token_transfer)
{
++num_ins;
cumulative_input_sum += amount;
continue;
}
CARROT_CHECK_AND_THROW(current_fee > last_fee,
carrot_logic_error, "provided fee by input count is not monotonically increasing");
const rct::xmr_amount marginal_fee_diff = current_fee - last_fee;
@@ -329,27 +318,33 @@ std::vector<std::size_t> get_input_counts_in_preferred_order()
// 1 or 2 randomly, then
// other ascending powers of 2, then
// other ascending positive numbers
//! @TODO: MRL discussion about 2 vs 1 default input count when 1 input can pay. If we default
// to 1, then that may reveal more information about the amount, and reveals that one can't pay
// with 1 output when using 2. Vice versa, if we default to 2, then that means that one only
// owns 1 output when using 1. It may be the most advantageous to randomly switch between
// preferring 1 vs 2. See: https://lavalle.pl/planning/node437.html. Con to this approach: if we
// default to 1 over 2 always then there's scenarios where we net save tx fees and proving time.
//static_assert(CARROT_MAX_TX_INPUTS == FCMP_PLUS_PLUS_MAX_INPUTS, "inconsistent input count max limit");
static_assert(CARROT_MIN_TX_INPUTS == 1 && CARROT_MAX_TX_INPUTS == 64,
// preferring 1 vs 2. See: https://lavalle.pl/planning/node437.html. Con to this approach: if we
// default to 1 over 2 always then there's scenarios where we net save tx fees and proving time.
//static_assert(CARROT_MAX_TX_INPUTS == FCMP_PLUS_PLUS_MAX_INPUTS, "inconsistent input count max limit");
static_assert(CARROT_MIN_TX_INPUTS == 1 && CARROT_MAX_TX_INPUTS == 128,
"refactor this function for different input count limits");
const bool random_bit = 0 == (crypto::rand<uint8_t>() & 0x01);
if (random_bit)
return {2, 1, 4, 8, 16, 32, 64, 3, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30, 31, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63};
return {2, 1, 4, 8, 16, 32, 64, 128, 3, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30, 31, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 65, 66, 67, 68, 69, 70, 71, 72, 73,
74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116,
117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127};
else
return {1, 2, 4, 8, 16, 32, 64, 3, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30, 31, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63};
return {1, 2, 4, 8, 16, 32, 64, 128, 3, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27, 28, 29, 30, 31, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 65, 66, 67, 68, 69, 70, 71, 72, 73,
74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116,
117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127};
}
//-------------------------------------------------------------------------------------------------------------------
select_inputs_func_t make_single_transfer_input_selector(
@@ -383,12 +378,11 @@ select_inputs_func_t make_single_transfer_input_selector(
// 3. Calculate minimum required input money sum for a given input count
const bool subtract_fee = flags & IS_KNOWN_FEE_SUBTRACTABLE;
const bool is_token_transfer = flags & IS_TOKEN_TRANSFER;
std::map<std::size_t, boost::multiprecision::uint128_t> required_money_by_input_count;
for (const auto &fee_and_input_count : fee_by_input_count)
{
required_money_by_input_count[fee_and_input_count.first] =
nominal_output_sum + ((subtract_fee || is_token_transfer) ? 0 : fee_and_input_count.second);
nominal_output_sum + (subtract_fee ? 0 : fee_and_input_count.second);
}
const boost::multiprecision::uint128_t absolute_minimum_required_money
= required_money_by_input_count.cbegin()->second;
@@ -402,10 +396,9 @@ select_inputs_func_t make_single_transfer_input_selector(
"Not enough money in all inputs (" << cryptonote::print_money(total_candidate_money)
<< ") to fund minimum output sum (" << cryptonote::print_money(absolute_minimum_required_money) << ')');
// const bool is_token_transfer = flags & IS_TOKEN_TRANSFER;
std::set<std::size_t> all_idxs; for (std::size_t i = 0; i < input_candidates.size(); ++i) all_idxs.insert(i);
const std::pair<std::size_t, boost::multiprecision::uint128_t> max_usable_money =
input_count_for_max_usable_money(input_candidates, all_idxs, CARROT_MAX_TX_INPUTS, fee_by_input_count, is_token_transfer);
input_count_for_max_usable_money(input_candidates, all_idxs, CARROT_MAX_TX_INPUTS, fee_by_input_count);
CARROT_CHECK_AND_THROW(max_usable_money.second >= absolute_minimum_required_money,
not_enough_usable_money,
"Not enough usable money in top " << max_usable_money.first << " inputs ("
@@ -430,7 +423,7 @@ select_inputs_func_t make_single_transfer_input_selector(
// Skip if not enough money in this selectable set for max number of tx inputs...
const auto max_usable_money = input_count_for_max_usable_money(input_candidates,
input_candidate_subset, CARROT_MAX_TX_INPUTS, fee_by_input_count, is_token_transfer);
input_candidate_subset, CARROT_MAX_TX_INPUTS, fee_by_input_count);
if (!max_usable_money.first)
continue;
else if (max_usable_money.second < required_money_by_input_count.at(max_usable_money.first))
@@ -454,7 +447,7 @@ select_inputs_func_t make_single_transfer_input_selector(
// Skip if not enough money in this selectable set for exact number of inputs...
const auto max_usable_money = input_count_for_max_usable_money(input_candidates,
input_candidate_subset, n_inputs, fee_by_input_count, is_token_transfer);
input_candidate_subset, n_inputs, fee_by_input_count);
if (max_usable_money.first != n_inputs)
continue;
else if (max_usable_money.second < required_money)
+2 -5
View File
@@ -52,17 +52,14 @@ struct InputCandidate
namespace InputSelectionFlags
{
// Quantum forward secrecy (ON = unsafe)
static constexpr std::uint32_t ALLOW_EXTERNAL_INPUTS_IN_NORMAL_TRANSFERS = 1 << 0; // 000..00000001
static constexpr std::uint32_t ALLOW_PRE_CARROT_INPUTS_IN_NORMAL_TRANSFERS = 1 << 1; // 000..00000010
static constexpr std::uint32_t ALLOW_EXTERNAL_INPUTS_IN_NORMAL_TRANSFERS = 1 << 0;
static constexpr std::uint32_t ALLOW_PRE_CARROT_INPUTS_IN_NORMAL_TRANSFERS = 1 << 1;
static constexpr std::uint32_t ALLOW_MIXED_INTERNAL_EXTERNAL = 1 << 2;
static constexpr std::uint32_t ALLOW_MIXED_CARROT_PRE_CARROT = 1 << 3;
// Amount handling
static constexpr std::uint32_t IS_KNOWN_FEE_SUBTRACTABLE = 1 << 4;
static constexpr std::uint32_t ALLOW_DUST = 1 << 5;
// Token transfer (fee is paid separately in SAL1 via rollup tx, so no fee for input selection)
static constexpr std::uint32_t IS_TOKEN_TRANSFER = 1 << 6;
}
/**
+1 -7
View File
@@ -60,7 +60,6 @@ void get_output_enote_proposals_from_proposal_v1(const CarrotTransactionProposal
// derive enote proposals
size_t change_index;
RCTOutputEnoteProposal return_enote_out;
std::unordered_map<crypto::public_key, size_t> normal_payments_indices;
get_output_enote_proposals(tx_proposal.normal_payment_proposals,
selfsend_payment_proposal_cores,
@@ -69,7 +68,6 @@ void get_output_enote_proposals_from_proposal_v1(const CarrotTransactionProposal
k_view_dev,
tx_proposal.key_images_sorted.at(0),
output_enote_proposals_out,
return_enote_out,
encrypted_payment_id_out,
tx_proposal.tx_type,
change_index,
@@ -129,12 +127,8 @@ void make_pruned_transaction_from_proposal_v1(const CarrotTransactionProposalV1
tx_proposal.sources,
tx_proposal.fee,
cryptonote::transaction_type::TRANSFER,
0, // tx_amount_burnt
{}, // change_masks
{}, // return_enote
{0},
encrypted_payment_id,
/*hf_version=*/10);
encrypted_payment_id);
// add extra payload and sort
if (!tx_proposal.extra.empty())
+3 -15
View File
@@ -67,8 +67,8 @@ struct CarrotPaymentProposalVerifiableSelfSendV1
*
* For exact details on what goes into the signable transaction hash, see `rct::get_pre_mlsag_hash`.
*/
struct CarrotTransactionProposalV1
{
struct CarrotTransactionProposalV1
{
/// Key images sorted in std::greater order
std::vector<crypto::key_image> key_images_sorted;
// sources in the same order as key_images_sorted.
@@ -86,21 +86,9 @@ struct CarrotPaymentProposalVerifiableSelfSendV1
rct::xmr_amount fee;
/// transaction type, e.g.
cryptonote::transaction_type tx_type;
/// how much money tx burns
rct::xmr_amount amount_burnt;
/// used if this is a CREATE_TOKEN transaction
cryptonote::token_metadata_t token;
/// This field is truly "extra". It should contain only tx.extra fields that aren't present in a
/// normal Carrot transaction, i.e. NOT ephemeral pubkeys nor encrypted PIDs
std::vector<std::uint8_t> extra;
/// Used if this is a TOKEN_TRANSFER or ROLLUP transaction
carrot::rollup_binding_tag_t rollup_binding_tag;
/// Used if this is a ROLLUP transaction
cryptonote::layer2_rollup_data_t layer2_rollup_data;
};
};
} //namespace carrot
+9 -68
View File
@@ -90,7 +90,7 @@ static void append_additional_payment_proposal_if_necessary(
//-------------------------------------------------------------------------------------------------------------------
std::uint64_t get_carrot_default_tx_extra_size(const std::size_t n_outputs)
{
CHECK_AND_ASSERT_THROW_MES(n_outputs <= CARROT_MAX_TX_OUTPUTS,
CHECK_AND_ASSERT_THROW_MES(n_outputs <= FCMP_PLUS_PLUS_MAX_OUTPUTS,
"get_carrot_default_tx_extra_size: n_outputs too high: " << n_outputs);
CHECK_AND_ASSERT_THROW_MES(n_outputs >= CARROT_MIN_TX_OUTPUTS,
"get_carrot_default_tx_extra_size: n_outputs too low: " << n_outputs);
@@ -209,45 +209,16 @@ void make_carrot_transaction_proposal_v1(const std::vector<CarrotPaymentProposal
input_amount_sum += selected_input.amount;
// callback to balance the outputs with the fee and input sum
std::string asset_type = "SAL1"; // default to SAL1
if (!normal_payment_proposals.empty()) {
asset_type = normal_payment_proposals.at(0).asset_type;
} else if (!selfsend_payment_proposals.empty()) {
asset_type = selfsend_payment_proposals.at(0).proposal.asset_type;
}
uint64_t fee = tx_proposal_out.fee;
if (asset_type != "SAL1") {
// check here
if (tx_type != cryptonote::transaction_type::BURN || asset_type != "SAL") {
CARROT_CHECK_AND_THROW(cryptonote::is_valid_custom_asset_type(asset_type),
carrot_logic_error, "make_carrot_transaction_proposal_v1: invalid asset type in payment proposals: " << asset_type);
}
fee = 0; //fee is always in SAL1
}
carve_fees_and_balance(input_amount_sum, fee, normal_payment_proposals, selfsend_payment_proposals);
carve_fees_and_balance(input_amount_sum, tx_proposal_out.fee, normal_payment_proposals, selfsend_payment_proposals);
// sanity check balance
input_amount_sum -= fee;
input_amount_sum -= tx_proposal_out.fee;
for (const CarrotPaymentProposalV1 &normal_payment_proposal : normal_payment_proposals)
input_amount_sum -= normal_payment_proposal.amount;
for (const CarrotPaymentProposalVerifiableSelfSendV1 &selfsend_payment_proposal : selfsend_payment_proposals)
input_amount_sum -= selfsend_payment_proposal.proposal.amount;
if (tx_type != cryptonote::transaction_type::STAKE &&
tx_type != cryptonote::transaction_type::BURN &&
tx_type != cryptonote::transaction_type::CREATE_TOKEN &&
tx_type != cryptonote::transaction_type::ROLLUP)
{
CHECK_AND_ASSERT_THROW_MES(input_amount_sum == 0,
"make_carrot_transaction_proposal_v1: post-carved transaction does not balance");
} else {
tx_proposal_out.amount_burnt = input_amount_sum.convert_to<uint64_t>();
CHECK_AND_ASSERT_THROW_MES(tx_proposal_out.amount_burnt >= 0,
"make_carrot_transaction_proposal_v1: post-carved transaction burnt amount is negative: "
<< tx_proposal_out.amount_burnt);
input_amount_sum -= tx_proposal_out.amount_burnt;
}
CHECK_AND_ASSERT_THROW_MES(input_amount_sum == 0,
"make_carrot_transaction_proposal_v1: post-carved transaction does not balance");
// collect and sort key images
tx_proposal_out.key_images_sorted.reserve(selected_inputs.size());
@@ -257,7 +228,7 @@ void make_carrot_transaction_proposal_v1(const std::vector<CarrotPaymentProposal
tx_proposal_out.key_images_sorted.end(),
std::greater{}); // consensus rules dictate inputs sorted in *reverse* lexicographical order since v7
// set the transaction type & new asset type
// set the transaction type
tx_proposal_out.tx_type = tx_type;
}
//-------------------------------------------------------------------------------------------------------------------
@@ -273,7 +244,6 @@ void make_carrot_transaction_proposal_v1_transfer(
const subaddress_index_extended &change_address_index,
const std::set<std::size_t> &subtractable_normal_payment_proposals,
const std::set<std::size_t> &subtractable_selfsend_payment_proposals,
const std::string &asset_type,
CarrotTransactionProposalV1 &tx_proposal_out)
{
std::vector<CarrotPaymentProposalVerifiableSelfSendV1> selfsend_payment_proposals = selfsend_payment_proposals_in;
@@ -294,8 +264,7 @@ void make_carrot_transaction_proposal_v1_transfer(
.proposal = CarrotPaymentProposalSelfSendV1{
.destination_address_spend_pubkey = change_address_spend_pubkey,
.amount = 0,
.enote_type = add_payment_type_selfsend ? CarrotEnoteType::PAYMENT : CarrotEnoteType::CHANGE,
.asset_type = asset_type
.enote_type = add_payment_type_selfsend ? CarrotEnoteType::PAYMENT : CarrotEnoteType::CHANGE
},
.subaddr_index = change_address_index
});
@@ -304,8 +273,7 @@ void make_carrot_transaction_proposal_v1_transfer(
carve_fees_and_balance_func_t carve_fees_and_balance =
[
&subtractable_normal_payment_proposals,
&subtractable_selfsend_payment_proposals,
&tx_type
&subtractable_selfsend_payment_proposals
]
(
const boost::multiprecision::uint128_t &input_sum_amount,
@@ -414,19 +382,6 @@ void make_carrot_transaction_proposal_v1_transfer(
CHECK_AND_ASSERT_THROW_MES(fee_remainder == 0,
"make unsigned transaction transfer subtractable: bug: fee remainder at end of carve function");
// remove the self send payment we have made to ourself now that we have our change payment.
if (tx_type == cryptonote::transaction_type::STAKE ||
tx_type == cryptonote::transaction_type::BURN ||
tx_type == cryptonote::transaction_type::CREATE_TOKEN ||
tx_type == cryptonote::transaction_type::ROLLUP)
{
selfsend_payment_proposals.back().proposal.enote_ephemeral_pubkey =
selfsend_payment_proposals.front().proposal.enote_ephemeral_pubkey;
selfsend_payment_proposals.erase(selfsend_payment_proposals.begin());
}
}; //end carve_fees_and_balance
// make unsigned transaction with fee carving callback
@@ -453,7 +408,6 @@ void make_carrot_transaction_proposal_v1_sweep(
std::vector<CarrotSelectedInput> &&selected_inputs,
const crypto::public_key &change_address_spend_pubkey,
const subaddress_index_extended &change_address_index,
const std::string &asset_type,
CarrotTransactionProposalV1 &tx_proposal_out)
{
// sanity check payment proposals are provided
@@ -476,19 +430,6 @@ void make_carrot_transaction_proposal_v1_sweep(
CHECK_AND_ASSERT_THROW_MES(bool(normal_payment_proposals.size()) ^ bool(selfsend_payment_proposals.size()),
"make carrot transaction proposal v1 sweep: both normal and self-send payment proposals are provided");
std::vector<CarrotPaymentProposalVerifiableSelfSendV1> selfsend_payment_proposals_inout{selfsend_payment_proposals};
//if (tx_type == cryptonote::transaction_type::RETURN) {
selfsend_payment_proposals_inout.push_back(carrot::CarrotPaymentProposalVerifiableSelfSendV1{
.proposal = carrot::CarrotPaymentProposalSelfSendV1{
.destination_address_spend_pubkey = change_address_spend_pubkey,
.amount = 0,
.enote_type = carrot::CarrotEnoteType::CHANGE,
.asset_type = asset_type
},
.subaddr_index = change_address_index
});
// }
const bool is_selfsend_sweep = !selfsend_payment_proposals.empty();
// define input selection callback, which is just a shuttle for `selected_inputs`
@@ -539,7 +480,7 @@ void make_carrot_transaction_proposal_v1_sweep(
// make unsigned transaction with sweep carving callback and selected inputs
make_carrot_transaction_proposal_v1(normal_payment_proposals,
selfsend_payment_proposals_inout,
selfsend_payment_proposals,
fee_per_weight,
fee_quantization_mask,
extra,
+4 -13
View File
@@ -92,26 +92,19 @@ static size_t estimate_rct_tx_size_carrot(int n_inputs, int mixin, int n_outputs
size += 1 + 6;
// vin
size += n_inputs * (1+1+4+(mixin+1)*2+32);
size += n_inputs * (1+6+4+(mixin+1)*2+32);
// vout
size += n_outputs * (1+1+32+4+3+16);
size += n_outputs * (3+4+16+32);
// extra
size += extra_size;
// rct signatures
// type
size += 1;
// amount_burnt
size += 8;
// return_address data
// NOTE: this will be wrong by 21 bytes for STAKE TXs using `protocol_tx_data_t`
size += n_outputs * (32 + 1);
// rct signatures
// rangeSigs
if (bulletproof || bulletproof_plus)
{
@@ -213,7 +206,6 @@ void make_carrot_transaction_proposal_v1_transfer(
const subaddress_index_extended &change_address_index,
const std::set<std::size_t> &subtractable_normal_payment_proposals,
const std::set<std::size_t> &subtractable_selfsend_payment_proposals,
const std::string &asset_type,
CarrotTransactionProposalV1 &tx_proposal_out);
void make_carrot_transaction_proposal_v1_sweep(
@@ -226,7 +218,6 @@ void make_carrot_transaction_proposal_v1_sweep(
std::vector<CarrotSelectedInput> &&selected_inputs,
const crypto::public_key &change_address_spend_pubkey,
const subaddress_index_extended &change_address_index,
const std::string &asset_type,
CarrotTransactionProposalV1 &tx_proposal_out);
} //namespace carrot
+22 -27
View File
@@ -183,33 +183,28 @@ namespace cryptonote
bool checkpoints::init_default_checkpoints(network_type nettype)
{
if (nettype == MAINNET) {
ADD_CHECKPOINT2(1, "b6b45052e7e182ebaeb14ab713db29ad979115e664d766aa0910e325564a27a6", "0x2");
ADD_CHECKPOINT2(10, "82724681cf6bd934eb3253d041de50206a77627ce40ffe418ce6e0fe392ec684", "0x7812a");
ADD_CHECKPOINT2(20, "4dac7b512d876df05bfa4f39b8dbacd75cb1483fbced8bfc5446ebe21b25a04f", "0xba98f");
ADD_CHECKPOINT2(30, "668246360c93ef791a59157cec9cd09722b32a966051feea399082433138f07b", "0xcc235");
ADD_CHECKPOINT2(40, "9a4183bc1d6e9828eac46505c5ef37ae5447ba6c9325dca02be9e1201f939a7d", "0xdf077");
ADD_CHECKPOINT2(50, "5cd8b089d2e77aed9b803b398c6bff07ca652100cb8fa114c91b72509aeeb7e9", "0xf37eb");
ADD_CHECKPOINT2(60, "0e1acf00dd38e0757996dcdc4b69ad54baf7ebe10ae1e8168b192acb1a0ed7f2", "0x10993b");
ADD_CHECKPOINT2(70, "988977507f388221a927e279307b548a0ae0de10ded8c4f22c315e1b483f921a", "0x121537");
ADD_CHECKPOINT2(80, "88ea1c49b20e7596e21ca8137b2a9fa98558df269a15816fe7d7495f1c63ea43", "0x13a290");
ADD_CHECKPOINT2(90, "254800bb6f9794aad95b2226ffc1a1eef0a817472e1877ae08fac6becb55b147", "0x153a55");
ADD_CHECKPOINT2(100, "ba8d75fad878af26ac2504b4868893a7f86c59f013d0f096925cf53271dd04e8", "0x16e91e");
ADD_CHECKPOINT2(110, "dca0779bfe403730b923fa0918645daeec6096b953be2c554f133460c6fcce35", "0x18acb9");
ADD_CHECKPOINT2(120, "5a57287f6b5c105ae264b88050731c5b9ad1313b916143d7585af1d345e70247", "0x1a88f5");
ADD_CHECKPOINT2(130, "4fd292ac0774461e968924f8097e78ec03eee43a2997deaddbc7993e470a61d6", "0x1c6edd");
ADD_CHECKPOINT2(140, "5a3b6ceeef5fd498ea3330acb8a0e87f2c1566c9b0100ad67237e5664d1f053b", "0x1e4991");
ADD_CHECKPOINT2(150, "78f26d08d39f7d5e1a3548277321471e16c95096fa9bcecbe8a420d406ee249b", "0x202406");
ADD_CHECKPOINT2(160, "7acaab1037ccfbadd3126d2612d5dc154020297f980df0b8df462f9c761d3326", "0x22154b");
ADD_CHECKPOINT2(170, "9541ae934e40fa6749ca3453e47cf5fdf38efbac9efcaa2714121e8a21dd2d24", "0x241ce7");
ADD_CHECKPOINT2(180, "e20bc8ac6aabb6b0792f23a29ce42a577c6a57d177a8ac1a51b68fb6de508045", "0x262b40");
ADD_CHECKPOINT2(190, "f69fdad7a15471b63a82668b618ee5b2a384291269d944b11974a723c1604124", "0x2856a3");
ADD_CHECKPOINT2(200, "eba53fa7006dfcdc837a56c0bc8f0e1883cf34861c26934d680252a6878a3f5d", "0x2aa022");
ADD_CHECKPOINT2(90000, "e125b5c1b26521f98e29df6ec88f041c176a2c0a3fcacd5bd0ad2278e9b02fd2", "0xc99801f937888"); // 3546475285149832
ADD_CHECKPOINT2(100000, "ff4e8ec805d5bfbcd01f350ac071be1d944ba73e0d27e37d12acb549902b3f3d", "0xDA97F5697F7D8"); // 3845539075979224
ADD_CHECKPOINT2(150000, "c43281eb5b2a41ee77a4465735e4820c6d14d473b568df7987541afc48f18568", "0x12BDA9ED687AAF"); // 5275087110961839
ADD_CHECKPOINT2(225000, "7648405f7cfb24341d9580275b518bb3713c68e970f547faa0b3bcae450d9ec2", "0x18CD5F1B7BA43A"); // 6981207807730746
ADD_CHECKPOINT2(300000, "a18ca65464c1f2d876dd3a00643c9be265655d6bca364eccc5e3d628b9a5cd2c", "0x1F0C2A50FE631C"); // 8739100165038876
ADD_CHECKPOINT2(375000, "07f0c907cc5cb44cef88e5899a411adddd4b0a4419210906e0583efdcafb499f", "0x240C7F9742F265"); // 10146841299710565
ADD_CHECKPOINT2(1, "b6b45052e7e182ebaeb14ab713db29ad979115e664d766aa0910e325564a27a6", "0x2");
ADD_CHECKPOINT2(10, "82724681cf6bd934eb3253d041de50206a77627ce40ffe418ce6e0fe392ec684", "0x7812a");
ADD_CHECKPOINT2(20, "4dac7b512d876df05bfa4f39b8dbacd75cb1483fbced8bfc5446ebe21b25a04f", "0xba98f");
ADD_CHECKPOINT2(30, "668246360c93ef791a59157cec9cd09722b32a966051feea399082433138f07b", "0xcc235");
ADD_CHECKPOINT2(40, "9a4183bc1d6e9828eac46505c5ef37ae5447ba6c9325dca02be9e1201f939a7d", "0xdf077");
ADD_CHECKPOINT2(50, "5cd8b089d2e77aed9b803b398c6bff07ca652100cb8fa114c91b72509aeeb7e9", "0xf37eb");
ADD_CHECKPOINT2(60, "0e1acf00dd38e0757996dcdc4b69ad54baf7ebe10ae1e8168b192acb1a0ed7f2", "0x10993b");
ADD_CHECKPOINT2(70, "988977507f388221a927e279307b548a0ae0de10ded8c4f22c315e1b483f921a", "0x121537");
ADD_CHECKPOINT2(80, "88ea1c49b20e7596e21ca8137b2a9fa98558df269a15816fe7d7495f1c63ea43", "0x13a290");
ADD_CHECKPOINT2(90, "254800bb6f9794aad95b2226ffc1a1eef0a817472e1877ae08fac6becb55b147", "0x153a55");
ADD_CHECKPOINT2(100, "ba8d75fad878af26ac2504b4868893a7f86c59f013d0f096925cf53271dd04e8", "0x16e91e");
ADD_CHECKPOINT2(110, "dca0779bfe403730b923fa0918645daeec6096b953be2c554f133460c6fcce35", "0x18acb9");
ADD_CHECKPOINT2(120, "5a57287f6b5c105ae264b88050731c5b9ad1313b916143d7585af1d345e70247", "0x1a88f5");
ADD_CHECKPOINT2(130, "4fd292ac0774461e968924f8097e78ec03eee43a2997deaddbc7993e470a61d6", "0x1c6edd");
ADD_CHECKPOINT2(140, "5a3b6ceeef5fd498ea3330acb8a0e87f2c1566c9b0100ad67237e5664d1f053b", "0x1e4991");
ADD_CHECKPOINT2(150, "78f26d08d39f7d5e1a3548277321471e16c95096fa9bcecbe8a420d406ee249b", "0x202406");
ADD_CHECKPOINT2(160, "7acaab1037ccfbadd3126d2612d5dc154020297f980df0b8df462f9c761d3326", "0x22154b");
ADD_CHECKPOINT2(170, "9541ae934e40fa6749ca3453e47cf5fdf38efbac9efcaa2714121e8a21dd2d24", "0x241ce7");
ADD_CHECKPOINT2(180, "e20bc8ac6aabb6b0792f23a29ce42a577c6a57d177a8ac1a51b68fb6de508045", "0x262b40");
ADD_CHECKPOINT2(190, "f69fdad7a15471b63a82668b618ee5b2a384291269d944b11974a723c1604124", "0x2856a3");
ADD_CHECKPOINT2(200, "eba53fa7006dfcdc837a56c0bc8f0e1883cf34861c26934d680252a6878a3f5d", "0x2aa022");
ADD_CHECKPOINT2(90000, "e125b5c1b26521f98e29df6ec88f041c176a2c0a3fcacd5bd0ad2278e9b02fd2", "0xc99801f937888"); // 3546475285149832
}
return true;
}
+7
View File
@@ -138,6 +138,13 @@ bool keys_match_internal_values(const std::unordered_map<KeyT, ValueT> &map, Pre
return true;
}
/// convenience wrapper for getting the last element after emplacing back
template <typename ContainerT>
typename ContainerT::value_type& add_element(ContainerT &container)
{
container.emplace_back();
return container.back();
}
/// convenience erasor for unordered maps: std::erase_if(std::unordered_map) is C++20
template <typename KeyT, typename ValueT, typename PredT>
void for_all_in_map_erase_if(std::unordered_map<KeyT, ValueT> &map_inout, PredT predicate)
-11
View File
@@ -1,11 +0,0 @@
#pragma once
#if defined(__x86_64__)
#define DEBUG_BREAK() asm volatile("int $3")
#elif defined(__aarch64__)
#define DEBUG_BREAK() asm volatile("brk #0xf000")
#elif defined(__arm__)
#define DEBUG_BREAK() asm volatile(".inst 0xe7f001f0") // Encoding for bkpt #0xf01, common for ARM32
#else
#error "Unsupported architecture for DEBUG_BREAK"
#endif
-1
View File
@@ -71,7 +71,6 @@ monero_add_library(cncrypto
target_link_libraries(cncrypto
PUBLIC
epee
mx25519_static
randomx
${Boost_SYSTEM_LIBRARY}
${SODIUM_LIBRARY}
+1 -4
View File
@@ -887,7 +887,4 @@ const ge_p3 ge_p3_H = {
{5858699, 5096796, 21321203, -7536921, -5553480, -11439507, -5627669, 15045946, 19977121, 5275251},
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{23443568, -5110398, -8776029, -4345135, 6889568, -14710814, 7474843, 3279062, 14550766, -7453428}
};
// Precomputed sqrt(-486664) mod p as 32-byte little-endian array
const fe fe_sqrt_m486664 = {12222970, 8312128, 11511410, -9067497, 15300785, 241793, -25456130, -14121551, 12187136, -3972024};
};
+2 -125
View File
@@ -104,21 +104,6 @@ void fe_1(fe h) {
h[9] = 0;
}
int fe_equal(const fe a, const fe b)
{
fe t;
fe_sub(t, a, b);
return fe_isnonzero(t) == 0;
}
void ge_from_xy(ge_p3 *out, const fe x, const fe y)
{
fe_1(out->Z); // Z = 1
fe_copy(out->X, x); // X = x
fe_copy(out->Y, y); // Y = y
fe_mul(out->T, x, y); // T = x*y
}
/* From fe_add.c */
/*
@@ -380,7 +365,7 @@ int fe_isnegative(const fe f) {
/* From fe_isnonzero.c, modified */
int fe_isnonzero(const fe f) {
static int fe_isnonzero(const fe f) {
unsigned char s[32];
fe_tobytes(s, f);
return (((int) (s[0] | s[1] | s[2] | s[3] | s[4] | s[5] | s[6] | s[7] | s[8] |
@@ -3982,114 +3967,6 @@ int edwards_bytes_to_x25519_vartime(unsigned char *xbytes, const unsigned char *
return 0;
}
// Precomputed sqrt(-1) from Monero (fe_sqrtm1 in crypto-ops-data.c)
extern const fe fe_sqrtm1;
extern const fe fe_sqrt_m486664;
// Function to recover v from u (returns 0 on success, -1 if not on curve)
int fe_sqrt_mont(fe v_out, const fe u_in) {
fe rhs;
fe t0, t1, t2;
fe candidate, c2, check;
// Compute rhs = u^3 + A u^2 + u, A=486662
fe A_fe;
fe_frombytes_vartime(A_fe, (const unsigned char[]){0x06, 0x6D, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}); // Correct little-endian 486662
fe_sq(t0, u_in); // t0 = u^2
fe_mul(t1, t0, u_in); // t1 = u^3
fe_mul(t2, t0, A_fe); // t2 = A u^2
fe_add(rhs, t1, t2); // u^3 + A u^2
fe_add(rhs, rhs, u_in); // + u
// The exponentiation chain for (p+3)/8
fe_1(t1);
fe_sq(t0, t1);
fe_mul(t0, t0, t1);
fe_sq(candidate, t0);
fe_mul(candidate, candidate, t1);
fe_mul(candidate, candidate, rhs);
fe_pow22523(candidate, candidate);
fe_mul(candidate, candidate, t0);
fe_mul(candidate, candidate, rhs);
// Check c^2 == rhs or -rhs
fe_sq(c2, candidate);
fe_sub(check, c2, rhs);
if (fe_isnonzero(check)) {
fe_add(check, c2, rhs);
if (fe_isnonzero(check)) {
return -1; // Not a quadratic residue
}
fe_mul(candidate, candidate, fe_sqrtm1); // Adjust with sqrt(-1)
}
// Output v (principal root; flip to -v if needed for your map)
fe_copy(v_out, candidate);
return 0;
}
void mont_to_ed(fe x_out, fe y_out, const fe u, const fe v) {
fe inv_v, temp;
fe t1, t2, inv_t2;
fe one;
fe_1(one);
fe_invert(inv_v, v); // 1/v
fe_mul(temp, u, inv_v); // u/v
fe_mul(x_out, fe_sqrt_m486664, temp); // sqrt(-486664) * (u/v)
fe_sub(t1, u, one); // u - 1
fe_add(t2, u, one); // u + 1
fe_invert(inv_t2, t2);
fe_mul(y_out, t1, inv_t2); // (u-1)/(u+1)
}
void ed_to_mont(fe u_out, fe v_out, const fe x, const fe y) {
fe t1, t2, inv_t2;
fe one;
fe_1(one);
fe_add(t1, one, y); // 1 + y
fe_sub(t2, one, y); // 1 - y
fe_invert(inv_t2, t2);
fe_mul(u_out, t1, inv_t2); // (1+y)/(1-y)
fe inv_x;
fe_invert(inv_x, x); // 1/x
fe_mul(t1, u_out, inv_x); // u / x
fe_mul(v_out, fe_sqrt_m486664, t1); // sqrt(-486664) * (u/x)
}
// Usage: Add two Montgomery points
void add_mont_points(fe u3, fe v3, const fe u1, const fe v1, const fe u2, const fe v2) {
ge_p3 P_ed, Q_ed, sum_ed;
// Convert to Edwards
fe x1, y1, x2, y2;
mont_to_ed(x1, y1, u1, v1);
mont_to_ed(x2, y2, u2, v2);
// Load into ge_p3 (assume Z=1, T=x*y for affine)
fe_1(P_ed.Z); fe_mul(P_ed.T, x1, y1); fe_copy(P_ed.X, x1); fe_copy(P_ed.Y, y1);
fe_1(Q_ed.Z); fe_mul(Q_ed.T, x2, y2); fe_copy(Q_ed.X, x2); fe_copy(Q_ed.Y, y2);
// Add using ge_
ge_cached Q_cached;
ge_p3_to_cached(&Q_cached, &Q_ed);
ge_p1p1 sum_p1p1;
ge_add(&sum_p1p1, &P_ed, &Q_cached);
ge_p1p1_to_p3(&sum_ed, &sum_p1p1);
// Convert back (normalize to affine: divide by Z)
fe inv_z;
fe_invert(inv_z, sum_ed.Z);
fe x_out, y_out;
fe_mul(x_out, sum_ed.X, inv_z);
fe_mul(y_out, sum_ed.Y, inv_z);
ed_to_mont(u3, v3, x_out, y_out);
}
int ge_p3_is_point_at_infinity_vartime(const ge_p3 *p) {
// https://eprint.iacr.org/2008/522
// X == T == 0 and Y/Z == 1
@@ -4186,4 +4063,4 @@ void fe_dbl(fe h, const fe f)
// Reduce the output for safety to ensure the result can be used as input to
// fe_add or fe_sub without an extra call to fe_reduce
fe_reduce(h, h_res);
}
}
+1 -10
View File
@@ -176,11 +176,6 @@ int sc_isnonzero(const unsigned char *); /* Doesn't normalize */
void ge_p3_to_x25519(unsigned char *xbytes, const ge_p3 *h);
int edwards_bytes_to_x25519_vartime(unsigned char *xbytes, const unsigned char *s);
int fe_sqrt_mont(fe v_out, const fe u_in);
void mont_to_ed(fe x_out, fe y_out, const fe u, const fe v);
void ed_to_mont(fe u_out, fe v_out, const fe x, const fe y);
void add_mont_points(fe u3, fe v3, const fe u1, const fe v1, const fe u2, const fe v2);
// internal
uint64_t load_3(const unsigned char *in);
uint64_t load_4(const unsigned char *in);
@@ -197,14 +192,10 @@ void fe_sq(fe h, const fe f);
void fe_sub(fe h, const fe f, const fe g);
void fe_0(fe h);
void fe_1(fe h);
int fe_equal(const fe a, const fe b);
void ge_from_xy(ge_p3 *out, const fe x, const fe y);
int fe_isnonzero(const fe f);
int ge_p3_is_point_at_infinity_vartime(const ge_p3 *p);
void fe_ed_y_derivatives_to_wei_x(unsigned char *wei_x, const fe inv_one_minus_y, const fe one_plus_y);
void fe_reduce(fe reduced_f, const fe f);
void fe_dbl(fe h, const fe f);
void fe_dbl(fe h, const fe f);
+1 -558
View File
@@ -41,7 +41,6 @@
#include "common/varint.h"
#include "warnings.h"
#include "crypto.h"
#include "mx25519.h"
#include "hash.h"
#include "cryptonote_config.h"
@@ -91,16 +90,6 @@ namespace crypto {
return &reinterpret_cast<const unsigned char &>(scalar);
}
static const mx25519_impl* get_mx25519_impl()
{
static std::once_flag of;
static const mx25519_impl *impl;
std::call_once(of, [&](){ impl = mx25519_select_impl(MX25519_TYPE_AUTO); });
if (impl == nullptr)
throw std::runtime_error("failed to obtain a mx25519 implementation");
return impl;
}
boost::mutex &get_random_lock()
{
static boost::mutex random_lock;
@@ -515,391 +504,6 @@ namespace crypto {
memwipe(&k, sizeof(k));
}
void crypto_ops::generate_carrot_tx_proof(
const hash &prefix_hash,
const public_key &R, // X25519 u-coordinate
const public_key &A, // Ed25519
const boost::optional<public_key> &B, // Ed if present
const public_key &D, // X25519 u-coordinate
const secret_key &r,
const secret_key &a,
signature &sig)
{
// Check if we are sender or receiver
if (r != crypto::null_skey) {
// SENDER
generate_carrot_tx_proof_as_sender(prefix_hash, R, A, B, D, r, a, sig);
return;
}
// RECEIVER
// Load points (A and B and R) into ge_p3
ge_p3 A_p3;
ge_p3 B_p3;
ge_p3 R_p3;
if (ge_frombytes_vartime(&A_p3, &A) != 0)
throw std::runtime_error("recipient view pubkey is invalid");
if (B && ge_frombytes_vartime(&B_p3, &*B) != 0)
throw std::runtime_error("recipient spend pubkey is invalid");
#if !defined(NDEBUG)
{
// Debug check D == a*R
mx25519_pubkey D_x25519;
mx25519_scmul_key(get_mx25519_impl(),
&D_x25519,
reinterpret_cast<const mx25519_privkey*>(&a),
reinterpret_cast<const mx25519_pubkey*>(&R));
public_key dbg_D;
memcpy(&dbg_D, &D_x25519, sizeof(mx25519_pubkey));
assert(D == dbg_D);
}
#endif
//
// 1. Pick random nonce k
//
crypto::secret_key k;
random_scalar(k);
static const public_key zero = {{
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
}};
s_comm_2 buf;
buf.msg = prefix_hash;
buf.D = D; // X25519 u-coord
buf.R = R; // X25519 u-coord
buf.A = A; // Ed25519
buf.B = B ? *B : zero;
cn_fast_hash(config::HASH_KEY_TXPROOF_V2,
sizeof(config::HASH_KEY_TXPROOF_V2)-1,
buf.sep);
//
// 2. Compute X = ConvertPointE(k*G or k*B)
//
ge_p3 kB_or_kG_p3;
if (B)
ge_scalarmult_p3(&kB_or_kG_p3, &k, &B_p3);
else
ge_scalarmult_base(&kB_or_kG_p3, &k);
mx25519_pubkey X_x25519;
ge_p3_to_x25519(X_x25519.data, &kB_or_kG_p3);
memcpy(&buf.X, &X_x25519, sizeof(mx25519_pubkey));
//
// 3. Compute Y = k*R
//
mx25519_pubkey Y;
mx25519_scmul_key(get_mx25519_impl(),
&Y,
reinterpret_cast<const mx25519_privkey*>(&k),
reinterpret_cast<const mx25519_pubkey*>(&R));
memcpy(&buf.Y, &Y, sizeof(mx25519_pubkey));
// ---------- Extract and lift R ----------
fe u_R;
fe_frombytes_vartime(u_R, (const unsigned char *)&R);
fe v_R_cand;
if (fe_sqrt_mont(v_R_cand, u_R) != 0)
throw std::runtime_error("R not on curve");
fe x1, y1, x2, y2, v_R_neg;
ge_p3 R_ed1, R_ed2;
// +v (principal)
mont_to_ed(x1, y1, u_R, v_R_cand);
ge_from_xy(&R_ed1, x1, y1);
// -v
fe_neg(v_R_neg, v_R_cand);
mont_to_ed(x2, y2, u_R, v_R_neg);
ge_from_xy(&R_ed2, x2, y2);
// Arbitrarily choose R_sign = true (principal v from fe_sqrt_mont)
bool R_sign = true;
ge_p3 R_ed_correct = R_ed1; // +v
// ---------- Extract and lift D (consistent with chosen R_sign) ----------
fe u_D;
fe_frombytes_vartime(u_D, (const unsigned char *)&D);
fe v_D_cand;
if (fe_sqrt_mont(v_D_cand, u_D) != 0)
throw std::runtime_error("D not on curve");
fe x3, y3, x4, y4, v_D_neg;
// Compute D_ed_true = a * R_ed_correct
ge_p3 D_ed_true;
ge_scalarmult_p3(&D_ed_true, &a, &R_ed_correct);
// Normalize to affine for matching
fe inv_z;
fe_invert(inv_z, D_ed_true.Z);
fe xd_true, yd_true;
fe_mul(xd_true, D_ed_true.X, inv_z);
fe_mul(yd_true, D_ed_true.Y, inv_z);
// +v for D
mont_to_ed(x3, y3, u_D, v_D_cand);
bool D_match1 = fe_equal(x3, xd_true) && fe_equal(y3, yd_true); // Affine match (mont_to_ed gives affine x,y)
// -v for D
fe_neg(v_D_neg, v_D_cand);
mont_to_ed(x4, y4, u_D, v_D_neg);
bool D_match2 = fe_equal(x4, xd_true) && fe_equal(y4, yd_true);
bool D_sign = false;
if (D_match1)
D_sign = true;
else if (D_match2)
D_sign = false;
else
throw std::runtime_error("D lift mismatch with computed D_ed_true");
// Pack signs (MSB is set to [1] for outbound, [0] for inbound
sig.sign_mask =
(R_sign ? 0x01 : 0x00) |
(D_sign ? 0x02 : 0x00);
struct {
s_comm_2 buf;
uint8_t sign_mask;
} challenge_hash;
challenge_hash.buf = buf;
challenge_hash.sign_mask = sig.sign_mask;
//
// 7. Compute challenge c = H(prefix_hash || … || sign_mask)
//
hash_to_scalar(&challenge_hash, sizeof(challenge_hash), sig.c);
//
// 8. Compute response z = k - c*a
//
sc_mulsub(&sig.r, &sig.c, &unwrap(a), &k);
memwipe(&k, sizeof(k));
#if !defined(NDEBUG)
bool ok = check_carrot_tx_proof(prefix_hash, R, A, B, D, sig);
assert(ok);
#endif
}
void crypto_ops::generate_carrot_tx_proof_as_sender(
const hash &prefix_hash,
const public_key &R, // X25519 u-coordinate
const public_key &A, // Ed25519
const boost::optional<public_key> &B, // Ed if present
const public_key &D, // X25519 u-coordinate
const secret_key &r,
const secret_key &a,
signature &sig)
{
// Load only Ed points (A and B) into ge_p3
ge_p3 A_p3;
ge_p3 B_p3;
if (ge_frombytes_vartime(&A_p3, &A) != 0)
throw std::runtime_error("recipient view pubkey is invalid");
if (B && ge_frombytes_vartime(&B_p3, &*B) != 0)
throw std::runtime_error("recipient spend pubkey is invalid");
#if !defined(NDEBUG)
{
assert(sc_check(&r) == 0);
// Debug check R == ConvertPointE(r*G or r*B)
public_key dbg_R;
ge_p3 dbg_R_p3;
if (B)
ge_scalarmult_p3(&dbg_R_p3, &r, &B_p3);
else
ge_scalarmult_base(&dbg_R_p3, &r);
mx25519_pubkey R_x25519;
ge_p3_to_x25519(R_x25519.data, &dbg_R_p3);
memcpy(&dbg_R, &R_x25519, sizeof(mx25519_pubkey));
assert(R == dbg_R);
// Debug check D == ConvertPointE(r*A)
public_key dbg_D;
ge_p3 dbg_D_p3;
ge_scalarmult_p3(&dbg_D_p3, &r, &A_p3);
mx25519_pubkey D_x25519;
ge_p3_to_x25519(D_x25519.data, &dbg_D_p3);
memcpy(&dbg_D, &D_x25519, sizeof(mx25519_pubkey));
assert(D == dbg_D);
}
#endif
//
// 1. Pick random nonce k
//
ec_scalar k;
random_scalar(k);
static const ec_point zero = {{
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
}};
s_comm_2 buf;
buf.msg = prefix_hash;
buf.D = D; // X25519 u-coord
buf.R = R; // X25519 u-coord
buf.A = A; // Ed25519
buf.B = B ? *B : zero;
cn_fast_hash(config::HASH_KEY_TXPROOF_V2,
sizeof(config::HASH_KEY_TXPROOF_V2)-1,
buf.sep);
//
// 2. Compute X = ConvertPointE(k*G or k*B)
//
ge_p3 kB_or_kG_p3;
if (B)
ge_scalarmult_p3(&kB_or_kG_p3, &k, &B_p3);
else
ge_scalarmult_base(&kB_or_kG_p3, &k);
mx25519_pubkey X_x25519;
ge_p3_to_x25519(X_x25519.data, &kB_or_kG_p3);
memcpy(&buf.X, &X_x25519, sizeof(mx25519_pubkey));
//
// 3. Compute Y = ConvertPointE(k*A)
//
ge_p3 kA_p3;
ge_scalarmult_p3(&kA_p3, &k, &A_p3);
mx25519_pubkey Y_x25519;
ge_p3_to_x25519(Y_x25519.data, &kA_p3);
memcpy(&buf.Y, &Y_x25519, sizeof(mx25519_pubkey));
//
// 4. Compute true Ed points R_ed_true and D_ed_true
//
ge_p3 R_ed_true, D_ed_true;
if (B)
ge_scalarmult_p3(&R_ed_true, &r, &B_p3);
else
ge_scalarmult_base(&R_ed_true, &r);
ge_scalarmult_p3(&D_ed_true, &r, &A_p3);
//
// 5. Determine sign bits for R and D
//
// ---------- Extract and lift R ----------
fe u_R;
fe_frombytes_vartime(u_R, (const unsigned char *)&R);
fe v_R_cand;
if (fe_sqrt_mont(v_R_cand, u_R) != 0)
throw std::runtime_error("R not on curve");
fe x1, y1, x2, y2, v_R_neg, v_D_neg;
mont_to_ed(x1, y1, u_R, v_R_cand);
fe_neg(v_R_neg, v_R_cand);
mont_to_ed(x2, y2, u_R, v_R_neg);
// Compute affine Edwards coords of R_ed_true
fe inv_z, xr_true, yr_true;
fe_invert(inv_z, R_ed_true.Z);
fe_mul(xr_true, R_ed_true.X, inv_z);
fe_mul(yr_true, R_ed_true.Y, inv_z);
bool R_match1 = fe_equal(xr_true, x1) && fe_equal(yr_true, y1);
bool R_match2 = fe_equal(xr_true, x2) && fe_equal(yr_true, y2);
if (!R_match1 && !R_match2)
throw std::runtime_error("R mapping mismatch");
bool R_sign = R_match1;
// ---------- Extract and lift D ----------
fe u_D;
fe_frombytes_vartime(u_D, (const unsigned char *)&D);
fe v_D_cand;
if (fe_sqrt_mont(v_D_cand, u_D) != 0)
throw std::runtime_error("D not on curve");
mont_to_ed(x1, y1, u_D, v_D_cand);
fe_neg(v_D_neg, v_D_cand);
mont_to_ed(x2, y2, u_D, v_D_neg);
fe_invert(inv_z, D_ed_true.Z);
fe_mul(xr_true, D_ed_true.X, inv_z);
fe_mul(yr_true, D_ed_true.Y, inv_z);
bool D_match1 = fe_equal(xr_true, x1) && fe_equal(yr_true, y1);
bool D_match2 = fe_equal(xr_true, x2) && fe_equal(yr_true, y2);
if (!D_match1 && !D_match2)
throw std::runtime_error("D mapping mismatch");
bool D_sign = D_match1;
//
// 6. Pack sign bits into signature, include in challenge hash
//
sig.sign_mask =
(R_sign ? 0x01 : 0x00) |
(D_sign ? 0x02 : 0x00) |
0x80;
struct {
s_comm_2 buf;
uint8_t sign_mask;
} challenge_hash;
challenge_hash.buf = buf;
challenge_hash.sign_mask = sig.sign_mask;
//
// 7. Compute challenge c = H(prefix_hash || … || sign_mask)
//
hash_to_scalar(&challenge_hash, sizeof(challenge_hash), sig.c);
//
// 8. Compute response z = k - c*r
//
sc_mulsub(&sig.r, &sig.c, &unwrap(r), &k);
memwipe(&k, sizeof(k));
#if !defined(NDEBUG)
bool ok = check_carrot_tx_proof(prefix_hash, R, A, B, D, sig);
assert(ok);
#endif
}
// Verify a proof: either v1 (version == 1) or v2 (version == 2)
bool crypto_ops::check_tx_proof(const hash &prefix_hash, const public_key &R, const public_key &A, const boost::optional<public_key> &B, const public_key &D, const signature &sig, const int version) {
// sanity check
@@ -1004,167 +608,6 @@ namespace crypto {
return sc_isnonzero(&c2) == 0;
}
// R and D are provided in X25519 format (u-coordinate), A and B in Ed25519.
bool crypto_ops::check_carrot_tx_proof(
const hash &prefix_hash,
const public_key &R, // X25519 u
const public_key &A, // Ed25519 viewkey
const boost::optional<public_key> &B, // Ed25519 spendkey if any
const public_key &D, // X25519 u
const signature &sig)
{
ge_p3 A_p3, B_p3;
if (ge_frombytes_vartime(&A_p3, &A) != 0)
return false;
if (B && ge_frombytes_vartime(&B_p3, &*B) != 0)
return false;
if (sc_check(&sig.c) != 0 || sc_check(&sig.r) != 0)
return false;
// Extract sign bits and direction flag
const bool R_sign = (sig.sign_mask & 0x01) != 0;
const bool D_sign = (sig.sign_mask & 0x02) != 0;
const bool outbound = (sig.sign_mask & 0x80) != 0;
//
// 1. Reconstruct R_ed and D_ed from X25519 u-coords + sign bits
//
// ----- R -----
fe u_R, v_R_candidate, v_R;
fe_frombytes_vartime(u_R, (const unsigned char *)&R);
if (fe_sqrt_mont(v_R_candidate, u_R) != 0)
return false;
if (R_sign) fe_copy(v_R, v_R_candidate);
else fe_neg(v_R, v_R_candidate);
fe x_R, y_R;
mont_to_ed(x_R, y_R, u_R, v_R);
ge_p3 R_ed;
ge_from_xy(&R_ed, x_R, y_R); // Z=1, T=X*Y
// ----- D -----
fe u_D, v_D_candidate, v_D;
fe_frombytes_vartime(u_D, (const unsigned char *)&D);
if (fe_sqrt_mont(v_D_candidate, u_D) != 0)
return false;
if (D_sign) fe_copy(v_D, v_D_candidate);
else fe_neg(v_D, v_D_candidate);
fe x_D, y_D;
mont_to_ed(x_D, y_D, u_D, v_D);
ge_p3 D_ed;
ge_from_xy(&D_ed, x_D, y_D);
//
// 2. Compute X'
// If inbound proof, X`= z*G + c*A (or z*B + c*A)
// If outbound proof, X`= z*G + c*R_ed (or z*B + c*R_ed)
//
ge_p3 c_p3;
if (outbound)
ge_scalarmult_p3(&c_p3, &sig.c, &R_ed);
else
ge_scalarmult_p3(&c_p3, &sig.c, &A_p3);
ge_p1p1 X_p1p1;
if (B)
{
// Subaddress: X' = c*A + z*B
ge_p3 rB_p3;
ge_scalarmult_p3(&rB_p3, &sig.r, &B_p3);
ge_cached rB_cached;
ge_p3_to_cached(&rB_cached, &rB_p3);
ge_add(&X_p1p1, &c_p3, &rB_cached);
}
else
{
// Main address: X' = c*R_ed + z*G
ge_p3 rG_p3;
ge_scalarmult_base(&rG_p3, &sig.r);
ge_cached rG_cached;
ge_p3_to_cached(&rG_cached, &rG_p3);
ge_add(&X_p1p1, &c_p3, &rG_cached);
}
ge_p3 X_ed_p3;
ge_p1p1_to_p3(&X_ed_p3, &X_p1p1);
mx25519_pubkey X_x25519;
ge_p3_to_x25519(X_x25519.data, &X_ed_p3);
//
// 3. Compute Y'
// If inbound, Y' = c*D_ed + z*R
// If outbound, Y' = c*D_ed + z*A
//
ge_p3 cD_p3;
ge_scalarmult_p3(&cD_p3, &sig.c, &D_ed);
ge_p3 z_p3;
if (outbound)
ge_scalarmult_p3(&z_p3, &sig.r, &A_p3);
else
ge_scalarmult_p3(&z_p3, &sig.r, &R_ed);
ge_cached z_cached;
ge_p3_to_cached(&z_cached, &z_p3);
ge_p1p1 Y_p1p1;
ge_add(&Y_p1p1, &cD_p3, &z_cached);
ge_p3 Y_ed_p3;
ge_p1p1_to_p3(&Y_ed_p3, &Y_p1p1);
mx25519_pubkey Y_x25519;
ge_p3_to_x25519(Y_x25519.data, &Y_ed_p3);
//
// 4. Rebuild the hash transcript exactly as the prover did
//
static const ec_point zero = {{
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
}};
s_comm_2 buf;
buf.msg = prefix_hash;
buf.D = D; // X25519 (same bytes as prover)
buf.R = R; // X25519
buf.A = A; // Ed25519
buf.B = B ? *B : zero;
cn_fast_hash(config::HASH_KEY_TXPROOF_V2,
sizeof(config::HASH_KEY_TXPROOF_V2)-1,
buf.sep);
memcpy(&buf.X, &X_x25519, sizeof(mx25519_pubkey));
memcpy(&buf.Y, &Y_x25519, sizeof(mx25519_pubkey));
struct {
s_comm_2 buf;
uint8_t sign_mask;
} challenge_hash;
challenge_hash.buf = buf;
challenge_hash.sign_mask = sig.sign_mask;
//
// 5. Recompute challenge and compare with sig.c
//
ec_scalar c2;
hash_to_scalar(&challenge_hash, sizeof(challenge_hash), c2);
sc_sub(&c2, &c2, &sig.c);
return sc_isnonzero(&c2) == 0;
}
static void hash_to_ec(const public_key &key, ge_p3 &res) {
hash h;
ge_p2 point;
@@ -1353,4 +796,4 @@ POP_WARNINGS
ki.data[31] ^= 0x80;
}
}
}
}
+3 -28
View File
@@ -85,7 +85,6 @@ namespace crypto {
POD_CLASS signature {
ec_scalar c, r;
uint8_t sign_mask;
friend class crypto_ops;
};
@@ -100,7 +99,7 @@ namespace crypto {
static_assert(sizeof(ec_point) == 32 && sizeof(ec_scalar) == 32 &&
sizeof(public_key) == 32 && sizeof(public_key_memsafe) == 32 && sizeof(secret_key) == 32 &&
sizeof(key_derivation) == 32 && sizeof(key_image) == 32 && sizeof(key_image_y) == 32 &&
sizeof(signature) == 65 && sizeof(view_tag) == 1, "Invalid structure size");
sizeof(signature) == 64 && sizeof(view_tag) == 1, "Invalid structure size");
class crypto_ops {
crypto_ops();
@@ -132,14 +131,8 @@ namespace crypto {
friend void generate_tx_proof(const hash &, const public_key &, const public_key &, const boost::optional<public_key> &, const public_key &, const secret_key &, signature &);
static void generate_tx_proof_v1(const hash &, const public_key &, const public_key &, const boost::optional<public_key> &, const public_key &, const secret_key &, signature &);
friend void generate_tx_proof_v1(const hash &, const public_key &, const public_key &, const boost::optional<public_key> &, const public_key &, const secret_key &, signature &);
static void generate_carrot_tx_proof(const hash &, const public_key &, const public_key &, const boost::optional<public_key> &, const public_key &, const secret_key &, const secret_key &, signature &);
friend void generate_carrot_tx_proof(const hash &, const public_key &, const public_key &, const boost::optional<public_key> &, const public_key &, const secret_key &, const secret_key &, signature &);
static void generate_carrot_tx_proof_as_sender(const hash &, const public_key &, const public_key &, const boost::optional<public_key> &, const public_key &, const secret_key &, const secret_key &, signature &);
friend void generate_carrot_tx_proof_as_sender(const hash &, const public_key &, const public_key &, const boost::optional<public_key> &, const public_key &, const secret_key &, const secret_key &, signature &);
static bool check_tx_proof(const hash &, const public_key &, const public_key &, const boost::optional<public_key> &, const public_key &, const signature &, const int);
friend bool check_tx_proof(const hash &, const public_key &, const public_key &, const boost::optional<public_key> &, const public_key &, const signature &, const int);
static bool check_carrot_tx_proof(const hash &, const public_key &, const public_key &, const boost::optional<public_key> &, const public_key &, const signature &);
friend bool check_carrot_tx_proof(const hash &, const public_key &, const public_key &, const boost::optional<public_key> &, const public_key &, const signature &);
static void derive_key_image_generator(const public_key &, ec_point &);
friend void derive_key_image_generator(const public_key &, ec_point &);
static void generate_key_image(const public_key &, const secret_key &, key_image &);
@@ -267,28 +260,10 @@ namespace crypto {
inline void generate_tx_proof_v1(const hash &prefix_hash, const public_key &R, const public_key &A, const boost::optional<public_key> &B, const public_key &D, const secret_key &r, signature &sig) {
crypto_ops::generate_tx_proof_v1(prefix_hash, R, A, B, D, r, sig);
}
/* Generation of a carrot tx proof; for carrot transactions, D is in X25519 domain (D = r*ConvertPointE(A))
* instead of Ed25519 domain (D = r*A). This version applies ConvertPointE transformation.
*/
inline void generate_carrot_tx_proof(const hash &prefix_hash, const public_key &R, const public_key &A, const boost::optional<public_key> &B, const public_key &D, const secret_key &r, const secret_key &a, signature &sig) {
crypto_ops::generate_carrot_tx_proof(prefix_hash, R, A, B, D, r, a, sig);
}
inline void generate_carrot_tx_proof_as_sender(const hash &prefix_hash, const public_key &R, const public_key &A, const boost::optional<public_key> &B, const public_key &D, const secret_key &r, const secret_key &a, signature &sig) {
crypto_ops::generate_carrot_tx_proof_as_sender(prefix_hash, R, A, B, D, r, a, sig);
}
inline bool check_tx_proof(const hash &prefix_hash, const public_key &R, const public_key &A, const boost::optional<public_key> &B, const public_key &D, const signature &sig, const int version) {
return crypto_ops::check_tx_proof(prefix_hash, R, A, B, D, sig, version);
}
/* Verification of a carrot tx proof; R and D should be in Ed25519 domain for verification,
*/
inline bool check_carrot_tx_proof(const hash &prefix_hash, const public_key &R, const public_key &A, const boost::optional<public_key> &B, const public_key &D, const signature &sig) {
return crypto_ops::check_carrot_tx_proof(prefix_hash, R, A, B, D, sig);
}
/*
inline bool check_carrot_tx_proof_as_sender(const hash &prefix_hash, const public_key &R, const public_key &A, const boost::optional<public_key> &B, const public_key &D, const signature &sig) {
return crypto_ops::check_carrot_tx_proof_as_sender(prefix_hash, R, A, B, D, sig);
}
*/
inline void derive_key_image_generator(const public_key &pub, ec_point &ki_gen) {
crypto_ops::derive_key_image_generator(pub, ki_gen);
}
@@ -403,4 +378,4 @@ CRYPTO_MAKE_HASHABLE_CONSTANT_TIME(public_key_memsafe)
CRYPTO_MAKE_HASHABLE(key_image)
CRYPTO_MAKE_HASHABLE(key_image_y)
CRYPTO_MAKE_COMPARABLE(signature)
CRYPTO_MAKE_COMPARABLE(view_tag)
CRYPTO_MAKE_COMPARABLE(view_tag)
+5 -29
View File
@@ -89,24 +89,12 @@ DISABLE_VS_WARNINGS(4244 4345)
void account_keys::xor_with_key_stream(const crypto::chacha_key &key)
{
// encrypt a large enough byte stream with chacha20
epee::wipeable_string key_stream = get_key_stream(key, m_encryption_iv, sizeof(crypto::secret_key) * (8 + m_multisig_keys.size()));
epee::wipeable_string key_stream = get_key_stream(key, m_encryption_iv, sizeof(crypto::secret_key) * (2 + m_multisig_keys.size()));
const char *ptr = key_stream.data();
for (size_t i = 0; i < sizeof(crypto::secret_key); ++i)
m_spend_secret_key.data[i] ^= *ptr++;
for (size_t i = 0; i < sizeof(crypto::secret_key); ++i)
m_view_secret_key.data[i] ^= *ptr++;
for (size_t i = 0; i < sizeof(crypto::secret_key); ++i)
s_master.data[i] ^= *ptr++;
for (size_t i = 0; i < sizeof(crypto::secret_key); ++i)
k_prove_spend.data[i] ^= *ptr++;
for (size_t i = 0; i < sizeof(crypto::secret_key); ++i)
s_view_balance.data[i] ^= *ptr++;
for (size_t i = 0; i < sizeof(crypto::secret_key); ++i)
k_view_incoming.data[i] ^= *ptr++;
for (size_t i = 0; i < sizeof(crypto::secret_key); ++i)
k_generate_image.data[i] ^= *ptr++;
for (size_t i = 0; i < sizeof(crypto::secret_key); ++i)
s_generate_address.data[i] ^= *ptr++;
for (crypto::secret_key &k: m_multisig_keys)
{
for (size_t i = 0; i < sizeof(crypto::secret_key); ++i)
@@ -128,20 +116,11 @@ DISABLE_VS_WARNINGS(4244 4345)
void account_keys::encrypt_viewkey(const crypto::chacha_key &key)
{
// encrypt a large enough byte stream with chacha20
epee::wipeable_string key_stream = get_key_stream(key, m_encryption_iv, sizeof(crypto::secret_key) * 8);
epee::wipeable_string key_stream = get_key_stream(key, m_encryption_iv, sizeof(crypto::secret_key) * 2);
const char *ptr = key_stream.data();
ptr += sizeof(crypto::secret_key); // Skip m_spend_secret_key
ptr += sizeof(crypto::secret_key);
for (size_t i = 0; i < sizeof(crypto::secret_key); ++i)
m_view_secret_key.data[i] ^= *ptr++;
ptr += (2 * sizeof(crypto::secret_key)); // Skip s_master, k_prove_spend
for (size_t i = 0; i < sizeof(crypto::secret_key); ++i)
s_view_balance.data[i] ^= *ptr++;
for (size_t i = 0; i < sizeof(crypto::secret_key); ++i)
k_view_incoming.data[i] ^= *ptr++;
for (size_t i = 0; i < sizeof(crypto::secret_key); ++i)
k_generate_image.data[i] ^= *ptr++;
for (size_t i = 0; i < sizeof(crypto::secret_key); ++i)
s_generate_address.data[i] ^= *ptr++;
}
//-----------------------------------------------------------------
void account_keys::decrypt_viewkey(const crypto::chacha_key &key)
@@ -172,8 +151,6 @@ DISABLE_VS_WARNINGS(4244 4345)
void account_base::forget_spend_key()
{
m_keys.m_spend_secret_key = crypto::secret_key();
m_keys.s_master = m_keys.m_spend_secret_key;
m_keys.k_prove_spend = m_keys.m_spend_secret_key;
m_keys.m_multisig_keys.clear();
}
//-----------------------------------------------------------------
@@ -186,7 +163,6 @@ DISABLE_VS_WARNINGS(4244 4345)
"Unexpected derived public spend key");
m_keys.m_spend_secret_key = spend_secret_key;
m_keys.s_master = m_keys.m_spend_secret_key;
}
//-----------------------------------------------------------------
crypto::secret_key account_base::generate(const crypto::secret_key& recovery_key, bool recover, bool two_random)
@@ -304,9 +280,9 @@ DISABLE_VS_WARNINGS(4244 4345)
std::string account_base::get_carrot_public_address_str(network_type nettype) const
{
// Build the cryptonote::account_public_address
account_public_address addr{m_keys.m_carrot_main_address.m_spend_public_key, m_keys.m_carrot_main_address.m_view_public_key, true};
account_public_address addr{m_keys.m_carrot_main_address.m_spend_public_key, m_keys.m_carrot_main_address.m_view_public_key};
// change this code into base 58
return get_account_address_as_str(nettype, false, addr);
return get_account_address_as_str(nettype, false, addr, true);
}
//-----------------------------------------------------------------
std::string account_base::get_public_integrated_address_str(const crypto::hash8 &payment_id, network_type nettype) const
-5
View File
@@ -75,11 +75,6 @@ namespace cryptonote
KV_SERIALIZE_CONTAINER_POD_AS_BLOB(m_multisig_keys)
const crypto::chacha_iv default_iv{{0, 0, 0, 0, 0, 0, 0, 0}};
KV_SERIALIZE_VAL_POD_AS_BLOB_OPT(m_encryption_iv, default_iv)
if (m_account_address.m_spend_public_key == crypto::null_pkey) {
KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE(s_view_balance)
KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE(k_view_incoming)
KV_SERIALIZE(m_carrot_account_address)
}
END_KV_SERIALIZE_MAP()
void encrypt(const crypto::chacha_key &key);
+3 -241
View File
@@ -44,7 +44,6 @@
#include "serialization/debug_archive.h"
#include "serialization/crypto.h"
#include "serialization/keyvalue_serialization.h" // eepe named serialization
#include "serialization/pair.h"
#include "serialization/string.h"
#include "carrot_core/core_types.h"
#include "carrot_impl/carrot_chain_serialization.h"
@@ -194,116 +193,8 @@ namespace cryptonote
VARINT_FIELD(amount)
FIELD(target)
END_SERIALIZE()
};
class protocol_tx_data_t {
public:
uint8_t version;
crypto::public_key return_address;
crypto::public_key return_pubkey;
carrot::view_tag_t return_view_tag;
carrot::encrypted_janus_anchor_t return_anchor_enc;
BEGIN_SERIALIZE_OBJECT()
VARINT_FIELD(version)
FIELD(return_address)
FIELD(return_pubkey)
FIELD(return_view_tag)
FIELD(return_anchor_enc)
END_SERIALIZE()
};
struct erc_token_t
{
uint8_t version;
std::string contract_address;
std::string lockbox_address;
std::string ticker;
uint64_t erc20_asset_id; // NOTE: this is NOT the Salvium `asset_type_id`!!!
BEGIN_SERIALIZE_OBJECT()
VARINT_FIELD(version)
FIELD(contract_address)
FIELD(lockbox_address)
FIELD(ticker)
VARINT_FIELD(erc20_asset_id)
END_SERIALIZE()
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(contract_address)
KV_SERIALIZE(lockbox_address)
KV_SERIALIZE(ticker)
KV_SERIALIZE(erc20_asset_id)
END_KV_SERIALIZE_MAP()
};
struct sal_token_t
{
uint8_t version;
uint64_t supply;
uint64_t size;
std::string name;
std::string url;
crypto::hash signature;
BEGIN_SERIALIZE_OBJECT()
VARINT_FIELD(version)
VARINT_FIELD(supply)
VARINT_FIELD(size)
FIELD(name)
FIELD(url)
FIELD(signature)
END_SERIALIZE()
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(supply)
KV_SERIALIZE(size)
KV_SERIALIZE(name)
KV_SERIALIZE(url)
END_KV_SERIALIZE_MAP()
};
#define TOKEN_TYPE_UNSET 0
#define TOKEN_TYPE_ERC20 1
#define TOKEN_TYPE_SAL 2
typedef boost::variant<erc_token_t, sal_token_t> token_v;
struct token_metadata_t
{
uint8_t version;
std::string asset_type;
token_v token;
BEGIN_SERIALIZE_OBJECT()
VARINT_FIELD(version)
FIELD(asset_type)
FIELD(token)
END_SERIALIZE()
};
class layer2_rollup_tx_t {
public:
crypto::hash tx_prefix_hash;
crypto::key_image first_key_image;
uint64_t tx_fee;
BEGIN_SERIALIZE_OBJECT()
FIELD(tx_prefix_hash)
FIELD(first_key_image)
VARINT_FIELD(tx_fee)
END_SERIALIZE()
};
class layer2_rollup_data_t {
public:
uint8_t version;
std::vector<layer2_rollup_tx_t> txs;
BEGIN_SERIALIZE_OBJECT()
VARINT_FIELD(version)
FIELD(txs)
END_SERIALIZE()
};
class transaction_prefix
@@ -336,12 +227,6 @@ namespace cryptonote
// Slippage limit
uint64_t amount_slippage_limit;
protocol_tx_data_t protocol_tx_data;
carrot::rollup_binding_tag_t rollup_binding_tag;
token_metadata_t token_metadata;
layer2_rollup_data_t layer2_rollup_data;
BEGIN_SERIALIZE()
VARINT_FIELD(version)
if(version == 0 || CURRENT_TRANSACTION_VERSION < version) return false;
@@ -359,30 +244,14 @@ namespace cryptonote
FIELD(return_address_list)
FIELD(return_address_change_mask)
} else {
if ((type == cryptonote::transaction_type::STAKE || type == cryptonote::transaction_type::CREATE_TOKEN) &&
(version >= TRANSACTION_VERSION_CARROT)) {
FIELD(protocol_tx_data)
} else {
FIELD(return_address)
FIELD(return_pubkey)
}
FIELD(return_address)
FIELD(return_pubkey)
}
FIELD(source_asset_type)
FIELD(destination_asset_type)
VARINT_FIELD(amount_slippage_limit)
}
}
if (version < TRANSACTION_VERSION_ENABLE_TOKENS) {
return true;
}
if (type == cryptonote::transaction_type::CREATE_TOKEN) {
FIELD(token_metadata)
} else if (type == cryptonote::transaction_type::TRANSFER) {
FIELD(rollup_binding_tag)
} else if (type == cryptonote::transaction_type::ROLLUP) {
FIELD(rollup_binding_tag)
FIELD(layer2_rollup_data)
}
END_SERIALIZE()
public:
@@ -399,18 +268,10 @@ namespace cryptonote
return_address_list.clear();
return_address_change_mask.clear();
return_pubkey = crypto::null_pkey;
protocol_tx_data.return_address = crypto::null_pkey;
protocol_tx_data.return_pubkey = crypto::null_pkey;
protocol_tx_data.return_view_tag = {};
protocol_tx_data.return_anchor_enc = {};
token_metadata.version = 0;
source_asset_type.clear();
destination_asset_type.clear();
amount_burnt = 0;
amount_slippage_limit = 0;
rollup_binding_tag = {0};
token_metadata = {};
layer2_rollup_data = {};
}
};
@@ -674,91 +535,6 @@ namespace cryptonote
END_SERIALIZE()
};
struct token_block_info {
uint64_t block_height;
std::map<uint32_t, uint64_t> token_info; // Replaces the vector
token_block_info() = default; // default ctor
explicit token_block_info(const uint64_t h)
: block_height(h) {}
void clear() {
block_height = 0;
token_info.clear();
}
std::vector<uint8_t> serialize() const noexcept {
constexpr uint8_t version = 1; // Bump if format changes
uint32_t sz = static_cast<uint32_t>(token_info.size());
size_t total_size = sizeof(uint8_t) + sizeof(uint64_t) + sizeof(uint32_t) + (sz * (sizeof(uint32_t) + sizeof(uint64_t)));
std::vector<uint8_t> buf(total_size);
uint8_t* ptr = buf.data();
std::memcpy(ptr, &version, sizeof(uint8_t));
ptr += sizeof(uint8_t);
std::memcpy(ptr, &block_height, sizeof(uint64_t));
ptr += sizeof(uint64_t);
std::memcpy(ptr, &sz, sizeof(uint32_t));
ptr += sizeof(uint32_t);
for (const auto& p : token_info) { // Iterates in sorted order
std::memcpy(ptr, &p.first, sizeof(uint32_t));
ptr += sizeof(uint32_t);
std::memcpy(ptr, &p.second, sizeof(uint64_t));
ptr += sizeof(uint64_t);
}
return buf;
}
void deserialize(const uint8_t* data, size_t len) {
if (len < sizeof(uint32_t)) {
throw std::runtime_error("Invalid serialized data");
}
uint8_t version;
std::memcpy(&version, data, sizeof(uint8_t));
data += sizeof(uint8_t);
len -= sizeof(uint8_t);
if (version == 0) { // Legacy: No height/version (your current format)
// Handle old blobs: Caller must set block_height externally
block_height = 0; // Or throw if height is mandatory
} else if (version == 1) {
if (len < sizeof(uint64_t) + sizeof(uint32_t)) {
throw std::runtime_error("Invalid serialized data");
}
std::memcpy(&block_height, data, sizeof(uint64_t));
data += sizeof(uint64_t);
len -= sizeof(uint64_t);
} else {
throw std::runtime_error("Unsupported version");
}
uint32_t sz;
std::memcpy(&sz, data, sizeof(uint32_t));
data += sizeof(uint32_t);
len -= sizeof(uint32_t);
if (len != sz * (sizeof(uint32_t) + sizeof(uint64_t))) {
throw std::runtime_error("Invalid serialized data length");
}
token_info.clear();
for (uint32_t i = 0; i < sz; ++i) {
uint32_t k;
uint64_t v;
std::memcpy(&k, data, sizeof(uint32_t));
data += sizeof(uint32_t);
std::memcpy(&v, data, sizeof(uint64_t));
data += sizeof(uint64_t);
token_info[k] = v; // Map handles sorting/uniquness
}
}
};
struct yield_block_info {
uint64_t block_height;
uint64_t slippage_total_this_block;
@@ -893,7 +669,6 @@ namespace cryptonote
{
crypto::public_key m_spend_public_key;
crypto::public_key m_view_public_key;
bool m_is_carrot;
BEGIN_SERIALIZE_OBJECT()
FIELD(m_spend_public_key)
@@ -908,8 +683,7 @@ namespace cryptonote
bool operator==(const account_public_address& rhs) const
{
return m_spend_public_key == rhs.m_spend_public_key &&
m_view_public_key == rhs.m_view_public_key &&
m_is_carrot == rhs.m_is_carrot;
m_view_public_key == rhs.m_view_public_key;
}
bool operator!=(const account_public_address& rhs) const
@@ -978,10 +752,6 @@ VARIANT_TAG(binary_archive, cryptonote::txout_to_scripthash, 0x1);
VARIANT_TAG(binary_archive, cryptonote::txout_to_key, 0x2);
VARIANT_TAG(binary_archive, cryptonote::txout_to_tagged_key, 0x3);
VARIANT_TAG(binary_archive, cryptonote::txout_to_carrot_v1, 0x4);
VARIANT_TAG(binary_archive, cryptonote::protocol_tx_data_t, 0x0);
VARIANT_TAG(binary_archive, cryptonote::token_metadata_t, 0x0);
VARIANT_TAG(binary_archive, cryptonote::erc_token_t, 0x0);
VARIANT_TAG(binary_archive, cryptonote::sal_token_t, 0x1);
VARIANT_TAG(binary_archive, cryptonote::transaction, 0xcc);
VARIANT_TAG(binary_archive, cryptonote::block, 0xbb);
@@ -994,10 +764,6 @@ VARIANT_TAG(json_archive, cryptonote::txout_to_scripthash, "scripthash");
VARIANT_TAG(json_archive, cryptonote::txout_to_key, "key");
VARIANT_TAG(json_archive, cryptonote::txout_to_tagged_key, "tagged_key");
VARIANT_TAG(json_archive, cryptonote::txout_to_carrot_v1, "carrot_v1");
VARIANT_TAG(json_archive, cryptonote::protocol_tx_data_t, "protocol_tx_data");
VARIANT_TAG(json_archive, cryptonote::token_metadata_t, "token_metadata");
VARIANT_TAG(json_archive, cryptonote::erc_token_t, "erc_token");
VARIANT_TAG(json_archive, cryptonote::sal_token_t, "sal_token");
VARIANT_TAG(json_archive, cryptonote::transaction, "tx");
VARIANT_TAG(json_archive, cryptonote::block, "block");
@@ -1010,9 +776,5 @@ VARIANT_TAG(debug_archive, cryptonote::txout_to_scripthash, "scripthash");
VARIANT_TAG(debug_archive, cryptonote::txout_to_key, "key");
VARIANT_TAG(debug_archive, cryptonote::txout_to_tagged_key, "tagged_key");
VARIANT_TAG(debug_archive, cryptonote::txout_to_carrot_v1, "carrot_v1");
VARIANT_TAG(debug_archive, cryptonote::protocol_tx_data_t, "protocol_tx_data");
VARIANT_TAG(debug_archive, cryptonote::token_metadata_t, "token_metadata");
VARIANT_TAG(debug_archive, cryptonote::erc_token_t, "erc_token");
VARIANT_TAG(debug_archive, cryptonote::sal_token_t, "sal_token");
VARIANT_TAG(debug_archive, cryptonote::transaction, "tx");
VARIANT_TAG(debug_archive, cryptonote::block, "block");
@@ -155,9 +155,10 @@ namespace cryptonote {
network_type nettype
, bool subaddress
, account_public_address const & adr
, bool is_carrot
)
{
uint64_t address_prefix = adr.m_is_carrot
uint64_t address_prefix = is_carrot
? (subaddress ? get_config(nettype).CARROT_PUBLIC_SUBADDRESS_BASE58_PREFIX : get_config(nettype).CARROT_PUBLIC_ADDRESS_BASE58_PREFIX)
: (subaddress ? get_config(nettype).CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX : get_config(nettype).CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX);
@@ -168,9 +169,10 @@ namespace cryptonote {
network_type nettype
, account_public_address const & adr
, crypto::hash8 const & payment_id
, bool is_carrot
)
{
uint64_t integrated_address_prefix = adr.m_is_carrot ? get_config(nettype).CARROT_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX : get_config(nettype).CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX;
uint64_t integrated_address_prefix = is_carrot ? get_config(nettype).CARROT_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX : get_config(nettype).CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX;
integrated_address iadr = {
adr, payment_id
@@ -283,8 +285,6 @@ namespace cryptonote {
LOG_PRINT_L1("Failed to validate address keys");
return false;
}
info.address.m_is_carrot = info.is_carrot;
}
else
{
@@ -316,7 +316,6 @@ namespace cryptonote {
//we success
info.address = blob.m_address;
info.address.m_is_carrot = false;
info.is_subaddress = false;
info.has_payment_id = false;
info.is_carrot = false;
@@ -88,12 +88,14 @@ namespace cryptonote {
network_type nettype
, bool subaddress
, const account_public_address& adr
, bool is_carrot = false
);
std::string get_account_integrated_address_as_str(
network_type nettype
, const account_public_address& adr
, const crypto::hash8& payment_id
, bool is_carrot = false
);
bool get_account_address_from_str(
@@ -45,7 +45,6 @@
#include "crypto/crypto.h"
#include "ringct/rctTypes.h"
#include "ringct/rctOps.h"
#include "serialization/containers.h"
namespace boost
{
@@ -74,11 +73,6 @@ namespace boost
a & reinterpret_cast<char (&)[sizeof(crypto::key_image)]>(x);
}
template <class Archive>
inline void serialize(Archive &a, carrot::input_context_t &x, const boost::serialization::version_type ver)
{
a & reinterpret_cast<char (&)[sizeof(carrot::input_context_t)]>(x);
}
template <class Archive>
inline void serialize(Archive &a, crypto::view_tag &x, const boost::serialization::version_type ver)
{
a & reinterpret_cast<char (&)[sizeof(crypto::view_tag)]>(x);
@@ -172,59 +166,6 @@ namespace boost
a & x.target;
}
template <class Archive>
inline void serialize(Archive &a, cryptonote::protocol_tx_data_t &x, const boost::serialization::version_type ver)
{
a & x.version;
a & x.return_address;
a & x.return_pubkey;
a & x.return_view_tag;
a & x.return_anchor_enc;
}
template <class Archive>
inline void serialize(Archive &a, cryptonote::erc_token_t &x, const boost::serialization::version_type ver)
{
a & x.version;
a & x.contract_address;
a & x.lockbox_address;
a & x.ticker;
a & x.erc20_asset_id;
}
template <class Archive>
inline void serialize(Archive &a, cryptonote::sal_token_t &x, const boost::serialization::version_type ver)
{
a & x.version;
a & x.supply;
a & x.size;
a & x.name;
a & x.url;
a & x.signature;
}
template <class Archive>
inline void serialize(Archive &a, cryptonote::token_metadata_t &x, const boost::serialization::version_type ver)
{
a & x.version;
a & x.asset_type;
a & x.token;
}
template <class Archive>
inline void serialize(Archive &a, cryptonote::layer2_rollup_tx_t &x, const boost::serialization::version_type ver)
{
a & x.tx_prefix_hash;
a & x.first_key_image;
a & x.tx_fee;
}
template <class Archive>
inline void serialize(Archive &a, cryptonote::layer2_rollup_data_t &x, const boost::serialization::version_type ver)
{
a & x.version;
a & x.txs;
}
template <class Archive>
inline void serialize(Archive &a, cryptonote::transaction_prefix &x, const boost::serialization::version_type ver)
@@ -242,29 +183,14 @@ namespace boost
a & x.return_address_list;
a & x.return_address_change_mask;
} else {
if ((x.type == cryptonote::transaction_type::STAKE || x.type == cryptonote::transaction_type::CREATE_TOKEN) &&
(x.version >= TRANSACTION_VERSION_CARROT)) {
a & x.protocol_tx_data;
} else {
a & x.return_address;
a & x.return_pubkey;
}
a & x.return_address;
a & x.return_pubkey;
}
a & x.source_asset_type;
a & x.destination_asset_type;
a & x.amount_slippage_limit;
}
}
if (x.version >= TRANSACTION_VERSION_ENABLE_TOKENS) {
if (x.type == cryptonote::transaction_type::CREATE_TOKEN) {
a & x.token_metadata;
} else if (x.type == cryptonote::transaction_type::TRANSFER) {
a & x.rollup_binding_tag;
} else if (x.type == cryptonote::transaction_type::ROLLUP) {
a & x.rollup_binding_tag;
a & x.layer2_rollup_data;
}
}
}
template <class Archive>
@@ -283,28 +209,13 @@ namespace boost
a & x.return_address_list;
a & x.return_address_change_mask;
} else {
if ((x.type == cryptonote::transaction_type::STAKE || x.type == cryptonote::transaction_type::CREATE_TOKEN) &&
(x.version >= TRANSACTION_VERSION_CARROT)) {
a & x.protocol_tx_data;
} else {
a & x.return_address;
a & x.return_pubkey;
}
a & x.return_address;
a & x.return_pubkey;
}
a & x.source_asset_type;
a & x.destination_asset_type;
a & x.amount_slippage_limit;
}
if (x.version >= TRANSACTION_VERSION_ENABLE_TOKENS) {
if (x.type == cryptonote::transaction_type::CREATE_TOKEN) {
a & x.token_metadata;
} else if (x.type == cryptonote::transaction_type::TRANSFER) {
a & x.rollup_binding_tag;
} else if (x.type == cryptonote::transaction_type::ROLLUP) {
a & x.rollup_binding_tag;
a & x.layer2_rollup_data;
}
}
}
if (x.version == 1)
{
+36 -202
View File
@@ -31,7 +31,6 @@
#include <atomic>
#include <csignal>
#include <map>
#include <boost/algorithm/string.hpp>
#include "wipeable_string.h"
#include "string_tools.h"
@@ -44,7 +43,6 @@
#include "crypto/hash.h"
#include "ringct/rctSigs.h"
#include "oracle/asset_types.h"
#include "common/debugging.h"
using namespace epee;
@@ -115,7 +113,7 @@ namespace cryptonote
const bool plus = (
rv.type == rct::RCTTypeBulletproofPlus ||
rv.type == rct::RCTTypeFullProofs ||
/*rv.type == rct::RCTTypeSalviumZero ||*/
rv.type == rct::RCTTypeSalviumZero ||
rv.type == rct::RCTTypeSalviumOne);
const uint64_t bp_base = (32 * ((plus ? 6 : 9) + 7 * 2)) / 2; // notional size of a 2 output proof, normalized to 1 proof (ie, divided by 2)
const size_t n_outputs = tx.vout.size();
@@ -1116,37 +1114,7 @@ namespace cryptonote
default:
break;
}
if (asset_type_id)
{
// Check to see if 1st byte is permitted
std::string s, s_prefix;
switch (asset_type_id >> 24) {
case 0x01:
// We have a user-generated token
s_prefix = "sal";
break;
case 0x02:
s_prefix = "erc";
break;
default:
ASSERT_MES_AND_THROW("Invalid asset_type_id: " << asset_type_id);
}
// Break up the remaining 3 bytes into 4 chunks of base36/64
static const char alphabet[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
uint32_t asset_type_id_temp = asset_type_id & 0x00FFFFFF;
for (int i=0; i<4; ++i) {
uint8_t val = asset_type_id_temp & 0x0000003F;
if (val >= 36)
ASSERT_MES_AND_THROW("Invalid asset_type_id: " << asset_type_id);
s.push_back(alphabet[val]);
asset_type_id_temp >>= 6;
}
std::reverse(s.begin(), s.end());
return s_prefix + s;
}
// Should probably throw() here
ASSERT_MES_AND_THROW("Invalid asset_type_id: " << asset_type_id);
return "";
}
//---------------------------------------------------------------
@@ -1161,162 +1129,11 @@ namespace cryptonote
} else if (asset_type == "") {
return 0x00000000;
} else {
if (asset_type.length() != 7) {
LOG_ERROR("Custom asset type '" << asset_type << "' has invalid length.");
return 0x00000000;
}
static const std::string alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
// Check the 4-char type
std::string s_type = asset_type.substr(3);
std::transform(s_type.begin(), s_type.end(), s_type.begin(),
[](unsigned char c){ return std::toupper(c); });
uint32_t asset_id = 0x00000000;
for (int i=0; i<s_type.length(); ++i) {
uint8_t idx = alphabet.find(s_type.at(i));
if (idx == std::string::npos || idx >= 36) {
LOG_ERROR("Custom asset type contains invalid char.");
return 0x00000000;
}
asset_id = (asset_id << 6) | (idx & 0x3F);
}
// Check the 3-char prefix
std::string s_prefix = asset_type.substr(0,3);
std::transform(s_prefix.begin(), s_prefix.end(), s_prefix.begin(),
[](unsigned char c){ return std::tolower(c); });
if (s_prefix == "sal") {
asset_id |= 0x01000000;
} else if (s_prefix == "erc") {
asset_id |= 0x02000000;
} else {
LOG_ERROR("Custom asset type has invalid prefix.");
return 0x00000000;
}
return asset_id;
// Should probably throw() here
return static_cast<uint32_t>(-1);
}
}
//---------------------------------------------------------------
bool is_asset_type_token(const std::string& asset_type)
{
// SAL, SAL1, BURN are base asset types
// erc prefix is not included here
if (asset_type.length() >= 3) {
std::string prefix = asset_type.substr(0, 3);
return (prefix == "sal");
}
return false;
}
//---------------------------------------------------------------
bool is_valid_asset_type(const std::string& asset_type) {
// This method does NOT throw()
try {
uint32_t asset_id = asset_id_from_type(asset_type);
std::string asset_type_check = asset_type_from_id(asset_id);
return (asset_type_check == asset_type);
}
catch (std::exception e) {
return false;
}
}
//---------------------------------------------------------------
bool is_valid_custom_asset_type(const std::string& asset_type)
{
if (!is_valid_asset_type(asset_type))
return false;
// double check with reserved IDs
uint32_t id = asset_id_from_type(asset_type);
if (id == 0x53414C00 || id == 0x53414C31 || id == 0x4255524E || id == 0x00000000) {
return false;
}
return true;
}
//---------------------------------------------------------------
uint64_t get_token_creation_price(const std::string& ticker)
{
static const std::map<std::string, uint64_t> premium_tickers = {
// add more
{"USDT", 10000 * COIN},
{"USDC", 10000 * COIN},
{"WBTC", 10000 * COIN},
{"DOGE", 10000 * COIN},
{"SHIB", 10000 * COIN},
{"AVAX", 10000 * COIN},
{"ATOM", 10000 * COIN},
{"NEAR", 10000 * COIN},
{"TRON", 10000 * COIN},
{"HBAR", 10000 * COIN},
{"AAVE", 10000 * COIN},
{"FLOW", 10000 * COIN},
{"EGLD", 10000 * COIN},
{"KLAY", 10000 * COIN},
{"LUNA", 10000 * COIN},
{"DASH", 10000 * COIN},
{"NANO", 10000 * COIN},
{"CORE", 10000 * COIN},
{"BEAM", 10000 * COIN},
{"DYDX", 10000 * COIN},
{"COMP", 10000 * COIN},
{"SAND", 10000 * COIN},
{"MANA", 10000 * COIN},
{"RUNE", 10000 * COIN},
{"PYTH", 10000 * COIN},
{"ARKM", 10000 * COIN},
{"BLUR", 10000 * COIN},
{"STRK", 10000 * COIN},
{"PEPE", 10000 * COIN},
{"BONK", 10000 * COIN},
{"VIUM", 10000 * COIN},
{"GOLD", 10000 * COIN},
{"SILV", 10000 * COIN},
{"CASH", 10000 * COIN},
{"EURO", 10000 * COIN},
{"PESO", 10000 * COIN},
{"BOND", 10000 * COIN},
{"FUND", 10000 * COIN},
{"BANK", 10000 * COIN},
{"SWAP", 10000 * COIN},
{"LEND", 10000 * COIN},
{"LOAN", 10000 * COIN},
{"NOTE", 10000 * COIN},
{"HOLD", 10000 * COIN},
{"BULL", 10000 * COIN},
{"BEAR", 10000 * COIN},
{"TECH", 10000 * COIN},
{"DATA", 10000 * COIN},
{"HASH", 10000 * COIN},
{"NODE", 10000 * COIN},
{"BYTE", 10000 * COIN},
{"GRID", 10000 * COIN},
{"CODE", 10000 * COIN},
{"META", 10000 * COIN},
{"WEB3", 10000 * COIN},
{"NFTS", 10000 * COIN},
{"DEFI", 10000 * COIN},
{"LAND", 10000 * COIN},
{"REAL", 10000 * COIN},
{"RENT", 10000 * COIN},
{"FARM", 10000 * COIN},
{"OILX", 10000 * COIN},
{"ENRG", 10000 * COIN},
{"FUEL", 10000 * COIN},
{"VOTE", 10000 * COIN},
{"PASS", 10000 * COIN},
{"LOCK", 10000 * COIN},
};
// is it a premium ticker
auto it = premium_tickers.find(ticker);
if (it != premium_tickers.end()) {
return it->second;
}
// not premium
return 1000 * COIN;
}
//---------------------------------------------------------------
/**
* The various scenarios that are permitted for Salvium are more extensive than
* they are for Zepyhr / Havan. Specifically, we permit:
@@ -1564,31 +1381,48 @@ namespace cryptonote
for (const auto &o: tx.vout)
{
if (hf_version >= HF_VERSION_CARROT) {
if (tx.type != cryptonote::transaction_type::PROTOCOL) {
CHECK_AND_ASSERT_MES(o.target.type() == typeid(txout_to_carrot_v1), false, "wrong variant type: "
<< o.target.type().name() << ", expected txout_to_carrot_v1 in transaction id=" << get_transaction_hash(tx));
} else {
CHECK_AND_ASSERT_MES(o.target.type() == typeid(txout_to_key) ||
o.target.type() == typeid(txout_to_tagged_key) ||
o.target.type() == typeid(txout_to_carrot_v1), false, "wrong variant type: "
<< o.target.type().name() << ", expected txout_to_key or txout_to_tagged_key or txout_to_carrot_v1 in protocol transaction");
// require all outputs in a tx be of the same type
CHECK_AND_ASSERT_MES(o.target.type() == tx.vout[0].target.type(), false, "non-matching variant types: "
<< o.target.type().name() << " and " << tx.vout[0].target.type().name() << ", "
<< "expected matching variant types in protocol transaction");
}
}
else {
if (hf_version >= HF_VERSION_CARROT)
{
// from v11, require outputs be carrot outputs
CHECK_AND_ASSERT_MES(o.target.type() == typeid(txout_to_carrot_v1), false, "wrong variant type: "
<< o.target.type().name() << ", expected txout_to_carrot_v1 in transaction id=" << get_transaction_hash(tx));
} else {
// require outputs be of type txout_to_key OR txout_to_tagged_key
// to allow grace period before requiring all to be txout_to_tagged_key
CHECK_AND_ASSERT_MES(o.target.type() == typeid(txout_to_key) || o.target.type() == typeid(txout_to_tagged_key), false, "wrong variant type: "
<< o.target.type().name() << ", expected txout_to_key or txout_to_tagged_key in transaction");
// require all outputs in a tx be of the same type
CHECK_AND_ASSERT_MES(o.target.type() == tx.vout[0].target.type(), false, "non-matching variant types: "
<< o.target.type().name() << " and " << tx.vout[0].target.type().name() << ", "
<< "expected matching variant types in transaction");
}
// Verify the asset type
std::string asset_type;
CHECK_AND_ASSERT_MES(cryptonote::get_output_asset_type(o, asset_type), false, "failed to get asset type");
if (hf_version < HF_VERSION_SALVIUM_ONE_PROOFS) {
// Prior to the first audit, ONLY SAL was supported
CHECK_AND_ASSERT_MES(asset_type == "SAL", false, "wrong output asset type:" << asset_type);
} else {
if (tx.type == cryptonote::transaction_type::AUDIT) {
// HERE BE DRAGONS!!!
// SRCG: This will NOT always be the case - when we add an audit for SALx it'll need to support that as well
// The CHANGE for an AUDIT TX must be SAL (and 0 value, and unspendable, and to the origin wallet, and ...)
CHECK_AND_ASSERT_MES(asset_type == "SAL", false, "wrong output asset type:" << asset_type);
// LAND AHOY!!!
} else if (tx.type == cryptonote::transaction_type::PROTOCOL) {
if (hf_version < HF_VERSION_AUDIT1_PAUSE) {
// PROTOCOL TXs are responsible for paying out SAL and SAL1 during the first AUDIT
CHECK_AND_ASSERT_MES(asset_type == "SAL1" || asset_type == "SAL", false, "wrong output asset type:" << asset_type);
} else {
CHECK_AND_ASSERT_MES(asset_type == "SAL1", false, "wrong output asset type:" << asset_type);
}
} else {
// All other TX types must only spend + create SAL1 (MINER, TRANSFER)
CHECK_AND_ASSERT_MES(asset_type == "SAL1", false, "wrong output asset type:" << asset_type);
}
}
}
return true;
}
@@ -135,10 +135,6 @@ namespace cryptonote
uint64_t get_outs_money_amount(const transaction& tx);
std::string asset_type_from_id(const uint32_t asset_type_id);
uint32_t asset_id_from_type(const std::string asset_type);
bool is_valid_custom_asset_type(const std::string& asset_type);
bool is_valid_asset_type(const std::string& asset_type);
bool is_asset_type_token(const std::string& asset_type);
uint64_t get_token_creation_price(const std::string& ticker);
bool get_tx_asset_types(const transaction& tx, const crypto::hash &txid, std::string& source, std::string& destination, const bool is_miner_tx);
bool get_output_public_key(const cryptonote::tx_out& out, crypto::public_key& output_public_key);
boost::optional<crypto::view_tag> get_output_view_tag(const cryptonote::tx_out& out);
+4 -23
View File
@@ -104,9 +104,7 @@ namespace cryptonote
}
miner::miner(i_miner_handler* phandler, const get_block_hash_t &gbh):
m_forced_stop(1),
m_stop(1),
miner::miner(i_miner_handler* phandler, const get_block_hash_t &gbh):m_stop(1),
m_template{},
m_template_no(0),
m_diffic(0),
@@ -175,12 +173,9 @@ namespace cryptonote
uint64_t seed_height;
crypto::hash seed_hash;
crypto::public_key miner_reward_tx_key;
if(!m_phandler->get_block_template(bl, m_mine_address, di, height, expected_reward, extra_nonce, seed_height, seed_hash, miner_reward_tx_key))
if(!m_phandler->get_block_template(bl, m_mine_address, di, height, expected_reward, extra_nonce, seed_height, seed_hash))
{
LOG_ERROR("Failed to get_block_template(), stopping mining");
m_forced_stop = true;
m_stop = true;
return false;
}
set_block_template(bl, di, height, expected_reward);
@@ -190,17 +185,7 @@ namespace cryptonote
bool miner::on_idle()
{
m_update_block_template_interval.do_call([&](){
if(is_mining()) {
// Request the block template
request_block_template();
} else {
// Check for forced stop
if (m_forced_stop) {
if (!m_threads_active) {
stop();
}
}
}
if(is_mining())request_block_template();
return true;
});
@@ -408,12 +393,8 @@ namespace cryptonote
return false;
}
if (!request_block_template()) {
LOG_ERROR("Unable to start miner - unknown error");
return false;
}
request_block_template();//lets update block template
m_forced_stop = false;
m_stop = false;
m_thread_index = 0;
set_is_background_mining_enabled(do_background);
+1 -2
View File
@@ -47,7 +47,7 @@ namespace cryptonote
struct i_miner_handler
{
virtual bool handle_block_found(block& b, block_verification_context &bvc) = 0;
virtual bool get_block_template(block& b, const account_public_address& adr, difficulty_type& diffic, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce, uint64_t &seed_height, crypto::hash &seed_hash, crypto::public_key &miner_reward_tx_key) = 0;
virtual bool get_block_template(block& b, const account_public_address& adr, difficulty_type& diffic, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce, uint64_t &seed_height, crypto::hash &seed_hash) = 0;
protected:
~i_miner_handler(){};
};
@@ -118,7 +118,6 @@ namespace cryptonote
};
std::atomic<bool> m_forced_stop;
std::atomic<bool> m_stop;
epee::critical_section m_template_lock;
block m_template;
+1 -12
View File
@@ -39,7 +39,6 @@
#define TX_EXTRA_NONCE 0x02
#define TX_EXTRA_MERGE_MINING_TAG 0x03
#define TX_EXTRA_TAG_ADDITIONAL_PUBKEYS 0x04
#define TX_EXTRA_TAG_TOKEN 0x80
#define TX_EXTRA_MYSTERIOUS_MINERGATE_TAG 0xDE
#define TX_EXTRA_NONCE_PAYMENT_ID 0x00
@@ -168,15 +167,6 @@ namespace cryptonote
END_SERIALIZE()
};
struct tx_extra_token
{
cryptonote::token_metadata_t token;
BEGIN_SERIALIZE()
FIELD(token)
END_SERIALIZE()
};
struct tx_extra_mysterious_minergate
{
std::string data;
@@ -190,7 +180,7 @@ namespace cryptonote
// varint tag;
// varint size;
// varint data[];
typedef boost::variant<tx_extra_padding, tx_extra_pub_key, tx_extra_nonce, tx_extra_merge_mining_tag, tx_extra_additional_pub_keys, tx_extra_mysterious_minergate, tx_extra_token> tx_extra_field;
typedef boost::variant<tx_extra_padding, tx_extra_pub_key, tx_extra_nonce, tx_extra_merge_mining_tag, tx_extra_additional_pub_keys, tx_extra_mysterious_minergate> tx_extra_field;
}
VARIANT_TAG(binary_archive, cryptonote::tx_extra_padding, TX_EXTRA_TAG_PADDING);
@@ -199,4 +189,3 @@ VARIANT_TAG(binary_archive, cryptonote::tx_extra_nonce, TX_EXTRA_NONCE);
VARIANT_TAG(binary_archive, cryptonote::tx_extra_merge_mining_tag, TX_EXTRA_MERGE_MINING_TAG);
VARIANT_TAG(binary_archive, cryptonote::tx_extra_additional_pub_keys, TX_EXTRA_TAG_ADDITIONAL_PUBKEYS);
VARIANT_TAG(binary_archive, cryptonote::tx_extra_mysterious_minergate, TX_EXTRA_MYSTERIOUS_MINERGATE_TAG);
VARIANT_TAG(binary_archive, cryptonote::tx_extra_token, TX_EXTRA_TAG_TOKEN);
+38 -39
View File
@@ -44,11 +44,9 @@
#define CRYPTONOTE_MAX_TX_PER_BLOCK 0x10000000
#define CRYPTONOTE_PUBLIC_ADDRESS_TEXTBLOB_VER 0
#define CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW 60
#define CURRENT_TRANSACTION_VERSION 5
#define CURRENT_TRANSACTION_VERSION 3
#define TRANSACTION_VERSION_2_OUTS 2
#define TRANSACTION_VERSION_N_OUTS 3
#define TRANSACTION_VERSION_CARROT 4
#define TRANSACTION_VERSION_ENABLE_TOKENS 5
#define CURRENT_BLOCK_MAJOR_VERSION 1
#define CURRENT_BLOCK_MINOR_VERSION 1
#define CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT 60*60*2
@@ -89,14 +87,8 @@
#define PREMINE_AMOUNT_UPFRONT ((uint64_t)650000000000000ull) // 3.4% of MONEY_SUPPLY
#define PREMINE_AMOUNT_MONTHLY ((uint64_t)65000000000000ull) // 8.6%/24 of MONEY_SUPPLY
#define TREASURY_SAL1_MINT_AMOUNT ((uint64_t)130000000000000ull) // 1.3M
#define TREASURY_SAL1_MINT_COUNT 8 // 8 times
#define CREATE_TOKEN_LOCK_PERIOD 10
// HF11 block reward split
#define BLOCK_REWARD_TREASURY_PCT 25 // to treasury, 21600-block unlock
#define BLOCK_REWARD_STAKER_PCT 20 // to stakers via yield
#define TREASURY_SAL1_MINT_AMOUNT ((uint64_t)65000000000000ull) // 650K
#define TREASURY_SAL1_MINT_COUNT 16 // 16 times
#define DIFFICULTY_TARGET_V2 120 // seconds
#define DIFFICULTY_TARGET_V1 60 // seconds - before first fork
@@ -251,14 +243,13 @@
#define HF_VERSION_AUDIT2 8
#define HF_VERSION_AUDIT2_PAUSE 9
#define HF_VERSION_CARROT 10
#define HF_VERSION_ENABLE_TOKENS 11
#define HF_VERSION_REQUIRE_VIEW_TAGS 255
#define HF_VERSION_ENABLE_CONVERT 255
#define HF_VERSION_ENABLE_ORACLE 255
#define HF_VERSION_SLIPPAGE_YIELD 255
#define TESTNET_VERSION 18
#define TESTNET_VERSION 14
#define STAGENET_VERSION 1
#define PER_KB_FEE_QUANTIZATION_DECIMALS 8
@@ -323,19 +314,26 @@ namespace config
const uint64_t STAKE_LOCK_PERIOD = 30*24*30;
const uint64_t TREASURY_SAL1_MINT_PERIOD = 30*24*30; // 1 month of blocks
std::string const TREASURY_ADDRESS_CARROT = "SC11ksHLFhy7H1yMk9bUZvADG1Z9ZkR1T5QMknm3RbGBbgdPkyanB2WBb5TER3MsiwJC5BnyoiYs2DBcvAfAm6JQ537iNKdtvm";
std::string const TREASURY_ADDRESS = "SaLvdZR6w1A21sf2Wh6jYEh1wzY4GSbT7RX6FjyPsnLsffWLrzFQeXUXJcmBLRWDzZC2YXeYe5t7qKsnrg9FpmxmEcxPHsEYfqA";
// treasury payout {tx-key, output-key, anchor_enc, view_tag} tuples
// treasury payout {tx-key, output-key, anchor_enc, vie_tag} tuples
const std::map<uint64_t, std::tuple<std::string, std::string, std::string, std::string>> TREASURY_SAL1_MINT_OUTPUT_DATA = {
{334750, {"1b2cd3ff56aa77c0cbab0473bfb96697ebdd0b25ad230136bfe41d5dc1ef265f","718cf02eabca157fd7ad7f8537db217624bfe1ca99dd09e758357e7000a5e57a","789cca3def51fb879eb7fbca271869b7","79bd0c"}},
{356350, {"b51acbf35265d09f3cfb83dcabde2746991ddf0d30b5a4ecc34043b349a77031","9dc0d2e9534cdccf83494687c55c67c8c1b29834acf97cce53124a08a9549231","588ebc2918d06c009a18a28a8ab76694","ab8c23"}},
{377950, {"771c6865980493846cbb049b34f72b937878cf799ae1126775df35064cf53526","60d340613c7721aeb03f2de1b56e2916d6cb023cc668acaca00e1606e0bb7f64","198bb0e5880c8abf8108158284ca7637","9b93f2"}},
{399550, {"d9159f9bb654230382a69bb7a739c14f9d506c21dba5be9f4cdf66126ed1b24e","c3b34e7f9977f31f659abd9306b650416a674ed7bcfb8c75b257040a1a06b8b9","6f0de181716e0a9e100228d58f11d42c","4c87fd"}},
{421150, {"1e2ab1ae204e7a9375f5b57fed2524e2d1a4702c4bbc6d420eb65d92af44c60c","826ecca0e2837860a6d2be89a410ff6aab22c5f5a66bd0a318de3abe646aa26a","bad663aa8253c40d00de0a2d1dfca60f","4a04d7"}},
{442750, {"18267940a2b37c82850f3fb83d935281ee5cc436b0797ec10ca26c9cc3c0ef01","77bdec7bbc4cabd84cc8cf0666e1fdfe299480b9b2a4cf52cc959d728fa899ab","a8807121e33471cf18aa82af4826c9a7","d35d35"}},
{464350, {"9ab50223bfecec2508e8233540dc13c3fc7e15a8d77ecb90939afee96859724d","675a1b3f2a2cd2bd0e7ec073c426125d95e12ad13e541bf019925c481c2bca15","591d2f2331832c347654ab255ad97e2d","d87c9c"}},
{485950, {"c0d7299fe0b873687e7319f1a0d1f67712ef3ccf6a579d96c5f99743add6f029","dd3d17b5145b56377e023c169ae858cdf48bd6c23e8b2a77e02765ce316e3ca7","6a9e74df01762e2b32db1dc4d69dc3e9","75debe"}}
{1000000ULL, {"a1bdd1da651fbbb845232816e1aa2d4ff29b790f10bbd4f574a012f1199e15a4", "b0733ab6f251b16458efa9ebb3fb99bd54d43173b5768fe9ffc42e0fe46ae3a8", "00", "00"}},
{1020000ULL, {"47996eccbcc078b06d0f6ece37bf3a700c2bd60adfdd898b22096f16a9ad315c", "fd6bcceb4799ee067d59b97a6f66a0f9a70f134220259d3b4d6a2278ba4aca4c", "00", "00"}},
{1040000ULL, {"a3e6754a849b80c21a77e6065fefdae29eeeabf17c407453356244a00545bdb8", "3d395454df1452d715d27190e022b20395871c99af578f7251c3f9752e0274a6", "00", "00"}},
{1060000ULL, {"0d5e97a910e0f9c606ad9c711b6595aaed142d857cde2efa519112b9a29240d5", "56c29e28bdcf4f20b4b45906b93ae7c4bf9ee82e18cd45543cb69a14ce5efb88", "00", "00"}},
{1080000ULL, {"495fa363de88915aa8b74818c4b80715a882a688b4f7127ab7cd3b6885f3567a", "d42dfe0da5579c82e8255eba8c0a17170023f14a6a5030da6abf9f10abb52cbb", "00", "00"}},
{1100000ULL, {"85ea10ec40390e4f406446fb519e974d89536154045c6df28bb3b538b254e20d", "0ce2b7dd3a8ce8b596889dac8081a62f98fd70f1f043944ab4ac592c3c59e77b", "00", "00"}},
{1120000ULL, {"40f201b38a319dda81e7201e57fea7924067a4a332ed71b8e51ec29ac2d67310", "8289aa6963b98d1034e94eae55d8be6b33d0a88f14f174ebcbaec70837986c7c", "00", "00"}},
{1140000ULL, {"c5a648cc7846341357b7b4653a58f9eb4800d88b5de587bceec7a5c28f98d05a", "3f308a203845d88e5e728fcebcdcea1f90e2f424d461617993c672a6138ad2d8", "00", "00"}},
{1160000ULL, {"4c51d6550b8eeb6cc8f0d395cc83a5f90ec2a4d86501b3f68da48d618ccf5711", "53f0bd8cebeefb3a88fffa5d7f6ad43d4712608ded561732467ca499df940454", "00", "00"}},
{1180000ULL, {"ce2f5d82118fed03d5e269e285fc16189a6cd34f38999e5c055a5dea5fce61bc", "f7fc6948b194d9bd6f2df6ecb83f04e6c8d1a2556a63fedb310a4631fe1bfc42", "00", "00"}},
{1200000ULL, {"6248028fd77fb02b5c6ea72dea10b417891a2da7aaf9565aed382e063b4981a3", "63986e1177499bdb23cd49afb519ec18f38cb1b0c386220b376d8ffdc2e37890", "00", "00"}},
{1220000ULL, {"6adcb695aa5d6d01133c68900f29e501e9549816e827ea0c164bbc78f3534dd6", "6a440ccb18f5e703e8000de3865ac40d4c18f081270d32eef377dc831f28d8d0", "00", "00"}},
{1240000ULL, {"b97a4d2259480f34f20e41c489ab5c2e5ae9ee84d8672a7eff8012f2260e121e", "e6eb9147ff40e22209d321d0f1bfbfe20acf5ceb6b9d0bfb13688ad28aa1232e", "00", "00"}},
{1260000ULL, {"4fd214602a36902f22d16927244c456e8cc5a406a9570131f138a028214ffdf0", "34060b8bd96009b9b298280ebd84fa9587fa8c9df6fb5ad0270fb6cd2098885c", "00", "00"}},
{1280000ULL, {"9d60178ec6d6599d7a31298f2559fb9c3111f2c70494b3a1638db877ea55b808", "7985ed03856a929663e954738d0938713407717835f760c7ca4d54844a128c91", "00", "00"}},
{1300000ULL, {"cd65718eab234bf419332e53bd2f48e2ade70af48c5e126ab5080321e1493dfc", "581cb4cca7a0a029ee2cac51dfc00a0c3a657d2eaf67ed3c6ae7bacc11b4f007", "00", "00"}},
};
// Hash domain separators
@@ -428,20 +426,26 @@ namespace config
"KWv3Vo1/Gny+1vfaxsXhBQiG1KlHkafNGarzoL0WHW4ocqaaqF5iv8i35A==\n"
"-----END PUBLIC KEY-----\n";
std::string const TREASURY_ADDRESS_CARROT = "SC1TouvX6e4HmkAqsU6AAXLRjgeZnnKHjSpVfMHepTXramNMT2P47AsDmteLH81wdPR2DwMg3cxKvgrhUBeDSUW6MhM3sQb92we";
std::string const TREASURY_ADDRESS = "SaLvTyL2pN2SCAPRxwDQ7qjhdg46VbhZrGZTp2wHKJ5sK434a8ivEH35eWp2FTcmyW6LY6ExfBb9chmQ9xAL1eJyZ5FQjtQGTis3v";
std::string const TREASURY_ADDRESS = "SaLvTyLFta9BiAXeUfFkKvViBkFt4ay5nEUBpWyDKewYggtsoxBbtCUVqaBjtcCDyY1euun8Giv7LLEgvztuurLo5a6Km1zskZn36";
// treasury payout {tx-key, output-key, anchor_enc, vie_tag} tuples
// check address type before future development
const std::map<uint64_t, std::tuple<std::string, std::string, std::string, std::string>> TREASURY_SAL1_MINT_OUTPUT_DATA = {
{1100, {"71336a480440ed24a53b2cfd5a5292d1e618c3e843637227883ea2cc42fb346f","a135f59a05ea9e33539e4502b187b4789cc7fba79616c6902a902cc6601f0359","7f1c6970232254a9b13f7f063df2a853","62073c"}},
{1120, {"2cc49b182addc0106b601c9876c01a4b06532c05f9dd9179b2c4f47e5c7c0d74","fd62e59324389f37d0bb628a39f413c11be34d572ec3a40f465e008b9dfd5e0c","fbf8584222e299bb748009eaf2177123","b76a8d"}},
{1140, {"50f1dd5244bb6fdc62b5a18b868a4dc9e9ad15f4a7a54e5a98084a3a5213c846","942de90a3347df3e962d9b0a2745f8aedb265a8caf73aabef9aa713f4ec3e493","933702e29d680bf21ad559a2d3243621","dae32b"}},
{1160, {"114a1fef3a03c81b3b6308fb4e51db42d86945d8f71ee8798749a4aa2d8bfe57","fd77f0289b7e25ae68c86f4cd2c72ac0211a4d0e7a31c84b8d58a33bbd3c511b","d8048bb76b9313768a4c69100cba6d43","46b0a3"}},
{1180, {"cf7fe9d97a7a4cb881bff1d37bb6981bcb0691649c465d660522a43f14b32849","b76908d56108e7111374f60993e9411def7bb2899118f20f49e67a801936a1ad","f203a5acd48f93f1451d32d70716e585","d72097"}},
{1200, {"415e8fa4fb6bed8bc59591883f5e098dde6179e980eccfc4cbb3a64c4168cf47","5426c588d7c5750c76b526ef268b45f7414e2ddea40218ee92d123564c5114c4","fb1926bbef8c70ebd796ae77dffca07d","351edf"}},
{1220, {"1f47cce00e8e1c77cb3ff007491d261dae75de5bbfdbe0f4913d74a8503aaa5e","4d8aac299306989aa169982d89457852a1bab858c668c9b740d96b682bb1961b","d8c0be7926ce704290cfd8d5e0500f33","750003"}},
{1240, {"3afd93c684638d54e68f5d8d417863035f12482251feea5cf7515725a2bb0f4f","7895e6baded473b093b57993ae3497a47b0ea78cf35b37d1387f226f445d9018","76a0c37e6f3d9d508c4bce1d7162514e","09e146"}}
{1100, {"310fe378b82e2475a87c83eef07c57d92fa0731d5c499258e774852158276968","f17c5a62efcc96710f2a173538fe5e79b190b44ab6facc01a619f0e227ac18d1","eb613855f58d093ae9d527e8ab69b46a","6c74f9"}},
{1120, {"adb74cea72d46ebe5a45e5886189e71c493308686f076ccfc053cb9b4f55b656","b40e958589238cc48a5a7f03f1f28406a13b2f724efe831cfec43c06bb0fcb60","77a51cc3a6c3c53d631cadad72f57c1d","e5fec0"}},
{1140, {"c5e9a67c695ddcab05b980de0c8cc7d9d5b9c09af58047843bfd7d29a038f671","6c3253bd837b899b87aedc97114feb9c10c2d255ce59b7ba5b470817a37d16df","fcf6e1907ea30dbafd510e33a37cc2dc","fa5c45"}},
{1160, {"e95c8b7fc3d0e7e34d544e97d3b526e94f70acb7d85cb0053b3cb830e863ac38","3a5ae93e922985ea1a126ff8fd35f6cbf39fa556525e15a049765510eb1360e1","7ea6d62add9387a28f3dbed5dbac120b","c26ac2"}},
{1180, {"9d453235a25e470df2d7ceaa8f8d4216a8939a0a93bc0c43f1b902cb461ee82d","2e990ed2de4d745389d88aa9868634ce430f09d2c0cb5ebc2ee8b9bcc23e221a","807e07241a48b97acb537241822a97b8","eb37c0"}},
{1200, {"92dbd7da158d4bcb4f002dcc505ed4c49ac4e4782724b506a5977119c80c4869","4505a9be31c2ac6ad5faa2ea8332b85b1a3efee84d0456740d208b8188ad842a","8870c1f88de25b5443d8323759f386d9","443c65"}},
{1220, {"1e4d5c44a112c3ac89ab2c7065bb2c8c094779b3a5d696652198f7dd05f88b77","01f56bf134652852688e30dd9559bdb5fe2edd046bed99dbea23b655d2475b89","da088fc1e1c2f2d0e348f06f2079e8ed","d7c7bf"}},
{1240, {"91ba144c930a65996b2d7c3b296217c692225756392b580a323838e48b357452","f2d5f4f2aaa599a52c557270cbc5cde138b753a98297d975b74a7223a9b80b13","0dc3a42cb1f36768a09c316790936356","172c22"}},
{1260, {"1d626ede8d2e34e888384655b30942a25be272a3ea58d49835265e6933a91a52","05666de1b136236f0682e128c0c3ae84578a6a4b233a578dd676e581a582fe19","c81ccf7f93e01e7872543907de8d17d0","21dd94"}},
{1280, {"85b10b5ae72ab59281f47be4edede17b7a017dc7ddd839813e3a12c0b2a39874","d34d259e2fee2b0c977242c473cf83997920c1e64ff7a9c364b2bf4abba4d5cc","43de6ce100ca3eeb6734fc44cc9f7dbc","574e2f"}},
{1300, {"c699ca0dcbe538e6be9e997acb50a4c13557d1e8cf3a105ab47406cb68300656","50c5e0fa60907c2c2b66748562193b7f5bfcba269eb398c5c975c9e125933942","05aeb41f8863152a7e0e36f216ecbb12","e413dd"}},
{1320, {"76bb126d6e0e5d3d7ee7ccabd194a248cbe006ae7d57f89c31c6826f8e7b4851","e1f2277b378630d92bc03003e3d206899404afde342fcb3a9b1790f798c8b5a4","26274ad1bbf5d483f2c747754b898873","a2df70"}},
{1340, {"5738dc94686bfffe1789b695785f270f6f616b1a52e071e975cf915063233b1a","982b4848ed74f2a5d899f778b182c35f40535579349435b466ff98c3fce678e7","67bd9b9a434b9028564a065a30ae34fa","36ceec"}},
{1360, {"473b6f6941d6eafaef007d3d932763b6e39c1428d3ba76dfff452ddc67f93b48","76e3b1280b959672d86c357e6f5fcd8a74e61a0a948a0541a0eb384060705bac","74b5ad8847471e3d8723ad3e101b8a13","5e5671"}},
{1380, {"6dae9a14e24b96caf8f7acb0edad936a4ecaa194a61b3785a2b1d08cbca0a158","26ca204c10481ed2447447e3893e0c46c9f01df16c3f3a671cf9e6054176ee5d","7c04e4ed28bfac12a0050bdae44f9979","4c23ad"}},
{1400, {"a5837480d8e17ddb9b29baaf5671545d59d18b546de0d7092768882cff94d125","dc76eb3892b3721da947fc71de8ab30ef32651f1b6bb1a45eb7b80882217a5ac","bb490940a3cdf4a17fd0bec0b578531f","84d899"}}
};
}
@@ -474,7 +478,6 @@ namespace config
"KWv3Vo1/Gny+1vfaxsXhBQiG1KlHkafNGarzoL0WHW4ocqaaqF5iv8i35A==\n"
"-----END PUBLIC KEY-----\n";
std::string const TREASURY_ADDRESS_CARROT = ""; // TODO: generate stagenet Carrot treasury address ?
std::string const TREASURY_ADDRESS = "fuLMowH85abK8nz9BBMEem7MAfUbQu4aSHHUV9j5Z86o6Go9Lv2U5ZQiJCWPY9R9HA8p5idburazjAhCqDngLo7fYPCD9ciM9ee1A";
// treasury payout {tx-key, output-key, anchor_enc, view_tag} tuples
@@ -529,7 +532,6 @@ namespace cryptonote
uint64_t TREASURY_SAL1_MINT_PERIOD;
std::map<uint8_t, std::pair<uint64_t, std::pair<std::string, std::string>>> const AUDIT_HARD_FORKS;
std::string TREASURY_ADDRESS;
std::string TREASURY_ADDRESS_CARROT;
std::map<uint64_t, std::tuple<std::string, std::string, std::string, std::string>> TREASURY_SAL1_MINT_OUTPUT_DATA;
};
inline const config_t& get_config(network_type nettype)
@@ -553,7 +555,6 @@ namespace cryptonote
::config::TREASURY_SAL1_MINT_PERIOD,
::config::AUDIT_HARD_FORKS,
::config::TREASURY_ADDRESS,
::config::TREASURY_ADDRESS_CARROT,
::config::TREASURY_SAL1_MINT_OUTPUT_DATA
};
static const config_t testnet = {
@@ -575,7 +576,6 @@ namespace cryptonote
::config::testnet::TREASURY_SAL1_MINT_PERIOD,
::config::testnet::AUDIT_HARD_FORKS,
::config::testnet::TREASURY_ADDRESS,
::config::testnet::TREASURY_ADDRESS_CARROT,
::config::testnet::TREASURY_SAL1_MINT_OUTPUT_DATA
};
static const config_t stagenet = {
@@ -597,7 +597,6 @@ namespace cryptonote
::config::stagenet::TREASURY_SAL1_MINT_PERIOD,
::config::stagenet::AUDIT_HARD_FORKS,
::config::stagenet::TREASURY_ADDRESS,
::config::stagenet::TREASURY_ADDRESS_CARROT,
::config::stagenet::TREASURY_SAL1_MINT_OUTPUT_DATA
};
switch (nettype)
File diff suppressed because it is too large Load Diff
+5 -28
View File
@@ -394,8 +394,8 @@ namespace cryptonote
*
* @return true if block template filled in successfully, else false
*/
bool create_block_template(block& b, const account_public_address& miner_address, difficulty_type& di, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce, uint64_t &seed_height, crypto::hash &seed_hash, crypto::public_key &miner_reward_tx_key);
bool create_block_template(block& b, const crypto::hash *from_block, const account_public_address& miner_address, difficulty_type& di, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce, uint64_t &seed_height, crypto::hash &seed_hash, crypto::public_key &miner_reward_tx_key);
bool create_block_template(block& b, const account_public_address& miner_address, difficulty_type& di, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce, uint64_t &seed_height, crypto::hash &seed_hash);
bool create_block_template(block& b, const crypto::hash *from_block, const account_public_address& miner_address, difficulty_type& di, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce, uint64_t &seed_height, crypto::hash &seed_hash);
/**
* @brief gets data required to create a block template and start mining on it
@@ -726,19 +726,6 @@ namespace cryptonote
*/
bool check_tx_outputs(const transaction& tx, tx_verification_context &tvc) const;
/**
* @brief check a transaction's input/output/TX asset types conform to current standards
*
* This function checks, for example at the time of this writing, that
* the asset types are supported by the given TX for the current HF version on-chain.
*
* @param tx the transaction to check the asset types of
* @param tvc returned info about tx verification
*
* @return false if the TX version and/or type is unsupported, otherwise true
*/
bool check_tx_asset_types(const transaction& tx, tx_verification_context &tvc) const;
/**
* @brief check that a transaction's version & type conforms to current standards
*
@@ -1188,13 +1175,6 @@ namespace cryptonote
*/
bool calculate_yield_payouts(const uint64_t start_height, std::vector<std::pair<yield_tx_info, uint64_t>>& yield_payouts);
/**
* calculate the yield payouts
*
* @return TRUE if the payouts were calculated successfully, FALSE otherwise
*/
bool calculate_yield_payouts(const uint64_t start_height, std::vector<std::pair<yield_tx_info_carrot, uint64_t>>& yield_payouts);
/**
* @brief get the ABI entry for a particular height from the cache
*
@@ -1246,8 +1226,6 @@ namespace cryptonote
*/
bool validate_ybi_cache();
bool is_tx_paid_for(const cryptonote::transaction& tx);
#ifndef IN_UNIT_TESTS
private:
#endif
@@ -1333,7 +1311,7 @@ namespace cryptonote
crypto::hash m_btc_seed_hash;
uint64_t m_btc_seed_height;
bool m_btc_valid;
crypto::public_key m_btc_miner_reward_tx_key;
bool m_batch_success;
@@ -1579,11 +1557,10 @@ namespace cryptonote
* @param b the block containing the miner transaction to be validated
* @param height the blockchain's weight
* @param version hard fork version for that transaction
* @param txs create_coin transactions in the block
*
* @return false if anything is found wrong with the protocol transaction, otherwise true
*/
bool validate_protocol_transaction(const block& b, uint64_t height, uint8_t hf_version, const std::vector<std::pair<transaction, blobdata>>& txs = std::vector<std::pair<transaction, blobdata>>());
bool validate_protocol_transaction(const block& b, uint64_t height, uint8_t hf_version);
/**
* @brief reverts the blockchain to its previous state following a failed switch
@@ -1759,7 +1736,7 @@ namespace cryptonote
*
* At some point, may be used to push an update to miners
*/
void cache_block_template(const block &b, const cryptonote::account_public_address &address, const blobdata &nonce, const difficulty_type &diff, uint64_t height, uint64_t expected_reward, uint64_t seed_height, const crypto::hash &seed_hash, uint64_t pool_cookie, crypto::public_key &miner_reward_tx_key);
void cache_block_template(const block &b, const cryptonote::account_public_address &address, const blobdata &nonce, const difficulty_type &diff, uint64_t height, uint64_t expected_reward, uint64_t seed_height, const crypto::hash &seed_hash, uint64_t pool_cookie);
/**
* @brief sends new block notifications to ZMQ `miner_data` subscribers
+10 -32
View File
@@ -843,10 +843,7 @@ namespace cryptonote
bad_semantics_txes_lock.unlock();
uint8_t hf_version = m_blockchain_storage.get_current_hard_fork_version();
const size_t max_tx_version = hf_version >= HF_VERSION_ENABLE_TOKENS ? TRANSACTION_VERSION_ENABLE_TOKENS :
hf_version >= HF_VERSION_CARROT ? TRANSACTION_VERSION_CARROT :
hf_version >= HF_VERSION_ENABLE_N_OUTS ? TRANSACTION_VERSION_N_OUTS :
TRANSACTION_VERSION_2_OUTS;
const size_t max_tx_version = (hf_version >= HF_VERSION_ENABLE_N_OUTS) ? TRANSACTION_VERSION_N_OUTS : TRANSACTION_VERSION_2_OUTS;
if (tx.version == 0 || tx.version > max_tx_version)
{
// v2 is the latest one we know
@@ -905,7 +902,6 @@ namespace cryptonote
//-----------------------------------------------------------------------------------------------
bool core::handle_incoming_tx_accumulated_batch(std::vector<tx_verification_batch_info> &tx_info, bool keeped_by_block)
{
const uint8_t hf_version = m_blockchain_storage.get_current_hard_fork_version();
bool ret = true;
if (keeped_by_block && get_blockchain_storage().is_within_compiled_block_hash_area())
{
@@ -927,6 +923,7 @@ namespace cryptonote
if (tx_info[n].tx->version < 2)
continue;
const rct::rctSig &rv = tx_info[n].tx->rct_signatures;
const uint8_t hf_version = m_blockchain_storage.get_current_hard_fork_version();
if (hf_version >= HF_VERSION_CARROT) {
if (rv.type != rct::RCTTypeNull && rv.type != rct::RCTTypeSalviumOne) {
MERROR_VER("Invalid RCT type provided");
@@ -951,11 +948,7 @@ namespace cryptonote
tx_info[n].result = false;
return false;
}
}
bool need_rollup = false;
if (hf_version >= HF_VERSION_CARROT) {
need_rollup = (tx_info[n].tx->source_asset_type != "SAL1");
}
}
switch (rv.type) {
case rct::RCTTypeNull:
// coinbase should not come here, so we reject for all other types
@@ -970,8 +963,7 @@ namespace cryptonote
tx_info[n].tx->type == cryptonote::transaction_type::CONVERT ? tx_info[n].tx->amount_burnt :
tx_info[n].tx->type == cryptonote::transaction_type::STAKE ? tx_info[n].tx->amount_burnt :
tx_info[n].tx->type == cryptonote::transaction_type::AUDIT ? tx_info[n].tx->amount_burnt :
0,
need_rollup
0
))
{
MERROR_VER("rct signature semantics check failed");
@@ -1028,7 +1020,7 @@ namespace cryptonote
}
if (!rvv.empty())
{
LOG_PRINT_L1("Verifying transactions one at a time");
LOG_PRINT_L1("One transaction among this group has bad semantics, verifying one at a time");
ret = false;
for (size_t n = 0; n < tx_info.size(); ++n)
{
@@ -1036,19 +1028,12 @@ namespace cryptonote
continue;
if (tx_info[n].tx->rct_signatures.type != rct::RCTTypeBulletproof && tx_info[n].tx->rct_signatures.type != rct::RCTTypeBulletproof2 && tx_info[n].tx->rct_signatures.type != rct::RCTTypeCLSAG && tx_info[n].tx->rct_signatures.type != rct::RCTTypeBulletproofPlus && tx_info[n].tx->rct_signatures.type != rct::RCTTypeFullProofs && tx_info[n].tx->rct_signatures.type != rct::RCTTypeSalviumZero && tx_info[n].tx->rct_signatures.type != rct::RCTTypeSalviumOne)
continue;
bool need_rollup = false;
if (hf_version >= HF_VERSION_CARROT) {
need_rollup = (tx_info[n].tx->source_asset_type != "SAL1");
}
if (!rct::verRctSemanticsSimple(tx_info[n].tx->rct_signatures,
tx_info[n].tx->type == cryptonote::transaction_type::BURN ? tx_info[n].tx->amount_burnt :
tx_info[n].tx->type == cryptonote::transaction_type::CONVERT ? tx_info[n].tx->amount_burnt :
tx_info[n].tx->type == cryptonote::transaction_type::STAKE ? tx_info[n].tx->amount_burnt :
tx_info[n].tx->type == cryptonote::transaction_type::AUDIT ? tx_info[n].tx->amount_burnt :
tx_info[n].tx->type == cryptonote::transaction_type::CREATE_TOKEN ? tx_info[n].tx->amount_burnt :
tx_info[n].tx->type == cryptonote::transaction_type::ROLLUP ? tx_info[n].tx->amount_burnt :
0,
need_rollup
0
))
{
set_semantics_failed(tx_info[n].tx_hash);
@@ -1262,13 +1247,6 @@ namespace cryptonote
return false;
}
/*
if (hf_version >= HF_VERSION_ENABLE_TOKENS && !m_blockchain_storage.is_tx_paid_for(tx))
{
MERROR_VER("tx has not been paid for by ROLLUP");
return false;
}
*/
return true;
}
//-----------------------------------------------------------------------------------------------
@@ -1542,14 +1520,14 @@ namespace cryptonote
notify_txpool_event(tx_blobs, epee::to_span(tx_hashes), epee::to_span(txs), just_broadcasted);
}
//-----------------------------------------------------------------------------------------------
bool core::get_block_template(block& b, const account_public_address& adr, difficulty_type& diffic, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce, uint64_t &seed_height, crypto::hash &seed_hash, crypto::public_key &miner_reward_tx_key)
bool core::get_block_template(block& b, const account_public_address& adr, difficulty_type& diffic, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce, uint64_t &seed_height, crypto::hash &seed_hash)
{
return m_blockchain_storage.create_block_template(b, adr, diffic, height, expected_reward, ex_nonce, seed_height, seed_hash, miner_reward_tx_key);
return m_blockchain_storage.create_block_template(b, adr, diffic, height, expected_reward, ex_nonce, seed_height, seed_hash);
}
//-----------------------------------------------------------------------------------------------
bool core::get_block_template(block& b, const crypto::hash *prev_block, const account_public_address& adr, difficulty_type& diffic, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce, uint64_t &seed_height, crypto::hash &seed_hash, crypto::public_key &miner_reward_tx_key)
bool core::get_block_template(block& b, const crypto::hash *prev_block, const account_public_address& adr, difficulty_type& diffic, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce, uint64_t &seed_height, crypto::hash &seed_hash)
{
return m_blockchain_storage.create_block_template(b, prev_block, adr, diffic, height, expected_reward, ex_nonce, seed_height, seed_hash, miner_reward_tx_key);
return m_blockchain_storage.create_block_template(b, prev_block, adr, diffic, height, expected_reward, ex_nonce, seed_height, seed_hash);
}
//-----------------------------------------------------------------------------------------------
bool core::get_miner_data(uint8_t& major_version, uint64_t& height, crypto::hash& prev_id, crypto::hash& seed_hash, difficulty_type& difficulty, uint64_t& median_weight, uint64_t& already_generated_coins, std::vector<tx_block_template_backlog_entry>& tx_backlog)
+2 -2
View File
@@ -231,8 +231,8 @@ namespace cryptonote
*
* @note see Blockchain::create_block_template
*/
virtual bool get_block_template(block& b, const account_public_address& adr, difficulty_type& diffic, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce, uint64_t &seed_height, crypto::hash &seed_hash, crypto::public_key &miner_reward_tx_key) override;
virtual bool get_block_template(block& b, const crypto::hash *prev_block, const account_public_address& adr, difficulty_type& diffic, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce, uint64_t &seed_height, crypto::hash &seed_hash, crypto::public_key &miner_reward_tx_key);
virtual bool get_block_template(block& b, const account_public_address& adr, difficulty_type& diffic, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce, uint64_t &seed_height, crypto::hash &seed_hash) override;
virtual bool get_block_template(block& b, const crypto::hash *prev_block, const account_public_address& adr, difficulty_type& diffic, uint64_t& height, uint64_t& expected_reward, const blobdata& ex_nonce, uint64_t &seed_height, crypto::hash &seed_hash);
/**
* @copydoc Blockchain::get_miner_data
+57 -125
View File
@@ -346,30 +346,14 @@ namespace cryptonote
// Clear the TX contents
tx.set_null();
tx.version = (hard_fork_version >= HF_VERSION_ENABLE_TOKENS) ? 3 : 2;
bool carrot_found = false;
bool noncarrot_found = false;
tx.type = cryptonote::transaction_type::PROTOCOL;
// Scan the protocol_data to make sure all or none are Carrot
for (auto const& entry: protocol_data) {
if (entry.is_carrot) carrot_found = true;
else noncarrot_found = true;
}
// Force the TX type to 2
tx.version = 2;
if (carrot_found && noncarrot_found) {
LOG_ERROR("Cannot mix Carrot and non-Carrot outputs in the same protocol transaction");
return false;
}
if (carrot_found && hard_fork_version < HF_VERSION_CARROT) {
LOG_ERROR("Carrot outputs found in CryptoNote protocol transaction");
return false;
}
if (carrot_found || (!noncarrot_found && hard_fork_version >= HF_VERSION_CARROT))
const bool do_carrot = hard_fork_version >= HF_VERSION_CARROT;
if (do_carrot)
{
// Ensure the TX version is correct
tx.version = TRANSACTION_VERSION_CARROT;
try
{
// Create a vector of enotes
@@ -378,21 +362,34 @@ namespace cryptonote
// Iterate over the protocol_data we received, creating an enote for each entry
for (auto const& entry: protocol_data) {
carrot::CarrotDestinationV1 destination;
carrot::make_carrot_main_address_v1(entry.P_change,
entry.return_address,
destination);
CHECK_AND_ASSERT_THROW_MES(!destination.is_subaddress,
"construct_protocol_tx: subaddress are not allowed in miner transactions");
CHECK_AND_ASSERT_THROW_MES(destination.payment_id == carrot::null_payment_id,
"construct_protocol_tx: integrated addresses are not allowed in miner transactions");
LOG_PRINT_L2(((entry.type == cryptonote::transaction_type::STAKE) ? "Yield TX payout submitted " : "Audit TX payout submitted ") << entry.amount_burnt << entry.source_asset);
const carrot::CarrotPaymentProposalV1 payment_proposal{
.destination = destination,
.amount = entry.amount_burnt,
.asset_type = "SAL1",
.randomness = carrot::gen_janus_anchor()
};
// Build the proposal
carrot::CarrotCoinbaseEnoteV1 e;
e.onetime_address = entry.return_address;
// amount_minted for CREATE_TOKEN, amount_burnt for STAKE/AUDIT
e.amount = (entry.type == cryptonote::transaction_type::CREATE_TOKEN) ? entry.amount_minted : entry.amount_burnt;
e.asset_type = entry.destination_asset;
e.view_tag = entry.return_view_tag;
e.anchor_enc = entry.return_anchor_enc;
e.block_index = height;
memcpy(e.enote_ephemeral_pubkey.data, entry.return_pubkey.data, sizeof(crypto::public_key));
get_coinbase_output_proposal_v1(payment_proposal, height, e);
enotes.push_back(e);
}
tx = store_carrot_to_coinbase_transaction_v1(enotes, std::string{}, cryptonote::transaction_type::PROTOCOL, height);
tx.amount_burnt = 0;
tx.version = (hard_fork_version >= HF_VERSION_ENABLE_TOKENS) ? TRANSACTION_VERSION_ENABLE_TOKENS : TRANSACTION_VERSION_CARROT;
tx.invalidate_hashes();
}
catch (const std::exception &e)
@@ -413,29 +410,14 @@ namespace cryptonote
std::vector<crypto::public_key> additional_tx_public_keys;
for (auto const& entry: protocol_data) {
if (entry.type == cryptonote::transaction_type::STAKE) {
// PAYOUT
LOG_PRINT_L2("Yield TX payout submitted " << entry.amount_burnt << entry.source_asset);
if (entry.is_carrot) {
tx_out out;
out.amount = entry.amount_burnt;
out.target = txout_to_carrot_v1 {
.key = entry.return_address,
.asset_type = entry.destination_asset,
.view_tag = entry.return_view_tag,
.encrypted_janus_anchor = entry.return_anchor_enc,
};
additional_tx_public_keys.push_back(entry.return_pubkey);
tx.vout.push_back(out);
} else {
// Create the TX output for this refund
tx_out out;
cryptonote::set_tx_out(entry.amount_burnt, entry.destination_asset, CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW, entry.return_address, false, crypto::view_tag{}, out);
additional_tx_public_keys.push_back(entry.return_pubkey);
tx.vout.push_back(out);
}
// Create the TX output for this refund
tx_out out;
cryptonote::set_tx_out(entry.amount_burnt, entry.destination_asset, CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW, entry.return_address, false, crypto::view_tag{}, out);
additional_tx_public_keys.push_back(entry.return_pubkey);
tx.vout.push_back(out);
} else if (entry.type == cryptonote::transaction_type::AUDIT) {
// PAYOUT
LOG_PRINT_L2("Audit TX payout submitted " << entry.amount_burnt << entry.source_asset);
@@ -459,17 +441,7 @@ namespace cryptonote
return true;
}
//---------------------------------------------------------------
carrot::janus_anchor_t get_deterministic_treasury_anchor_from_height(uint64_t height)
{
carrot::janus_anchor_t treasury_anchor{};
for (int i = 0; i < 8; ++i)
treasury_anchor.bytes[i] = (height >> (8 * i)) & 0xff;
for (int i = 8; i < 16; ++i)
treasury_anchor.bytes[i] = 0;
return treasury_anchor;
}
//---------------------------------------------------------------
bool construct_miner_tx(size_t height, size_t median_weight, uint64_t already_generated_coins, size_t current_block_weight, uint64_t fee, const account_public_address &miner_address, crypto::public_key& miner_reward_tx_key, transaction& tx, network_type nettype, const std::vector<hardfork_t>& hardforks, const blobdata& extra_nonce, size_t max_outs, uint8_t hard_fork_version) {
bool construct_miner_tx(size_t height, size_t median_weight, uint64_t already_generated_coins, size_t current_block_weight, uint64_t fee, const account_public_address &miner_address, transaction& tx, network_type nettype, const std::vector<hardfork_t>& hardforks, const blobdata& extra_nonce, size_t max_outs, uint8_t hard_fork_version) {
// Clear the TX contents
tx.set_null();
@@ -497,70 +469,33 @@ namespace cryptonote
{
try
{
// miner destination
carrot::CarrotDestinationV1 miner_destination;
// Build the miner payout
carrot::CarrotDestinationV1 destination;
carrot::make_carrot_main_address_v1(miner_address.m_spend_public_key,
miner_address.m_view_public_key,
miner_destination);
CHECK_AND_ASSERT_THROW_MES(!miner_destination.is_subaddress,
"construct_miner_tx: subaddresses are not allowed in miner transactions");
CHECK_AND_ASSERT_THROW_MES(miner_destination.payment_id == carrot::null_payment_id,
"construct_miner_tx: integrated addresses are not allowed in miner transactions");
destination);
const bool do_new_split = (hard_fork_version >= HF_VERSION_ENABLE_TOKENS);
uint64_t treasury_reward = do_new_split ? (block_reward * BLOCK_REWARD_TREASURY_PCT / 100) : 0;
uint64_t stake_reward = (block_reward - treasury_reward) * BLOCK_REWARD_STAKER_PCT / 100;
uint64_t miner_reward = (block_reward - treasury_reward - stake_reward);
CHECK_AND_ASSERT_THROW_MES(!destination.is_subaddress,
"make_single_enote_carrot_coinbase_transaction_v1: subaddress are not allowed in miner transactions");
CHECK_AND_ASSERT_THROW_MES(destination.payment_id == carrot::null_payment_id,
"make_single_enote_carrot_coinbase_transaction_v1: integrated addresses are not allowed in miner transactions");
//miner enote
const carrot::CarrotPaymentProposalV1 miner_proposal{
.destination = miner_destination,
.amount = miner_reward,
uint64_t stake_reward = block_reward / 5;
const carrot::CarrotPaymentProposalV1 payment_proposal{
.destination = destination,
.amount = block_reward - stake_reward,
.asset_type = "SAL1",
.randomness = carrot::gen_janus_anchor()
};
// Determine number of enotes: miner + optional treasury_reward + optional treasury_mint
size_t num_enotes = 1;
if (do_new_split) num_enotes++; // treasury reward output
if (treasury_payout_exists) num_enotes++;
std::vector<carrot::CarrotCoinbaseEnoteV1> enotes(num_enotes);
carrot::get_coinbase_output_proposal_v1(miner_proposal, height, enotes[0]);
std::vector<carrot::CarrotCoinbaseEnoteV1> enotes(treasury_payout_exists ? 2 : 1);
carrot::get_coinbase_output_proposal_v1(payment_proposal, height, enotes.front());
// STORE THE MINER TX_PUB_KEY NOW
miner_reward_tx_key = carrot::raw_byte_convert<crypto::public_key>(enotes[0].enote_ephemeral_pubkey);
size_t enote_idx = 1;
// Add the treasury reward enote (25% of block reward) for HF11+
if (do_new_split) {
//treasury address for HF11+ block reward split
address_parse_info treasury_addr_info;
bool treasury_ok = cryptonote::get_account_address_from_str(treasury_addr_info, nettype, get_config(nettype).TREASURY_ADDRESS_CARROT);
CHECK_AND_ASSERT_MES(treasury_ok, false, "Failed to parse treasury address for block reward split"); // maybe more check can be added here, but it's enough for now (bcs validation)
carrot::CarrotDestinationV1 treasury_destination;
carrot::make_carrot_main_address_v1(treasury_addr_info.address.m_spend_public_key,
treasury_addr_info.address.m_view_public_key,
treasury_destination);
// Derive a deterministic janus anchor from height so validators can independently recompute the expected treasury K_o
const carrot::janus_anchor_t treasury_anchor = get_deterministic_treasury_anchor_from_height(height);
const carrot::CarrotPaymentProposalV1 treasury_proposal{
.destination = treasury_destination,
.amount = treasury_reward,
.asset_type = "SAL1",
.randomness = treasury_anchor
};
carrot::get_coinbase_output_proposal_v1(treasury_proposal, height, enotes[enote_idx]);
enote_idx++;
}
//
// Check to see if there needs to be a treasury payout
if (treasury_payout_exists) {
// Convert the strings into meaningful data
const auto [tx_public_key_str, onetime_address_str, anchor_enc_str, view_tag_str] = treasury_payout_data.at(height);
mx25519_pubkey tx_public_key;
CHECK_AND_ASSERT_THROW_MES(epee::string_tools::hex_to_pod(tx_public_key_str, tx_public_key), "fail to deserialize treasury tx public key");
@@ -571,8 +506,8 @@ namespace cryptonote
carrot::view_tag_t view_tag;
CHECK_AND_ASSERT_THROW_MES(epee::string_tools::hex_to_pod(view_tag_str, view_tag), "fail to deserialize treasury tx view_tag");
//
carrot::CarrotCoinbaseEnoteV1 &treasury_enote = enotes[enote_idx];
// Manually produce an enote for the treasury payout using the hardcoded keys
carrot::CarrotCoinbaseEnoteV1 &treasury_enote = enotes.back();
treasury_enote.onetime_address = onetime_address;
treasury_enote.amount = TREASURY_SAL1_MINT_AMOUNT;
treasury_enote.asset_type = "SAL1";
@@ -580,15 +515,15 @@ namespace cryptonote
treasury_enote.view_tag = view_tag;
treasury_enote.enote_ephemeral_pubkey = tx_public_key;
treasury_enote.block_index = height;
// sort enotes by K_o
if (enotes[0].onetime_address > enotes[1].onetime_address) {
std::swap(enotes[0], enotes[1]);
}
}
// Sort enotes by K_o
std::sort(enotes.begin(), enotes.end(), [](const carrot::CarrotCoinbaseEnoteV1 &a, const carrot::CarrotCoinbaseEnoteV1 &b) {
return a.onetime_address < b.onetime_address;
});
tx = carrot::store_carrot_to_coinbase_transaction_v1(enotes, extra_nonce, cryptonote::transaction_type::MINER, height);
tx.version = (hard_fork_version >= HF_VERSION_ENABLE_TOKENS) ? TRANSACTION_VERSION_ENABLE_TOKENS : TRANSACTION_VERSION_CARROT;
tx.amount_burnt = stake_reward;
tx.invalidate_hashes();
}
@@ -603,8 +538,6 @@ namespace cryptonote
keypair txkey = keypair::generate(hw::get_device("default"));
add_tx_pub_key_to_extra(tx, txkey.pub);
// STORE THE MINER TX_PUB_KEY NOW
miner_reward_tx_key = txkey.pub;
if(!extra_nonce.empty())
if(!add_extra_nonce_to_tx_extra(tx.extra, extra_nonce))
return false;
@@ -648,7 +581,6 @@ namespace cryptonote
case HF_VERSION_AUDIT2:
case HF_VERSION_AUDIT2_PAUSE:
case HF_VERSION_CARROT:
case HF_VERSION_ENABLE_TOKENS:
// SRCG: subtract 20% that will be rewarded to staking users
CHECK_AND_ASSERT_MES(tx.amount_burnt == 0, false, "while creating outs: amount_burnt is nonzero");
tx.amount_burnt = amount / 5;
+1 -6
View File
@@ -68,18 +68,13 @@ namespace cryptonote
uint8_t type;
crypto::public_key P_change;
crypto::public_key return_pubkey;
carrot::view_tag_t return_view_tag;
carrot::encrypted_janus_anchor_t return_anchor_enc;
uint64_t origin_height;
bool is_carrot;
};
//---------------------------------------------------------------
bool construct_protocol_tx(const size_t height, transaction& tx, std::vector<protocol_data_entry>& protocol_data, const uint8_t hf_version);
//---------------------------------------------------------------
carrot::janus_anchor_t get_deterministic_treasury_anchor_from_height(uint64_t height);
//---------------------------------------------------------------
bool construct_miner_tx(size_t height, size_t median_weight, uint64_t already_generated_coins, size_t current_block_weight, uint64_t fee, const account_public_address &miner_address, crypto::public_key& miner_reward_tx_key, transaction& tx, network_type nettype = network_type::FAKECHAIN, const std::vector<hardfork_t>& hardforks = {}, const blobdata& extra_nonce = blobdata(), size_t max_outs = 999, uint8_t hard_fork_version = 1);
bool construct_miner_tx(size_t height, size_t median_weight, uint64_t already_generated_coins, size_t current_block_weight, uint64_t fee, const account_public_address &miner_address, transaction& tx, network_type nettype = network_type::FAKECHAIN, const std::vector<hardfork_t>& hardforks = {}, const blobdata& extra_nonce = blobdata(), size_t max_outs = 999, uint8_t hard_fork_version = 1);
struct tx_source_entry
{
+2 -72
View File
@@ -47,7 +47,6 @@
#include "common/perf_timer.h"
#include "crypto/hash.h"
#include "crypto/duration.h"
#include "common/debugging.h"
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "txpool"
@@ -267,20 +266,6 @@ namespace cryptonote
tvc.m_verifivation_failed = true;
return false;
}
// Check the TX asset types
if (!m_blockchain.check_tx_asset_types(tx, tvc)) {
LOG_PRINT_L1("Transaction with id= "<< id << " has invalid asset type(s)");
tvc.m_verifivation_failed = true;
return false;
}
// HERE BE DRAGONS!!!
// Check that CREATE_TOKEN txs are unique in the pool
if (tx.type == cryptonote::transaction_type::CREATE_TOKEN) {
// TODO: ...scan the existing entries - requires either a registry of CREATE_TOKEN TXs, or to interatively process the pool
}
// LAND AHOY!!!
// assume failure during verification steps until success is certain
tvc.m_verifivation_failed = true;
@@ -1520,10 +1505,6 @@ namespace cryptonote
return false;
}
// Check that `transfer token` TXs have been paid for before accepting them into a block template
if (!m_blockchain.is_tx_paid_for(lazy_tx()))
return false;
//transaction is ok.
return true;
}
@@ -1633,7 +1614,7 @@ namespace cryptonote
//---------------------------------------------------------------------------------
//---------------------------------------------------------------------------------
//TODO: investigate whether boolean return is appropriate
bool tx_memory_pool::fill_block_template(block &bl, size_t median_weight, uint64_t already_generated_coins, size_t &total_weight, uint64_t &fee, uint64_t &expected_reward, std::vector<std::pair<protocol_tx_data_t, token_metadata_t>> &create_token_entries, uint8_t version)
bool tx_memory_pool::fill_block_template(block &bl, size_t median_weight, uint64_t already_generated_coins, size_t &total_weight, uint64_t &fee, uint64_t &expected_reward, uint8_t version)
{
CRITICAL_REGION_LOCAL(m_transactions_lock);
CRITICAL_REGION_LOCAL1(m_blockchain);
@@ -1649,6 +1630,7 @@ namespace cryptonote
return false;
}
size_t max_total_weight_pre_v5 = (130 * median_weight) / 100 - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE;
size_t max_total_weight_v5 = 2 * median_weight - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE;
size_t max_total_weight = version >= 5 ? max_total_weight_v5 : max_total_weight_pre_v5;
@@ -1656,15 +1638,6 @@ namespace cryptonote
LOG_PRINT_L2("Filling block template, median weight " << median_weight << ", " << m_txs_by_fee_and_receive_time.size() << " txes in the pool");
// Store list of tokens being created
std::set<std::string> tokens;
// Get the list of already-created tokens that are in the DB
std::map<std::string, cryptonote::token_metadata_t> mapTokens = m_blockchain.get_db().get_tokens();
for (const auto &entry: mapTokens) {
tokens.insert(entry.second.asset_type);
}
LockedTXN lock(m_blockchain.get_db());
auto sorted_it = m_txs_by_fee_and_receive_time.begin();
@@ -1776,49 +1749,6 @@ namespace cryptonote
LOG_PRINT_L2(" key images already seen");
continue;
}
if (version < HF_VERSION_CARROT && tx.version >= TRANSACTION_VERSION_CARROT)
{
LOG_PRINT_L2(" is a Carrot transaction - cannot be mined");
continue;
}
if (version >= HF_VERSION_CARROT && tx.version < TRANSACTION_VERSION_CARROT)
{
LOG_PRINT_L2(" is not a Carrot transaction - cannot be mined");
continue;
}
// check for ROLLUP TXs
if (tx.type == cryptonote::transaction_type::ROLLUP)
{
if (version < HF_VERSION_ENABLE_TOKENS) {
LOG_PRINT_L2(" is a ROLLUP transaction before they are permitted - cannot be mined");
continue;
}
}
// check and include create token entries
if (tx.type == transaction_type::CREATE_TOKEN)
{
if (version < HF_VERSION_ENABLE_TOKENS) {
LOG_PRINT_L2(" is a CREATE_TOKEN transaction before they are permitted - cannot be mined");
continue;
}
std::string asset_type = "sal" + tx.token_metadata.asset_type;
if (!cryptonote::is_valid_asset_type(asset_type)) {
LOG_PRINT_L2(" is a CREATE_TOKEN transaction with an invalid asset_type - cannot be mined");
continue;
}
// Check to see if token is already being created
if (tokens.find(tx.token_metadata.asset_type) != tokens.end()) {
LOG_PRINT_L2(" is a CREATE_TOKEN transaction with an asset_type already in the block template - cannot be mined");
continue;
}
tokens.insert(tx.token_metadata.asset_type);
create_token_entries.push_back(std::make_pair(tx.protocol_tx_data, tx.token_metadata));
}
bl.tx_hashes.push_back(sorted_it->second);
total_weight += meta.weight;
+1 -2
View File
@@ -226,12 +226,11 @@ namespace cryptonote
* @param total_weight return-by-reference the total weight of the new block
* @param fee return-by-reference the total of fees from the included transactions
* @param expected_reward return-by-reference the total reward awarded to the miner finding this block, including transaction fees
* @param create_token_entries list of create coin entries to include in protocol tx
* @param version hard fork version to use for consensus rules
*
* @return true
*/
bool fill_block_template(block &bl, size_t median_weight, uint64_t already_generated_coins, size_t &total_weight, uint64_t &fee, uint64_t &expected_reward, std::vector<std::pair<protocol_tx_data_t, token_metadata_t>> &create_token_entries, uint8_t version);
bool fill_block_template(block &bl, size_t median_weight, uint64_t already_generated_coins, size_t &total_weight, uint64_t &fee, uint64_t &expected_reward, uint8_t version);
/**
* @brief get a list of all transactions in the pool
@@ -187,7 +187,7 @@ bool ver_rct_non_semantics_simple_cached
// mixring. Future versions of the protocol may differ in this regard, but if this assumptions
// holds true in the future, enable the verification hash by modifying the `untested_tx`
// condition below.
const bool untested_tx = tx.version > TRANSACTION_VERSION_ENABLE_TOKENS || tx.rct_signatures.type > rct::RCTTypeSalviumOne;
const bool untested_tx = tx.version > 3 || tx.rct_signatures.type > rct::RCTTypeSalviumOne;
VER_ASSERT(!untested_tx, "Unknown TX type. Make sure RCT cache works correctly with this type and then enable it in the code here.");
// Don't cache older (or newer) rctSig types
+1 -3
View File
@@ -54,8 +54,6 @@ namespace cryptonote
STAKE = 6,
RETURN = 7,
AUDIT = 8,
CREATE_TOKEN = 9,
ROLLUP = 10,
MAX = 10
MAX = 8
};
}
+1 -10
View File
@@ -374,8 +374,6 @@ bool t_command_parser_executor::start_mining(const std::vector<std::string>& arg
return true;
}
bool is_carrot = m_executor.current_hard_fork_version() >= HF_VERSION_CARROT;
cryptonote::address_parse_info info;
cryptonote::network_type nettype = cryptonote::MAINNET;
if(!cryptonote::get_account_address_from_str(info, cryptonote::MAINNET, args.front()))
@@ -422,13 +420,6 @@ bool t_command_parser_executor::start_mining(const std::vector<std::string>& arg
tools::fail_msg_writer() << "subaddress for mining reward is not yet supported!" << std::endl;
return true;
}
if (info.is_carrot && !is_carrot) {
tools::fail_msg_writer() << "mining to Carrot wallet address, but Carrot isn't supported yet" << std::endl;
return true;
} else if (!info.is_carrot && is_carrot) {
tools::fail_msg_writer() << "mining to CryptoNote wallet address, but Carrot wallet address is required" << std::endl;
return true;
}
if(nettype != cryptonote::MAINNET)
std::cout << "Mining to a " << (nettype == cryptonote::TESTNET ? "testnet" : "stagenet") << " address, make sure this is intentional!" << std::endl;
uint64_t threads_count = 1;
@@ -479,7 +470,7 @@ bool t_command_parser_executor::start_mining(const std::vector<std::string>& arg
}
}
m_executor.start_mining(info.address, threads_count, nettype, do_background_mining, ignore_battery, info.is_carrot);
m_executor.start_mining(info.address, threads_count, nettype, do_background_mining, ignore_battery);
return true;
}
+1 -2
View File
@@ -149,8 +149,7 @@ void print_genesis_tx_hex(const cryptonote::network_type nettype) {
//Prepare genesis_tx
cryptonote::transaction tx_genesis;
crypto::public_key miner_reward_tx_key = crypto::null_pkey;
cryptonote::construct_miner_tx(0, 0, 0, 10, 0, miner_acc1.get_keys().m_account_address, miner_reward_tx_key, tx_genesis, (network_type)nettype, {}, blobdata(), 999, 1);
cryptonote::construct_miner_tx(0, 0, 0, 10, 0, miner_acc1.get_keys().m_account_address, tx_genesis, (network_type)nettype, {}, blobdata(), 999, 1);
std::cout << "Object:" << std::endl;
std::cout << obj_to_json_str(tx_genesis) << std::endl << std::endl;
+1 -29
View File
@@ -1352,7 +1352,7 @@ bool t_rpc_command_executor::print_transaction_pool_stats() {
return true;
}
bool t_rpc_command_executor::start_mining(cryptonote::account_public_address address, uint64_t num_threads, cryptonote::network_type nettype, bool do_background_mining, bool ignore_battery, bool is_carrot) {
bool t_rpc_command_executor::start_mining(cryptonote::account_public_address address, uint64_t num_threads, cryptonote::network_type nettype, bool do_background_mining, bool ignore_battery) {
cryptonote::COMMAND_RPC_START_MINING::request req;
cryptonote::COMMAND_RPC_START_MINING::response res;
req.miner_address = cryptonote::get_account_address_as_str(nettype, false, address);
@@ -1650,34 +1650,6 @@ bool t_rpc_command_executor::in_peers(bool set, uint32_t limit)
return true;
}
uint8_t t_rpc_command_executor::current_hard_fork_version()
{
cryptonote::COMMAND_RPC_HARD_FORK_INFO::request req;
cryptonote::COMMAND_RPC_HARD_FORK_INFO::response res;
std::string fail_message = "Unsuccessful";
epee::json_rpc::error error_resp;
req.version = 0;
if (m_is_rpc)
{
if (!m_rpc_client->json_rpc_request(req, res, "hard_fork_info", fail_message.c_str()))
{
return 0;
}
}
else
{
if (!m_rpc_server->on_hard_fork_info(req, res, error_resp) || res.status != CORE_RPC_STATUS_OK)
{
tools::fail_msg_writer() << make_error(fail_message, res.status);
return 0;
}
}
return res.version;
}
bool t_rpc_command_executor::hard_fork_info(uint8_t version)
{
cryptonote::COMMAND_RPC_HARD_FORK_INFO::request req;
+1 -3
View File
@@ -106,7 +106,7 @@ public:
bool print_transaction_pool_stats();
bool start_mining(cryptonote::account_public_address address, uint64_t num_threads, cryptonote::network_type nettype, bool do_background_mining = false, bool ignore_battery = false, bool is_carrot = false);
bool start_mining(cryptonote::account_public_address address, uint64_t num_threads, cryptonote::network_type nettype, bool do_background_mining = false, bool ignore_battery = false);
bool stop_mining();
@@ -128,8 +128,6 @@ public:
bool in_peers(bool set, uint32_t limit);
uint8_t current_hard_fork_version();
bool hard_fork_info(uint8_t version);
bool print_bans();
-4
View File
@@ -202,10 +202,6 @@ namespace hw {
const crypto::public_key &R, const crypto::public_key &A, const boost::optional<crypto::public_key> &B, const crypto::public_key &D, const crypto::secret_key &r,
crypto::signature &sig) = 0;
virtual void generate_carrot_tx_proof(const crypto::hash &prefix_hash,
const crypto::public_key &R, const crypto::public_key &A, const boost::optional<crypto::public_key> &B, const crypto::public_key &D, const crypto::secret_key &r,
const crypto::secret_key &a, crypto::signature &sig) = 0;
virtual bool open_tx(crypto::secret_key &tx_key) = 0;
virtual void get_transaction_prefix_hash(const cryptonote::transaction_prefix& tx, crypto::hash& h) = 0;
-6
View File
@@ -282,12 +282,6 @@ namespace hw {
crypto::generate_tx_proof(prefix_hash, R, A, B, D, r, sig);
}
void device_default::generate_carrot_tx_proof(const crypto::hash &prefix_hash,
const crypto::public_key &R, const crypto::public_key &A, const boost::optional<crypto::public_key> &B, const crypto::public_key &D, const crypto::secret_key &r,
const crypto::secret_key &a, crypto::signature &sig) {
crypto::generate_carrot_tx_proof(prefix_hash, R, A, B, D, r, a, sig);
}
bool device_default::open_tx(crypto::secret_key &tx_key) {
cryptonote::keypair txkey = cryptonote::keypair::generate(*this);
tx_key = txkey.sec;
-4
View File
@@ -112,10 +112,6 @@ namespace hw {
const crypto::public_key &R, const crypto::public_key &A, const boost::optional<crypto::public_key> &B, const crypto::public_key &D, const crypto::secret_key &r,
crypto::signature &sig) override;
void generate_carrot_tx_proof(const crypto::hash &prefix_hash,
const crypto::public_key &R, const crypto::public_key &A, const boost::optional<crypto::public_key> &B, const crypto::public_key &D, const crypto::secret_key &r,
const crypto::secret_key &a, crypto::signature &sig) override;
bool open_tx(crypto::secret_key &tx_key) override;
void get_transaction_prefix_hash(const cryptonote::transaction_prefix& tx, crypto::hash& h) override;
-8
View File
@@ -1433,14 +1433,6 @@ namespace hw {
#endif
}
void device_ledger::generate_carrot_tx_proof(const crypto::hash &prefix_hash,
const crypto::public_key &R, const crypto::public_key &A, const boost::optional<crypto::public_key> &B, const crypto::public_key &D, const crypto::secret_key &r,
const crypto::secret_key &a, crypto::signature &sig) {
// to-do: For now, carrot tx proofs are not supported
AUTO_LOCK_CMD();
crypto::generate_carrot_tx_proof(prefix_hash, R, A, B, D, r, a, sig);
}
bool device_ledger::open_tx(crypto::secret_key &tx_key) {
AUTO_LOCK_CMD();
this->lock();
-4
View File
@@ -253,10 +253,6 @@ namespace hw {
const crypto::public_key &R, const crypto::public_key &A, const boost::optional<crypto::public_key> &B, const crypto::public_key &D, const crypto::secret_key &r,
crypto::signature &sig) override;
void generate_carrot_tx_proof(const crypto::hash &prefix_hash,
const crypto::public_key &R, const crypto::public_key &A, const boost::optional<crypto::public_key> &B, const crypto::public_key &D, const crypto::secret_key &r,
const crypto::secret_key &a, crypto::signature &sig) override;
bool open_tx(crypto::secret_key &tx_key) override;
void get_transaction_prefix_hash(const cryptonote::transaction_prefix& tx, crypto::hash& h) override;
-9
View File
@@ -58,12 +58,6 @@ const hardfork_t mainnet_hard_forks[] = {
// version 9 starts from block 179200, which is on or around the 10th of March, 2025. Fork time finalised on 2025-02-24. No fork voting occurs for the v9 fork.
{ 9, 179200, 0, 1740393800 },
// version 10 Carrot - including treasury mint - starts from block 334750, which is on or around the 13th of October, 2025. Fork time finalised on 2025-09-29. No fork voting occurs for the v10 fork.
{10, 334750, 0, 1759142500 },
// version 11 Two Milestone 1 - starts from block 465000, which is on or around the 13th of April, 2026. Fork time finalised on 2026-03-20. No fork voting occurs for the v11 fork.
{11, 465000, 0, 1774000000 },
};
const size_t num_mainnet_hard_forks = sizeof(mainnet_hard_forks) / sizeof(mainnet_hard_forks[0]);
const uint64_t mainnet_hard_fork_version_1_till = ((uint64_t)-1);
@@ -98,9 +92,6 @@ const hardfork_t testnet_hard_forks[] = {
// version 10 Carrot - including treasury mint - starts from block 1100
{10, 1100, 0, 1739780005 },
// version 11
{11, 1200, 0, 1739880005 },
};
const size_t num_testnet_hard_forks = sizeof(testnet_hard_forks) / sizeof(testnet_hard_forks[0]);
const uint64_t testnet_hard_fork_version_1_till = ((uint64_t)-1);
-120
View File
@@ -26,8 +26,6 @@
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#pragma once
#include <cstdint> // For uint8_t, etc.
#include <cstring> // For memcpy
#include <string>
#include <vector>
@@ -76,122 +74,4 @@ namespace oracle {
}
}
};
class asset_type_counts_v2
{
public:
// Fields
std::map<uint32_t, uint64_t> asset_counts;
asset_type_counts_v2() noexcept
: asset_counts{}
{
}
uint64_t operator[](const uint32_t asset_type_id) const noexcept
{
if (asset_counts.count(asset_type_id) == 0)
return 0;
else
return asset_counts.at(asset_type_id);
}
bool add(const uint32_t asset_type_id, const uint64_t amount)
{
if (asset_counts.count(asset_type_id) == 0)
return false;
asset_counts[asset_type_id] += amount;
return true;
}
bool add_asset_type(const uint32_t asset_type_id)
{
if (asset_counts.count(asset_type_id) != 0)
return false;
asset_counts[asset_type_id] = 0;
return true;
}
std::map<uint32_t, uint64_t> get()
{
return asset_counts;
}
std::vector<uint32_t> get_asset_types() const noexcept
{
std::vector<uint32_t> asset_type_ids;
for (const auto& entry: asset_counts) {
asset_type_ids.push_back(entry.first);
}
return asset_type_ids;
}
bool has_asset_type(const uint32_t asset_type_id) const noexcept
{
return asset_counts.count(asset_type_id) == 1;
}
std::vector<uint8_t> serialize() const noexcept {
constexpr uint8_t version = 1; // Bump if format changes
uint32_t sz = static_cast<uint32_t>(asset_counts.size());
size_t total_size = sizeof(uint8_t) + sizeof(uint32_t) + (sz * (sizeof(uint32_t) + sizeof(uint64_t)));
std::vector<uint8_t> buf(total_size);
uint8_t* ptr = buf.data();
std::memcpy(ptr, &version, sizeof(uint8_t));
ptr += sizeof(uint8_t);
std::memcpy(ptr, &sz, sizeof(uint32_t));
ptr += sizeof(uint32_t);
for (const auto& p : asset_counts) { // Iterates in sorted order
std::memcpy(ptr, &p.first, sizeof(uint32_t));
ptr += sizeof(uint32_t);
std::memcpy(ptr, &p.second, sizeof(uint64_t));
ptr += sizeof(uint64_t);
}
return buf;
}
void deserialize(const uint8_t* data, size_t len) {
if (len < sizeof(uint32_t)) {
throw std::runtime_error("Invalid serialized data");
}
uint8_t version;
std::memcpy(&version, data, sizeof(uint8_t));
data += sizeof(uint8_t);
len -= sizeof(uint8_t);
if (version == 1) {
if (len < sizeof(uint32_t)) {
throw std::runtime_error("Invalid serialized data");
}
} else {
throw std::runtime_error("Unsupported version");
}
uint32_t sz;
std::memcpy(&sz, data, sizeof(uint32_t));
data += sizeof(uint32_t);
len -= sizeof(uint32_t);
if (len != sz * (sizeof(uint32_t) + sizeof(uint64_t))) {
throw std::runtime_error("Invalid serialized data length");
}
asset_counts.clear();
for (uint32_t i = 0; i < sz; ++i) {
uint32_t k;
uint64_t v;
std::memcpy(&k, data, sizeof(uint32_t));
data += sizeof(uint32_t);
std::memcpy(&v, data, sizeof(uint64_t));
data += sizeof(uint64_t);
asset_counts[k] = v; // Map handles sorting/uniquness
}
}
};
}
+22 -4
View File
@@ -733,9 +733,9 @@ namespace nodetool
std::set<std::string> full_addrs;
if (m_nettype == cryptonote::TESTNET)
{
full_addrs.insert("165.22.6.67:29080");
full_addrs.insert("165.22.15.162:29080");
full_addrs.insert("162.243.163.207:29080");
full_addrs.insert("72.5.43.63:29080");
full_addrs.insert("195.85.114.217:29080");
full_addrs.insert("206.188.197.72:29080");
}
else if (m_nettype == cryptonote::STAGENET)
{
@@ -881,6 +881,12 @@ namespace nodetool
if (m_nettype == cryptonote::MAINNET)
{
return {
"xwvz3ekocr3dkyxfkmgm2hvbpzx2ysqmaxgter7znnqrhoicygkfswid.onion:18083",
"4pixvbejrvihnkxmduo2agsnmc3rrulrqc7s3cbwwrep6h6hrzsibeqd.onion:18083",
"zbjkbsxc5munw3qusl7j2hpcmikhqocdf4pqhnhtpzw5nt5jrmofptid.onion:18083",
"qz43zul2x56jexzoqgkx2trzwcfnr6l3hbtfcfx54g4r3eahy3bssjyd.onion:18083",
"plowsof3t5hogddwabaeiyrno25efmzfxyro2vligremt7sxpsclfaid.onion:18083",
"plowsoffjexmxalw73tkjmf422gq6575fc7vicuu4javzn2ynnte6tyd.onion:18083",
};
}
return {};
@@ -888,6 +894,10 @@ namespace nodetool
if (m_nettype == cryptonote::MAINNET)
{
return {
"s3l6ke4ed3df466khuebb4poienoingwof7oxtbo6j4n56sghe3a.b32.i2p:18080",
"sel36x6fibfzujwvt4hf5gxolz6kd3jpvbjqg6o3ud2xtionyl2q.b32.i2p:18080",
"uqj3aphckqtjsitz7kxx5flqpwjlq5ppr3chazfued7xucv3nheq.b32.i2p:18080",
"vdmnehdjkpkg57nthgnjfuaqgku673r5bpbqg56ix6fyqoywgqrq.b32.i2p:18080",
};
}
return {};
@@ -2044,13 +2054,20 @@ namespace nodetool
return true;
static const std::vector<std::string> dns_urls = {
"blocklist.moneropulse.se"
, "blocklist.moneropulse.org"
, "blocklist.moneropulse.net"
, "blocklist.moneropulse.no"
, "blocklist.moneropulse.fr"
, "blocklist.moneropulse.de"
, "blocklist.moneropulse.ch"
};
std::vector<std::string> records;
if (!tools::dns_utils::load_txt_records_from_dns(records, dns_urls))
return true;
unsigned good = 0;
unsigned good = 0, bad = 0;
for (const auto& record : records)
{
std::vector<std::string> ips;
@@ -2074,6 +2091,7 @@ namespace nodetool
continue;
}
MWARNING("Invalid IP address or subnet from DNS blocklist: " << ip << " - " << parsed_addr.error());
++bad;
}
}
if (good > 0)
+3 -5
View File
@@ -1961,7 +1961,7 @@ namespace rct {
//ver RingCT simple
//assumes only post-rct style inputs (at least for max anonymity)
bool verRctSemanticsSimple(const rctSig & rv, const uint64_t amount_burnt, const bool fee_paid_for_in_rollup)
bool verRctSemanticsSimple(const rctSig & rv, const uint64_t amount_burnt)
{
try
{
@@ -2027,10 +2027,8 @@ namespace rct {
}
key sumOutpks = addKeys(masks);
DP(sumOutpks);
if (!fee_paid_for_in_rollup) {
const key txnFeeKey = scalarmultH(d2h(rv.txnFee));
addKeys(sumOutpks, txnFeeKey, sumOutpks);
}
const key txnFeeKey = scalarmultH(d2h(rv.txnFee));
addKeys(sumOutpks, txnFeeKey, sumOutpks);
const key txnAmountBurntKey = scalarmultH(d2h(amount_burnt));
addKeys(sumOutpks, txnAmountBurntKey, sumOutpks);
+2 -4
View File
@@ -202,11 +202,9 @@ namespace rct {
);
bool verRct(const rctSig & rv, bool semantics);
static inline bool verRct(const rctSig & rv) { return verRct(rv, true) && verRct(rv, false); }
bool verRctSemanticsSimple(const rctSig & rv, const uint64_t amount_burnt=0, const bool fee_paid_for_in_rollup=false);
bool verRctSemanticsSimple(const rctSig & rv, const uint64_t amount_burnt=0);
bool verRctNonSemanticsSimple(const rctSig & rv);
static inline bool verRctSimple(const rctSig & rv, const uint64_t amount_burnt=0, const bool fee_paid_for_in_rollup=false) {
return verRctSemanticsSimple(rv, amount_burnt, fee_paid_for_in_rollup) && verRctNonSemanticsSimple(rv);
}
static inline bool verRctSimple(const rctSig & rv, const uint64_t amount_burnt=0) { return verRctSemanticsSimple(rv, amount_burnt) && verRctNonSemanticsSimple(rv); }
xmr_amount decodeRct(const rctSig & rv, const key & sk, unsigned int i, key & mask, hw::device &hwdev);
xmr_amount decodeRct(const rctSig & rv, const key & sk, unsigned int i, hw::device &hwdev);
xmr_amount decodeRctSimple(const rctSig & rv, const key & sk, unsigned int i, key & mask, hw::device &hwdev);
+2 -3
View File
@@ -446,7 +446,7 @@ namespace rct {
return false;
for (size_t i = 0; i < outputs; ++i)
{
if (type == RCTTypeBulletproofPlus || type == RCTTypeFullProofs || type == RCTTypeSalviumZero || type == RCTTypeSalviumOne)
if (type == RCTTypeBulletproofPlus || type == RCTTypeFullProofs || type == RCTTypeSalviumZero)
{
// Since RCTTypeBulletproof2 enote types, we don't serialize the blinding factor, and only serialize the
// first 8 bytes of ecdhInfo[i].amount
@@ -504,7 +504,7 @@ namespace rct {
FIELD(outPk)
VARINT_FIELD(txnFee)
FIELD(p_r)
if (type == RCTTypeSalviumZero || type == RCTTypeSalviumOne)
if (type == RCTTypeSalviumZero)
{
FIELD(salvium_data)
}
@@ -673,7 +673,6 @@ namespace rct {
FIELD(bulletproofs_plus)
FIELD(MGs)
FIELD(CLSAGs)
FIELD(TCLSAGs)
FIELD(pseudoOuts)
END_SERIALIZE()
};
+6 -73
View File
@@ -28,7 +28,6 @@
//
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
#include <regex>
#include <boost/preprocessor/stringize.hpp>
#include <boost/uuid/nil_generator.hpp>
#include <boost/filesystem.hpp>
@@ -1433,7 +1432,7 @@ namespace cryptonote
RPC_TRACKER(start_mining);
CHECK_CORE_READY();
cryptonote::address_parse_info info;
if(!get_account_address_from_str(info, m_core.get_nettype(), req.miner_address))
if(!get_account_address_from_str(info, nettype(), req.miner_address))
{
res.status = "Failed, wrong address";
LOG_PRINT_L0(res.status);
@@ -1446,17 +1445,6 @@ namespace cryptonote
return true;
}
const uint8_t version = m_core.get_blockchain_storage().get_current_hard_fork_version();
if (info.is_carrot && version < HF_VERSION_CARROT) {
res.status = "Mining to Carrot wallet address, but Carrot isn't supported yet";
LOG_PRINT_L0(res.status);
return true;
} else if (!info.is_carrot && version >= HF_VERSION_CARROT) {
res.status = "Mining to CryptoNote wallet address, but Carrot wallet address is required";
LOG_PRINT_L0(res.status);
return true;
}
unsigned int concurrency_count = boost::thread::hardware_concurrency() * 4;
// if we couldn't detect threads, set it to a ridiculously high number
@@ -1871,14 +1859,15 @@ namespace cryptonote
bool core_rpc_server::get_block_template(const account_public_address &address, const crypto::hash *prev_block, const cryptonote::blobdata &extra_nonce, size_t &reserved_offset, cryptonote::difficulty_type &difficulty, uint64_t &height, uint64_t &expected_reward, block &b, uint64_t &seed_height, crypto::hash &seed_hash, crypto::hash &next_seed_hash, epee::json_rpc::error &error_resp)
{
b = boost::value_initialized<cryptonote::block>();
crypto::public_key tx_pub_key = crypto::null_pkey;
if(!m_core.get_block_template(b, prev_block, address, difficulty, height, expected_reward, extra_nonce, seed_height, seed_hash, tx_pub_key))
if(!m_core.get_block_template(b, prev_block, address, difficulty, height, expected_reward, extra_nonce, seed_height, seed_hash))
{
error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
error_resp.message = "Internal error: failed to create block template";
LOG_ERROR("Failed to create block template");
return false;
}
blobdata block_blob = t_serializable_object_to_blob(b);
crypto::public_key tx_pub_key = cryptonote::get_tx_pub_key_from_extra(b.miner_tx);
if(tx_pub_key == crypto::null_pkey)
{
error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
@@ -1886,7 +1875,7 @@ namespace cryptonote
LOG_ERROR("Failed to get tx pub key in coinbase extra");
return false;
}
blobdata block_blob = t_serializable_object_to_blob(b);
uint64_t next_height;
crypto::rx_seedheights(height, &seed_height, &next_height);
if (next_height != seed_height)
@@ -1969,17 +1958,6 @@ namespace cryptonote
return false;
}
const uint8_t version = m_core.get_blockchain_storage().get_current_hard_fork_version();
if (info.is_carrot && version < HF_VERSION_CARROT) {
error_resp.code = CORE_RPC_ERROR_CODE_INVALID_CLIENT;
error_resp.message = "Mining to Carrot wallet address, but Carrot isn't supported yet";
return false;
} else if (!info.is_carrot && version >= HF_VERSION_CARROT) {
error_resp.code = CORE_RPC_ERROR_CODE_INVALID_CLIENT;
error_resp.message = "Mining to CryptoNote wallet address, but Carrot wallet address is required";
return false;
}
block b;
cryptonote::blobdata blob_reserve;
size_t reserved_offset;
@@ -3045,52 +3023,6 @@ namespace cryptonote
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
bool core_rpc_server::on_get_tokens(const COMMAND_RPC_GET_TOKENS::request& req, COMMAND_RPC_GET_TOKENS::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx)
{
PERF_TIMER(on_get_tokens);
std::map<std::string, cryptonote::token_metadata_t> tokens = m_core.get_blockchain_storage().get_db().get_tokens();
for (const auto &token: tokens) {
if (req.filter == "") {
// Match anything
res.tokens.push_back(token.first);
} else if (token.first.find(req.filter) != std::string::npos) {
// Match ticker
res.tokens.push_back(token.first);
} else if (token.second.token.type() == typeid(cryptonote::sal_token_t)) {
// Check SAL tokens
if (boost::get<cryptonote::sal_token_t>(token.second.token).name.find(req.filter) != std::string::npos) {
// Match name
res.tokens.push_back(token.first);
}
}
}
res.status = CORE_RPC_STATUS_OK;
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
bool core_rpc_server::on_get_token_info(const COMMAND_RPC_GET_TOKEN_INFO::request& req, COMMAND_RPC_GET_TOKEN_INFO::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx)
{
PERF_TIMER(on_token_info);
std::map<std::string, cryptonote::token_metadata_t> tokens = m_core.get_blockchain_storage().get_db().get_tokens();
if (tokens.count(req.asset_type) == 0) {
res.status = "Token not found";
return true;
}
res.token = tokens[req.asset_type];
if (res.token.token.type() == typeid(cryptonote::erc_token_t)) {
res.token_type = TOKEN_TYPE_ERC20;
res.erc_token = boost::get<cryptonote::erc_token_t>(res.token.token);
} else if (res.token.token.type() == typeid(cryptonote::sal_token_t)) {
res.token_type = TOKEN_TYPE_SAL;
res.sal_token = boost::get<cryptonote::sal_token_t>(res.token.token);
}
res.status = CORE_RPC_STATUS_OK;
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
bool core_rpc_server::on_get_yield_info(const COMMAND_RPC_GET_YIELD_INFO::request& req, COMMAND_RPC_GET_YIELD_INFO::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx)
{
CHECK_CORE_READY();
@@ -3154,6 +3086,7 @@ namespace cryptonote
CHECK_PAYMENT(req, res, COST_PER_FEE_ESTIMATE);
const uint8_t version = m_core.get_blockchain_storage().get_current_hard_fork_version();
m_core.get_blockchain_storage().get_dynamic_base_fee_estimate_2021_scaling(req.grace_blocks, res.fees);
res.fee = res.fees[0];
res.quantization_mask = Blockchain::get_fee_quantization_mask();
-4
View File
@@ -175,8 +175,6 @@ namespace cryptonote
MAP_JON_RPC_WE_IF("get_coinbase_tx_sum", on_get_coinbase_tx_sum, COMMAND_RPC_GET_COINBASE_TX_SUM, !m_restricted)
MAP_JON_RPC_WE("get_supply_info", on_get_supply_info, COMMAND_RPC_GET_SUPPLY_INFO)
MAP_JON_RPC_WE("get_yield_info", on_get_yield_info, COMMAND_RPC_GET_YIELD_INFO)
MAP_JON_RPC_WE("get_tokens", on_get_tokens, COMMAND_RPC_GET_TOKENS)
MAP_JON_RPC_WE("get_token_info", on_get_token_info, COMMAND_RPC_GET_TOKEN_INFO)
MAP_JON_RPC_WE("get_fee_estimate", on_get_base_fee_estimate, COMMAND_RPC_GET_BASE_FEE_ESTIMATE)
MAP_JON_RPC_WE_IF("get_alternate_chains",on_get_alternate_chains, COMMAND_RPC_GET_ALTERNATE_CHAINS, !m_restricted)
MAP_JON_RPC_WE_IF("relay_tx", on_relay_tx, COMMAND_RPC_RELAY_TX, !m_restricted)
@@ -256,8 +254,6 @@ namespace cryptonote
bool on_get_coinbase_tx_sum(const COMMAND_RPC_GET_COINBASE_TX_SUM::request& req, COMMAND_RPC_GET_COINBASE_TX_SUM::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
bool on_get_supply_info(const COMMAND_RPC_GET_SUPPLY_INFO::request& req, COMMAND_RPC_GET_SUPPLY_INFO::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
bool on_get_yield_info(const COMMAND_RPC_GET_YIELD_INFO::request& req, COMMAND_RPC_GET_YIELD_INFO::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
bool on_get_tokens(const COMMAND_RPC_GET_TOKENS::request& req, COMMAND_RPC_GET_TOKENS::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
bool on_get_token_info(const COMMAND_RPC_GET_TOKEN_INFO::request& req, COMMAND_RPC_GET_TOKEN_INFO::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
bool on_get_base_fee_estimate(const COMMAND_RPC_GET_BASE_FEE_ESTIMATE::request& req, COMMAND_RPC_GET_BASE_FEE_ESTIMATE::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
bool on_get_alternate_chains(const COMMAND_RPC_GET_ALTERNATE_CHAINS::request& req, COMMAND_RPC_GET_ALTERNATE_CHAINS::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
bool on_relay_tx(const COMMAND_RPC_RELAY_TX::request& req, COMMAND_RPC_RELAY_TX::response& res, epee::json_rpc::error& error_resp, const connection_context *ctx = NULL);
-70
View File
@@ -1488,76 +1488,6 @@ namespace cryptonote
typedef epee::misc_utils::struct_init<response_t> response;
};
struct COMMAND_RPC_GET_TOKENS
{
struct request_t
{
std::string filter;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE_OPT(filter, (std::string)"")
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<request_t> request;
struct response_t
{
std::string status;
std::vector<std::string> tokens;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(status)
KV_SERIALIZE(tokens)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<response_t> response;
};
struct COMMAND_RPC_GET_TOKEN_INFO
{
struct request_t
{
std::string asset_type;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(asset_type)
END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<request_t> request;
struct response_t
{
std::string status;
std::string asset_type;
uint8_t token_type; // erc20 or sal
cryptonote::token_metadata_t token;
cryptonote::erc_token_t erc_token;
cryptonote::sal_token_t sal_token;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(status)
KV_SERIALIZE(token_type)
KV_SERIALIZE(token.version)
KV_SERIALIZE(token.asset_type)
if (token_type == TOKEN_TYPE_ERC20) {
KV_SERIALIZE(erc_token)
token.token = erc_token;
} else {
KV_SERIALIZE(sal_token)
token.token = sal_token;
}
END_KV_SERIALIZE_MAP()
//BEGIN_KV_SERIALIZE_MAP()
//KV_SERIALIZE(status)
//KV_SERIALIZE(token)
//KV_SERIALIZE(asset_type)
//KV_SERIALIZE(sal_token)
//KV_SERIALIZE(erc_token)
//END_KV_SERIALIZE_MAP()
};
typedef epee::misc_utils::struct_init<response_t> response;
};
struct peer {
uint64_t id;
std::string host;

Some files were not shown because too many files have changed in this diff Show More