Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial tx_history #13

Draft
wants to merge 22 commits into
base: seraphis_wallet
Choose a base branch
from
Draft
Changes from 2 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
e99b422
add key exchange round booster to multisig_account
UkoeHB Mar 3, 2022
0b10b72
seraphis mega squash commit [initial commit - 05/15/2023]; see seraph…
UkoeHB Sep 3, 2021
dbd8c9c
async: explicit task constructors
UkoeHB May 15, 2023
f3dda41
rebase fixes
UkoeHB May 16, 2023
fb30680
make JamtisDestinationV1 serializable (#11)
DangerousFreedom1984 Jun 8, 2023
7e9203f
compile fix
UkoeHB Jul 14, 2023
ea9fa07
clarify SpBasicEnoteRecordV1 docs; add async unit test for custom joins
UkoeHB Aug 31, 2023
eeca802
remove broken perf tests
UkoeHB Sep 10, 2023
0a14382
Merge pull request #9 from seraphis-migration/seraphis_lib
rbrunner7 Sep 22, 2023
ad1cb23
common: add Jamtis base32 encoding
jeffro256 Sep 10, 2023
d7e89f7
Merge pull request #6 from jeffro256/jamtis_base32_sm
rbrunner7 Sep 26, 2023
774fdb9
fix base32 unit_test with single quote
Sep 27, 2023
7b3443e
Merge pull request #10 from DangerousFreedom1984/base32_quotes
rbrunner7 Sep 29, 2023
3149f3b
seraphis_impl: jamtis base32 checksums
jeffro256 Sep 11, 2023
9f0a03c
Merge pull request #7 from jeffro256/jamtis_checksum_sm
rbrunner7 Sep 29, 2023
0a92514
add operator== to JamtisPaymentProposals (#18)
DangerousFreedom1984 Oct 18, 2023
8868b2d
make JamtisPaymentProposal serializable (#21)
DangerousFreedom1984 Oct 23, 2023
b6c52f0
util to convert legacy outputs to seraphis lib compatible enotes (#22)
j-berman Oct 24, 2023
f5915c6
container_helpers: is_sorted_and_unique 3x fewer comparison ops (#19)
Oct 24, 2023
702e5b1
Merge pull request #12 from seraphis-migration/seraphis_lib
rbrunner7 Oct 25, 2023
eafafc8
initial tx_history
Oct 28, 2023
1669933
remove encrypt_file
Oct 28, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/seraphis_impl/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -31,6 +31,7 @@ set(seraphis_impl_sources
enote_store.cpp
enote_store_payment_validator.cpp
enote_store_utils.cpp
jamtis_address_checksum.cpp
legacy_ki_import_tool.cpp
scan_ledger_chunk_async.cpp
scan_process_basic.cpp
144 changes: 144 additions & 0 deletions src/seraphis_impl/jamtis_address_checksum.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
// Copyright (c) 2022, 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.

#include <cstdint>
#include <cstring>
#include <stdexcept>

#include "jamtis_address_checksum.h"

namespace
{
static constexpr const uint64_t GEN[5] = {0x1ae45cd581, 0x359aad8f02, 0x61754f9b24, 0xc2ba1bb368, 0xcd2623e3f0};

static constexpr const uint64_t M = 0xffffffffff;

// pass c=1 to start the chain
static bool jamtis_checksum_polymod(const char *encoded_data, size_t encoded_data_size, uint64_t &c)
{
for (const char *p = encoded_data; p < encoded_data + encoded_data_size; ++p)
{
const uint64_t v = (base32::JAMTIS_INVERTED_ALPHABET[static_cast<size_t>(*p)]);
if (v == base32::IGNC) // if character to ignore
continue;
else if (v >= 32) // if invalid character in input string
return false;

// voodoo magic
const uint64_t b = c >> 35;
c = ((c & 0x07ffffffff) << 5) ^ v;
for (uint64_t i = 0; i < 5; ++i)
if ((b >> i) & 1)
c ^= GEN[i];
}

return true;
}

// optimized version for updating c with 8-bytes of GF[0] when creating checksums
static inline uint64_t jamtis_checksum_polymod_zerosum(uint64_t c)
{
for (int j = 0; j < sp::jamtis::ADDRESS_CHECKSUM_SIZE_ENCODED; ++j)
{
// voodoo magic with v=0
const uint64_t b = c >> 35;
c = ((c & 0x07ffffffff) << 5);
for (uint64_t i = 0; i < 5; ++i)
if ((b >> i) & 1)
c ^= GEN[i];
}
return c;
}
} // anonymous namespace

namespace sp
{
namespace jamtis
{
bool create_address_checksum(const char *encoded_data,
size_t encoded_data_size,
char checksum_out[ADDRESS_CHECKSUM_SIZE_ENCODED])
{
static_assert(ADDRESS_CHECKSUM_SIZE_ENCODED <= 8, "integer underflow will occur");

// calculate checksum
uint64_t c = 1;
if (!jamtis_checksum_polymod(encoded_data, encoded_data_size, c))
return false;
c = jamtis_checksum_polymod_zerosum(c) ^ M;

// write checksum to output
for (uint64_t i = 0; i < ADDRESS_CHECKSUM_SIZE_ENCODED; ++i)
checksum_out[i] = base32::JAMTIS_ALPHABET[(c >> (5 * (7 - i))) & 31];

return true;
}

std::string create_address_checksum(const std::string &encoded_data)
{
std::string res(ADDRESS_CHECKSUM_SIZE_ENCODED, '\0');
if (!create_address_checksum(encoded_data.data(), encoded_data.size(), &res[0]))
throw std::runtime_error("couldn't create Jamtis checksum due to invalid char in input");
return res;
}

bool verify_address_checksum(const char *encoded_data,
size_t encoded_data_size,
const char checksum[ADDRESS_CHECKSUM_SIZE_ENCODED])
{
// calculate checksum
uint64_t c = 1;
if (!jamtis_checksum_polymod(encoded_data, encoded_data_size, c))
return false;
if (!jamtis_checksum_polymod(checksum, ADDRESS_CHECKSUM_SIZE_ENCODED, c))
return false;

// verify
return M == c;
}

bool verify_address_checksum(const std::string &encoded_data, const std::string &checksum)
{
if (checksum.size() != ADDRESS_CHECKSUM_SIZE_ENCODED)
return false;

return verify_address_checksum(encoded_data.data(), encoded_data.size(), checksum.data());
}

bool verify_address_checksum(const std::string &encoded_data_and_checksum)
{
if (encoded_data_and_checksum.size() < ADDRESS_CHECKSUM_SIZE_ENCODED)
return false;

const size_t data_len = encoded_data_and_checksum.size() - ADDRESS_CHECKSUM_SIZE_ENCODED;
return verify_address_checksum(encoded_data_and_checksum.data(),
data_len,
encoded_data_and_checksum.data() + data_len);
}
} // namespace jamtis
} // namespace sp
95 changes: 95 additions & 0 deletions src/seraphis_impl/jamtis_address_checksum.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
// Copyright (c) 2022, 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.

/**
* @brief: utilties for creating and verifying checksums on base32 encoded data
*
* This code uses tevador's GF32 checksum algorithm and can make checksums that recognize =< 5
* corrupted characters on any base32 encoded data, regardless of alphabet.
*
* spec here: https://gist.github.com/tevador/50160d160d24cfc6c52ae02eb3d17024#63-checksum
*/

#pragma once

#include <cstddef>

#include "common/base32.h"

namespace sp
{
namespace jamtis
{
static constexpr const size_t ADDRESS_CHECKSUM_SIZE_ENCODED = 8;

/**
* brief: create_address_checksum - create an 8 character checksum on base32 encoded data
* param: encoded_data - base32 encoded data
* param: encoded_data_size -
* outparam: checksum_out - eight byte checksum, encoded with the same encoding as input buffer
* return: true on success, false if input string is invalid
*/
bool create_address_checksum(const char *encoded_data,
size_t encoded_data_size,
char checksum_out[ADDRESS_CHECKSUM_SIZE_ENCODED]);

/**
* brief: create_address_checksum - create an 8 character checksum on base32 encoded data
* param: encoded_data - base32 encoded data
* return: 8 character checksum string
* throw: std::runtime_error if encoded_data contains invalid characters
*/
std::string create_address_checksum(const std::string &encoded_data);

/**
* brief: verify_address_checksum - check whether a checksum verifies for given base32 encoded data
* param: encoded_data - base32 encoded data
* param: encoded_data_size -
* param: checksum - eight byte checksum, encoded with the same encoding as input buffer
* return: true on verification success, false if input string is invalid or checksum is bad
*/
bool verify_address_checksum(const char *encoded_data,
size_t encoded_data_size,
const char checksum[ADDRESS_CHECKSUM_SIZE_ENCODED]);

/**
* brief: verify_address_checksum - check whether a checksum verifies for given base32 encoded data
* param: encoded_data - base32 encoded data
* param: checksum - eight byte checksum, encoded as base32
* return: true on verification success, false if input string is invalid or checksum is bad
*/
bool verify_address_checksum(const std::string &encoded_data, const std::string &checksum);

/**
* brief: verify_address_checksum - check whether a checksum verifies for given base32 encoded data
* param: encoded_data_and_checksum - base32 encoded data with 8 byte checksum appended to the end
* return: true on verification success, false if input string is invalid or checksum is bad
*/
bool verify_address_checksum(const std::string &encoded_data_and_checksum);
} // namespace jamtis
} // namespace sp
27 changes: 27 additions & 0 deletions tests/unit_tests/seraphis_integration.cpp
Original file line number Diff line number Diff line change
@@ -50,6 +50,7 @@
#include "seraphis_crypto/sp_composition_proof.h"
#include "seraphis_crypto/sp_crypto_utils.h"
#include "seraphis_impl/enote_store_utils.h"
#include "seraphis_impl/jamtis_address_checksum.h"
#include "seraphis_impl/tx_fee_calculator_squashed_v1.h"
#include "seraphis_impl/tx_input_selection_output_context_v1.h"
#include "seraphis_main/contextual_enote_record_utils.h"
@@ -77,6 +78,16 @@ using namespace jamtis;
using namespace sp::mocks;
using namespace jamtis::mocks;

static std::string create_random_base32_string(size_t len)
{
std::string s;
s.resize(len);
srand(crypto::rand<unsigned int>());
for (int i = 0; i < s.size(); ++i)
s[i] = base32::JAMTIS_ALPHABET[rand() % 32];
return s;
}

//-------------------------------------------------------------------------------------------------------------------
TEST(seraphis_integration, txtype_squashed_v1)
{
@@ -239,3 +250,19 @@ TEST(seraphis_integration, txtype_squashed_v1)
ledger_context);
}
//-------------------------------------------------------------------------------------------------------------------
TEST(seraphis_integration, jamtis_checksum_create_verify)
{
for (size_t datalen = 0; datalen < 250; ++datalen)
{
for (size_t i = 0; i < 10; ++i)
{
const std::string random_b32 = create_random_base32_string(datalen);

char checksum[sp::jamtis::ADDRESS_CHECKSUM_SIZE_ENCODED];
EXPECT_TRUE(sp::jamtis::create_address_checksum(random_b32.data(), random_b32.size(), checksum));

EXPECT_TRUE(sp::jamtis::verify_address_checksum(random_b32.data(), random_b32.size(), checksum));
}
}
}
//-------------------------------------------------------------------------------------------------------------------