diff --git a/src/libspark/coin.cpp b/src/libspark/coin.cpp index 27ca2f56e0..cb5ecc17c4 100644 --- a/src/libspark/coin.cpp +++ b/src/libspark/coin.cpp @@ -63,7 +63,8 @@ Coin::Coin( MintCoinRecipientData r; r.d = address.get_d(); r.k = k; - r.memo = std::string(padded_memo.begin(), padded_memo.end()); + r.memo_length = (uint8_t) memo.size(); + r.padded_memo = std::string(padded_memo.begin(), padded_memo.end()); CDataStream r_stream(SER_NETWORK, PROTOCOL_VERSION); r_stream << r; this->r_ = AEAD::encrypt(address.get_Q1()*SparkUtils::hash_k(k), "Mint coin data", r_stream); @@ -73,7 +74,8 @@ Coin::Coin( r.v = v; r.d = address.get_d(); r.k = k; - r.memo = std::string(padded_memo.begin(), padded_memo.end()); + r.memo_length = (uint8_t) memo.size(); + r.padded_memo = std::string(padded_memo.begin(), padded_memo.end()); CDataStream r_stream(SER_NETWORK, PROTOCOL_VERSION); r_stream << r; this->r_ = AEAD::encrypt(address.get_Q1()*SparkUtils::hash_k(k), "Spend coin data", r_stream); @@ -131,10 +133,15 @@ IdentifiedCoinData Coin::identify(const IncomingViewKey& incoming_view_key) { throw std::runtime_error("Unable to identify coin"); } + // Check that the memo length is valid + if (r.memo_length > this->params->get_memo_bytes()) { + throw std::runtime_error("Unable to identify coin"); + } + data.d = r.d; data.v = this->v; data.k = r.k; - data.memo = r.memo; + data.memo = std::string(r.padded_memo.begin(), r.padded_memo.begin() + r.memo_length); } else { SpendCoinRecipientData r; @@ -146,10 +153,15 @@ IdentifiedCoinData Coin::identify(const IncomingViewKey& incoming_view_key) { throw std::runtime_error("Unable to identify coin"); } + // Check that the memo length is valid + if (r.memo_length > this->params->get_memo_bytes()) { + throw std::runtime_error("Unable to identify coin"); + } + data.d = r.d; data.v = r.v; data.k = r.k; - data.memo = r.memo; + data.memo = std::string(r.padded_memo.begin(), r.padded_memo.begin() + r.memo_length); } // Validate the coin diff --git a/src/libspark/coin.h b/src/libspark/coin.h index e8e85c1ecd..3af6624821 100644 --- a/src/libspark/coin.h +++ b/src/libspark/coin.h @@ -33,7 +33,8 @@ struct RecoveredCoinData { struct MintCoinRecipientData { std::vector d; // encrypted diversifier Scalar k; // nonce - std::string memo; // memo + uint8_t memo_length; // memo length + std::string padded_memo; // padded memo ADD_SERIALIZE_METHODS; @@ -41,7 +42,8 @@ struct MintCoinRecipientData { inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(d); READWRITE(k); - READWRITE(memo); + READWRITE(memo_length); + READWRITE(padded_memo); } }; @@ -50,7 +52,8 @@ struct SpendCoinRecipientData { uint64_t v; // value std::vector d; // encrypted diversifier Scalar k; // nonce - std::string memo; // memo + uint8_t memo_length; // memo length + std::string padded_memo; // padded memo ADD_SERIALIZE_METHODS; @@ -59,7 +62,8 @@ struct SpendCoinRecipientData { READWRITE(v); READWRITE(d); READWRITE(k); - READWRITE(memo); + READWRITE(memo_length); + READWRITE(padded_memo); } }; diff --git a/src/libspark/test/coin_test.cpp b/src/libspark/test/coin_test.cpp index 522ea29f2a..c162ecdc9c 100644 --- a/src/libspark/test/coin_test.cpp +++ b/src/libspark/test/coin_test.cpp @@ -57,8 +57,8 @@ BOOST_AUTO_TEST_CASE(mint_identify_recover) BOOST_CHECK_EQUAL_COLLECTIONS(i_data.d.begin(), i_data.d.end(), address.get_d().begin(), address.get_d().end()); BOOST_CHECK_EQUAL(i_data.v, v); BOOST_CHECK_EQUAL(i_data.k, k); - BOOST_CHECK_EQUAL(strcmp(memo.c_str(), i_data.memo.c_str()), 0); // compare strings in a lexicographical manner, as we pad the memo in the coin - BOOST_CHECK_EQUAL(i_data.memo.size(), params->get_memo_bytes()); // check that it is padded + BOOST_CHECK_EQUAL(i_data.memo, memo); + // Recover coin RecoveredCoinData r_data = coin.recover(full_view_key, i_data); BOOST_CHECK_EQUAL( @@ -105,8 +105,7 @@ BOOST_AUTO_TEST_CASE(spend_identify_recover) BOOST_CHECK_EQUAL_COLLECTIONS(i_data.d.begin(), i_data.d.end(), address.get_d().begin(), address.get_d().end()); BOOST_CHECK_EQUAL(i_data.v, v); BOOST_CHECK_EQUAL(i_data.k, k); - BOOST_CHECK_EQUAL(strcmp(memo.c_str(), i_data.memo.c_str()), 0); // compare strings in a lexicographical manner, as we pad the memo in the coin - BOOST_CHECK_EQUAL(i_data.memo.size(), params->get_memo_bytes()); // check that it is padded + BOOST_CHECK_EQUAL(i_data.memo, memo); // Recover coin RecoveredCoinData r_data = coin.recover(full_view_key, i_data);