Skip to content

Commit f5b91c6

Browse files
committed
Output distribution checks
1 parent 9092a35 commit f5b91c6

2 files changed

Lines changed: 45 additions & 2 deletions

File tree

src/wallet/wallet2.cpp

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,10 @@ using namespace cryptonote;
147147
#define DEFAULT_UNLOCK_TIME (CRYPTONOTE_DEFAULT_TX_SPENDABLE_AGE * DIFFICULTY_TARGET_V2)
148148
#define RECENT_SPEND_WINDOW (50 * DIFFICULTY_TARGET_V2)
149149

150+
#define OUTPUT_DISTRIBUTION_CHECKPOINT_HEIGHT 2414180
151+
#define OUTPUT_DISTRIBUTION_CHECKPOINT_HASH "063e190b5230a11f33d7b448f218bd15bc578a8ec4f0f0875229f96283f61b44"
152+
#define OUTPUT_DISTRIBUTION_MAX_OUTPUT_SUM 100000000
153+
150154
static const std::string MULTISIG_SIGNATURE_MAGIC = "SigMultisigPkV1";
151155
static const std::string MULTISIG_EXTRA_INFO_MAGIC = "MultisigxV1";
152156

@@ -3797,6 +3801,37 @@ bool wallet2::cache_rct_distribution(uint64_t from_height)
37973801

37983802
return true;
37993803
}
3804+
3805+
void wallet2::check_rct_distribution() {
3806+
crypto::hash checkpoint_hash;
3807+
bool r = epee::string_tools::hex_to_pod(OUTPUT_DISTRIBUTION_CHECKPOINT_HASH, checkpoint_hash);
3808+
THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "Invalid output distribution checkpoint hash");
3809+
3810+
THROW_WALLET_EXCEPTION_IF(m_rct_offsets.size() < OUTPUT_DISTRIBUTION_CHECKPOINT_HEIGHT, error::wallet_internal_error, "Output distribution size too small");
3811+
THROW_WALLET_EXCEPTION_IF(m_rct_offsets.size() > (m_blockchain.size() + 10), error::wallet_internal_error, "Output distribution size too big");
3812+
3813+
// Create a new rct_offsets object with distribution up to checkpoint height
3814+
std::vector<uint64_t> rct_offsets_slice;
3815+
rct_offsets_slice.reserve(OUTPUT_DISTRIBUTION_CHECKPOINT_HEIGHT);
3816+
for (size_t i = m_rct_offsets.start_height(); i < OUTPUT_DISTRIBUTION_CHECKPOINT_HEIGHT; i++) {
3817+
rct_offsets_slice.push_back(m_rct_offsets[i]);
3818+
}
3819+
rct_offsets rct_offsets_to_hash;
3820+
rct_offsets_to_hash.init(m_rct_offsets.start_height(), rct_offsets_slice);
3821+
3822+
blobdata rct_offsets_blob = t_serializable_object_to_blob(rct_offsets_to_hash);
3823+
crypto::hash offsets_hash;
3824+
bool hash_result = get_object_hash(rct_offsets_blob, offsets_hash);
3825+
3826+
THROW_WALLET_EXCEPTION_IF(!hash_result, error::wallet_internal_error, "Unable to hash output distribution");
3827+
THROW_WALLET_EXCEPTION_IF(offsets_hash != checkpoint_hash, error::wallet_internal_error, "Output distribution hash does not match checkpoint hash. "
3828+
"Offset hash: " + epee::string_tools::pod_to_hex(offsets_hash) +
3829+
", Checkpoint hash: " + epee::string_tools::pod_to_hex(checkpoint_hash));
3830+
3831+
// sanity check
3832+
THROW_WALLET_EXCEPTION_IF(m_rct_offsets.offsets().back() >= OUTPUT_DISTRIBUTION_MAX_OUTPUT_SUM, error::wallet_internal_error, "Unrealistic number of outputs in output distribution");
3833+
}
3834+
38003835
//----------------------------------------------------------------------------------------------------
38013836
void wallet2::detach_blockchain(uint64_t height, std::map<std::pair<uint64_t, uint64_t>, size_t> *output_tracker_cache)
38023837
{
@@ -8723,8 +8758,10 @@ void wallet2::get_outs(std::vector<std::vector<tools::wallet2::get_outs_entry>>
87238758
COMMAND_RPC_GET_OUTPUTS_BIN::response daemon_resp = AUTO_VAL_INIT(daemon_resp);
87248759

87258760
std::unique_ptr<gamma_picker> gamma;
8726-
if (has_rct_distribution)
8727-
gamma.reset(new gamma_picker(m_rct_offsets.offsets()));
8761+
if (has_rct_distribution) {
8762+
check_rct_distribution();
8763+
gamma.reset(new gamma_picker(m_rct_offsets.offsets()));
8764+
}
87288765

87298766
size_t num_selected_transfers = 0;
87308767
for(size_t idx: selected_transfers)

src/wallet/wallet2.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,11 @@ namespace tools
203203
void clear() { m_start_height = 0, m_offsets.clear(); }
204204
std::vector<uint64_t>& offsets() {return m_offsets;}
205205

206+
BEGIN_SERIALIZE_OBJECT()
207+
VARINT_FIELD(m_start_height)
208+
FIELD(m_offsets)
209+
END_SERIALIZE()
210+
206211
private:
207212
size_t m_start_height;
208213
std::vector<uint64_t> m_offsets;
@@ -1609,6 +1614,7 @@ namespace tools
16091614
boost::shared_mutex m_transfers_mutex;
16101615

16111616
bool cache_rct_distribution(uint64_t from_height);
1617+
void check_rct_distribution();
16121618

16131619
private:
16141620
/*!

0 commit comments

Comments
 (0)