Skip to content

Commit df8d1d2

Browse files
committed
Add support for carrot (legacy, view-incoming, and view-balance keys). WIP
1 parent 204007f commit df8d1d2

36 files changed

Lines changed: 3040 additions & 306 deletions

CMakeLists.txt

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,18 +81,23 @@ set(MONERO_LIBRARIES
8181
common
8282
lmdb
8383
device
84-
cncrypto
85-
randomx
8684
epee
8785
easylogging
8886
version
8987
wallet-crypto
88+
fcmp_pp
89+
wallet
90+
carrot_impl
91+
carrot_core
92+
cncrypto
93+
randomx
94+
mx25519
9095
)
9196

9297
set(MONERO_OPTIONAL wallet-crypto)
9398

9499
if (MONERO_BUILD_DIR)
95-
100+
list(APPEND MONERO_LIBRARIES "fcmp_pp_rust")
96101
set(MONERO_SEARCH_PATHS
97102
"/contrib/epee/src"
98103
"/external/db_drivers/liblmdb"
@@ -101,6 +106,7 @@ if (MONERO_BUILD_DIR)
101106
"/src/crypto"
102107
"/src/crypto/wallet"
103108
"/src/cryptonote_basic"
109+
"/src/fcmp_pp/fcmp_pp_rust"
104110
"/src/lmdb"
105111
"/src/ringct"
106112
"/src/rpc"
@@ -161,7 +167,7 @@ if (MONERO_BUILD_DIR)
161167
endif()
162168

163169
foreach (LIB ${MONERO_LIBRARIES})
164-
find_library(LIB_PATH NAMES "${LIB}" PATHS ${MONERO_BUILD_DIR} PATH_SUFFIXES "/src/${LIB}" "external/${LIB}" ${MONERO_SEARCH_PATHS} NO_DEFAULT_PATH)
170+
find_library(LIB_PATH NAMES "${LIB}" PATHS ${MONERO_BUILD_DIR} PATH_SUFFIXES "/src/${LIB}" "/lib" "external/${LIB}" ${MONERO_SEARCH_PATHS} NO_DEFAULT_PATH)
165171

166172
list(FIND MONERO_OPTIONAL "${LIB}" LIB_OPTIONAL)
167173
if (NOT LIB_PATH)
@@ -280,6 +286,7 @@ set_property(TARGET monero::libraries PROPERTY
280286
"${MONERO_SOURCE_DIR}/external/easylogging++"
281287
"${MONERO_SOURCE_DIR}/external/rapidjson/include"
282288
"${MONERO_SOURCE_DIR}/external/supercop/include"
289+
"${MONERO_SOURCE_DIR}/external/mx25519/include"
283290
"${MONERO_SOURCE_DIR}/src"
284291
)
285292

Dockerfile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ RUN apt-get update \
1515
RUN apt-get install --no-install-recommends -y \
1616
build-essential \
1717
ca-certificates \
18+
cargo \
1819
ccache \
1920
cmake \
2021
doxygen \
@@ -104,7 +105,7 @@ RUN git clone --recursive \
104105
*) echo "Dockerfile does not support this platform"; exit 1 ;; \
105106
esac \
106107
# Build only monerod binary using number of available threads
107-
&& cd /monero && nice -n 19 ionice -c2 -n7 make -j${NPROC:-$(nproc)} -C build/release daemon lmdb_lib multisig
108+
&& cd /monero && nice -n 19 ionice -c2 -n7 make -j${NPROC:-$(nproc)} -C build/release daemon lmdb_lib multisig wallet
108109

109110
# Switch to monero-lws source directory
110111
WORKDIR /monero-lws

src/CMakeLists.txt

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,20 +57,20 @@ endif ()
5757
configure_file(lws_version.h.in "${CMAKE_BINARY_DIR}/generated_include/lws_version.h")
5858
include_directories("${CMAKE_BINARY_DIR}/generated_include")
5959

60-
add_subdirectory(lmdb)
61-
add_subdirectory(wire)
62-
add_subdirectory(db)
63-
add_subdirectory(net)
64-
add_subdirectory(rpc)
65-
add_subdirectory(util)
66-
6760
# For both the server and admin utility.
6861
set(monero-lws-common_sources config.cpp error.cpp)
6962
set(monero-lws-common_headers config.h error.h fwd.h)
7063

7164
add_library(monero-lws-common ${monero-lws-common_sources} ${monero-lws-common_headers})
7265
target_link_libraries(monero-lws-common monero::libraries)
7366

67+
add_subdirectory(lmdb)
68+
add_subdirectory(wire)
69+
add_subdirectory(db)
70+
add_subdirectory(net)
71+
add_subdirectory(rpc)
72+
add_subdirectory(util)
73+
7474
add_library(monero-lws-daemon-common rest_server.cpp scanner.cpp)
7575
target_include_directories(monero-lws-daemon-common PUBLIC ${ZMQ_INCLUDE_PATH})
7676
target_link_libraries(monero-lws-daemon-common

src/db/CMakeLists.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@
2626
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
2727
# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2828

29-
set(monero-lws-db_sources account.cpp data.cpp storage.cpp string.cpp)
30-
set(monero-lws-db_headers account.h data.h fwd.h storage.h string.h)
29+
set(monero-lws-db_sources account.cpp carrot.cpp data.cpp storage.cpp string.cpp)
30+
set(monero-lws-db_headers account.h carrot.h data.h fwd.h storage.h string.h)
3131

3232
add_library(monero-lws-db ${monero-lws-db_sources} ${monero-lws-db_headers})
3333
target_include_directories(monero-lws-db PUBLIC "${LMDB_INCLUDE}")
34-
target_link_libraries(monero-lws-db monero::libraries monero-lws-common monero-lws-lmdb monero-lws-wire-msgpack ${LMDB_LIB_PATH})
34+
target_link_libraries(monero-lws-db monero::libraries monero-lws-common monero-lws-lmdb monero-lws-wire-json monero-lws-wire-msgpack ${LMDB_LIB_PATH})

src/db/account.cpp

Lines changed: 102 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,16 @@
2929
#include <algorithm>
3030
#include <cstring>
3131

32+
#include "carrot_core/account_secrets.h"
3233
#include "common/error.h"
3334
#include "common/expect.h"
35+
#include "db/carrot.h"
3436
#include "db/data.h"
3537
#include "db/string.h"
38+
#include "error.h"
3639
#include "wire/adapted/crypto.h"
3740
#include "wire/adapted/pair.h"
41+
#include "wire/adapted/tuple.h"
3842
#include "wire/msgpack.h"
3943
#include "wire/vector.h"
4044
#include "wire/wrapper/trusted_array.h"
@@ -51,28 +55,53 @@ namespace lws
5155
return std::memcmp(std::addressof(lhs), std::addressof(rhs), sizeof(lhs)) < 0;
5256
}
5357
};
58+
59+
account::key_type get_type(const db::account_flags flags) noexcept
60+
{
61+
if (flags & db::account_flags::view_balance_key)
62+
return account::key_type::balance;
63+
return account::key_type::legacy;
64+
}
5465
}
5566

67+
WIRE_AS_INTEGER(account::key_type);
68+
5669
struct account::internal
5770
{
5871
internal()
59-
: address(), id(db::account_id::invalid), pubs{}, view_key{}
72+
: address(),
73+
id(db::account_id::invalid),
74+
pubs{},
75+
view_key{},
76+
balance_key{},
77+
type(account::key_type::legacy)
6078
{}
6179

6280
explicit internal(db::account const& source)
63-
: address(db::address_string(source.address)), id(source.id), pubs(source.address), view_key()
81+
: address(db::address_string(source.address)),
82+
id(source.id),
83+
pubs(source.address),
84+
view_key(),
85+
balance_key{},
86+
type(get_type(source.flags))
6487
{
6588
using inner_type =
6689
std::remove_reference<decltype(tools::unwrap(view_key))>::type;
6790

91+
crypto::secret_key& target = type == account::key_type::balance ?
92+
balance_key : view_key;
93+
6894
static_assert(std::is_standard_layout<db::view_key>(), "need standard layout source");
6995
static_assert(std::is_pod<inner_type>(), "need pod target");
70-
static_assert(sizeof(view_key) == sizeof(source.key), "different size keys");
96+
static_assert(sizeof(target) == sizeof(source.key), "different size keys");
7197
std::memcpy(
72-
std::addressof(tools::unwrap(view_key)),
98+
std::addressof(tools::unwrap(target)),
7399
std::addressof(source.key),
74100
sizeof(source.key)
75101
);
102+
103+
if (type == account::key_type::balance)
104+
::carrot::make_carrot_viewincoming_key(balance_key, view_key);
76105
}
77106

78107
void read_bytes(wire::msgpack_reader& source)
@@ -88,19 +117,24 @@ namespace lws
88117
WIRE_FIELD_ID(0, address),
89118
WIRE_FIELD_ID(1, id),
90119
WIRE_FIELD_ID(2, pubs),
91-
WIRE_FIELD_ID(3, view_key)
120+
WIRE_FIELD_ID(3, view_key),
121+
WIRE_FIELD_ID(4, balance_key),
122+
WIRE_FIELD_ID(5, type)
92123
);
93124
}
94125

95126
std::string address;
96127
db::account_id id;
97128
db::account_address pubs;
98129
crypto::secret_key view_key;
130+
crypto::secret_key balance_key;
131+
account::key_type type;
99132
};
100133

101-
account::account(std::shared_ptr<const internal> immutable, db::block_id height, std::vector<std::pair<db::output_id, db::address_index>> spendable, std::vector<crypto::public_key> pubs) noexcept
134+
account::account(std::shared_ptr<const internal> immutable, db::block_id height, std::vector<spendable_t> spendable, std::vector<balance_t> balance, std::vector<crypto::public_key> pubs) noexcept
102135
: immutable_(std::move(immutable))
103136
, spendable_(std::move(spendable))
137+
, balance_(std::move(balance))
104138
, pubs_(std::move(pubs))
105139
, spends_()
106140
, outputs_()
@@ -122,18 +156,20 @@ namespace lws
122156
wire::optional_field<2>("pubs_", wire::trusted_array(std::ref(self.pubs_))),
123157
wire::optional_field<3>("spends_", wire::trusted_array(std::ref(self.spends_))),
124158
wire::optional_field<4>("outputs_", wire::trusted_array(std::ref(self.outputs_))),
125-
WIRE_FIELD_ID(5, height_)
159+
WIRE_FIELD_ID(5, height_),
160+
wire::optional_field<6>("balance_", wire::trusted_array(std::ref(self.balance_)))
126161
);
127162
}
128163

129164
account::account() noexcept
130-
: immutable_(nullptr), spendable_(), pubs_(), spends_(), outputs_(), height_(db::block_id(0))
165+
: immutable_(nullptr), spendable_(), balance_(), pubs_(), spends_(), outputs_(), height_(db::block_id(0))
131166
{}
132167

133-
account::account(db::account const& source, std::vector<std::pair<db::output_id, db::address_index>> spendable, std::vector<crypto::public_key> pubs)
134-
: account(std::make_shared<internal>(source), source.scan_height, std::move(spendable), std::move(pubs))
168+
account::account(db::account const& source, std::vector<spendable_t> spendable, std::vector<balance_t> balance, std::vector<crypto::public_key> pubs)
169+
: account(std::make_shared<internal>(source), source.scan_height, std::move(spendable), std::move(balance), std::move(pubs))
135170
{
136171
std::sort(spendable_.begin(), spendable_.end());
172+
std::sort(balance_.begin(), balance_.end());
137173
std::sort(pubs_.begin(), pubs_.end(), sort_pubs{});
138174
}
139175

@@ -146,6 +182,7 @@ namespace lws
146182
map(source, *this, *immutable);
147183
immutable_ = std::move(immutable);
148184
std::sort(spendable_.begin(), spendable_.end());
185+
std::sort(balance_.begin(), balance_.end());
149186
std::sort(pubs_.begin(), pubs_.end(), sort_pubs{});
150187
}
151188

@@ -157,7 +194,7 @@ namespace lws
157194

158195
account account::clone() const
159196
{
160-
account result{immutable_, height_, spendable_, pubs_};
197+
account result{immutable_, height_, spendable_, balance_, pubs_};
161198
result.outputs_ = outputs_;
162199
result.spends_ = spends_;
163200
return result;
@@ -179,6 +216,13 @@ namespace lws
179216
return db::account_id::invalid;
180217
}
181218

219+
account::key_type account::type() const noexcept
220+
{
221+
if (immutable_)
222+
return immutable_->type;
223+
return key_type::legacy;
224+
}
225+
182226
std::string const& account::address() const
183227
{
184228
null_check();
@@ -209,29 +253,61 @@ namespace lws
209253
return immutable_->view_key;
210254
}
211255

212-
boost::optional<db::address_index> account::get_spendable(db::output_id const& id) const noexcept
256+
crypto::secret_key const& account::balance_key() const
257+
{
258+
null_check();
259+
return immutable_->balance_key;
260+
}
261+
262+
std::optional<db::address_index> account::get_spendable(db::output_id const& id) const noexcept
213263
{
214264
const auto searchable =
215-
std::make_pair(id, db::address_index{db::major_index::primary, db::minor_index::primary});
265+
std::make_pair(id, db::address_index::primary());
216266
const auto account =
217267
std::lower_bound(spendable_.begin(), spendable_.end(), searchable);
218268
if (account == spendable_.end() || account->first != id)
219-
return boost::none;
269+
return std::nullopt;
220270
return account->second;
221271
}
222272

273+
std::optional<std::pair<db::output_id, db::address_index>> account::get_spendable(crypto::key_image const& image) const noexcept
274+
{
275+
const auto searchable =
276+
std::make_tuple(image, std::uint64_t(0), db::address_index::primary());
277+
const auto account =
278+
std::lower_bound(balance_.begin(), balance_.end(), searchable);
279+
if (account == balance_.end() || std::get<0>(*account) != image)
280+
return std::nullopt;
281+
return std::make_pair(db::output_id{0, std::get<1>(*account)}, std::get<2>(*account));
282+
}
283+
223284
bool account::add_out(db::output const& out)
224285
{
225286
auto existing_pub = std::lower_bound(pubs_.begin(), pubs_.end(), out.pub, sort_pubs{});
226287
if (existing_pub != pubs_.end() && *existing_pub == out.pub)
227288
return false;
228289

229290
pubs_.insert(existing_pub, out.pub);
230-
auto spendable_value = std::make_pair(out.spend_meta.id, out.recipient);
231-
spendable_.insert(
232-
std::lower_bound(spendable_.begin(), spendable_.end(), spendable_value),
233-
spendable_value
234-
);
291+
292+
if (type() == key_type::balance)
293+
{
294+
const std::optional<crypto::key_image> image = get_image(out);
295+
if (!image)
296+
MONERO_THROW(error::crypto_failure, "Failed to generate carrot key image");
297+
auto elem = std::make_tuple(*image, out.spend_meta.id.low, out.recipient);
298+
balance_.insert(
299+
std::lower_bound(balance_.begin(), balance_.end(), elem),
300+
elem
301+
);
302+
}
303+
else if (!out.is_carrot())
304+
{
305+
auto spendable_value = std::make_pair(out.spend_meta.id, out.recipient);
306+
spendable_.insert(
307+
std::lower_bound(spendable_.begin(), spendable_.end(), spendable_value),
308+
spendable_value
309+
);
310+
}
235311
outputs_.push_back(out);
236312
return true;
237313
}
@@ -240,6 +316,12 @@ namespace lws
240316
{
241317
spends_.push_back(spend);
242318
}
243-
} // lws
244319

320+
std::optional<crypto::key_image> account::get_image(db::output const& out) const
321+
{
322+
if (!immutable_ || type() != key_type::balance)
323+
return std::nullopt;
324+
return carrot::get_image(out, immutable_->pubs, immutable_->balance_key);
325+
}
326+
} // lws
245327

0 commit comments

Comments
 (0)