From 0c77523d61607ada26537f36651e41762bee7cfc Mon Sep 17 00:00:00 2001 From: phloatingman Date: Fri, 29 Dec 2017 20:02:50 -0800 Subject: [PATCH 1/6] README: fill in libsodium package name for Arch Rebased by moneromooo, with a sensible commit message --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 637be8ed7..f18bd9081 100644 --- a/README.md +++ b/README.md @@ -139,7 +139,7 @@ library archives (`.a`). | libzmq | 3.0.0 | NO | `libzmq3-dev` | `zeromq` | `cppzmq-devel` | NO | ZeroMQ library | | OpenPGM | ? | NO | `libpgm-dev` | `libpgm` | `openpgm-devel` | NO | For ZeroMQ | | libunbound | 1.4.16 | YES | `libunbound-dev` | `unbound` | `unbound-devel` | NO | DNS resolver | -| libsodium | ? | NO | `libsodium-dev` | ? | `libsodium-devel` | NO | cryptography | +| libsodium | ? | NO | `libsodium-dev` | `libsodium` | `libsodium-devel` | NO | cryptography | | libunwind | any | NO | `libunwind8-dev` | `libunwind` | `libunwind-devel` | YES | Stack traces | | liblzma | any | NO | `liblzma-dev` | `xz` | `xz-devel` | YES | For libunwind | | libreadline | 6.3.0 | NO | `libreadline6-dev` | `readline` | `readline-devel` | YES | Input editing | From 52e19d695517fffedabd28424756175743f511bc Mon Sep 17 00:00:00 2001 From: Italocoin Project <12392580+italocoin-project@users.noreply.github.com> Date: Sun, 25 Mar 2018 18:36:25 +0200 Subject: [PATCH 2/6] README: Compile boost with cxxflags=-fPIC cflags=-fPIC Rebased and squashed by moneromooo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f18bd9081..7f5dcf290 100644 --- a/README.md +++ b/README.md @@ -282,7 +282,7 @@ If you are using the older Raspbian Jessie image, compiling Monero is a bit more ``` * Wait ~8 hours ``` - sudo ./bjam install + sudo ./bjam cxxflags=-fPIC cflags=-fPIC -a install ``` * Wait ~4 hours From 24f52396935f7d0624afaf88c6a4b5f2bf5e6932 Mon Sep 17 00:00:00 2001 From: whythat Date: Sun, 6 May 2018 11:38:47 +0300 Subject: [PATCH 3/6] wallet: add 'outputs' option for sweep_* commands 'outputs' option allows to specify the number of separate outputs of smaller denomination that will be created by sweep operation. rebased by moneromooo --- src/simplewallet/simplewallet.cpp | 52 +++++++++++++++++--- src/wallet/wallet2.cpp | 12 ++--- src/wallet/wallet2.h | 6 +-- src/wallet/wallet_rpc_server.cpp | 18 ++++++- src/wallet/wallet_rpc_server_commands_defs.h | 4 ++ 5 files changed, 74 insertions(+), 18 deletions(-) diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index e535b6d27..24903721a 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -2316,15 +2316,15 @@ simple_wallet::simple_wallet() boost::bind(&simple_wallet::sweep_unmixable, this, _1), tr("Send all unmixable outputs to yourself with ring_size 1")); m_cmd_binder.set_handler("sweep_all", boost::bind(&simple_wallet::sweep_all, this, _1), - tr("sweep_all [index=[,,...]] [] []
[]"), - tr("Send all unlocked balance to an address. If the parameter \"index[,,...]\" is specified, the wallet sweeps outputs received by those address indices. If omitted, the wallet randomly chooses an address index to be used.")); + tr("sweep_all [index=[,,...]] [] [] [outputs=]
[]"), + tr("Send all unlocked balance to an address. If the parameter \"index[,,...]\" is specified, the wallet sweeps outputs received by those address indices. If omitted, the wallet randomly chooses an address index to be used. If the parameter \"outputs=\" is specified and N > 0, wallet splits the transaction into N even outputs.")); m_cmd_binder.set_handler("sweep_below", boost::bind(&simple_wallet::sweep_below, this, _1), tr("sweep_below [index=[,,...]] [] []
[]"), tr("Send all unlocked outputs below the threshold to an address.")); m_cmd_binder.set_handler("sweep_single", boost::bind(&simple_wallet::sweep_single, this, _1), - tr("sweep_single [] []
[]"), + tr("sweep_single [] [] [outputs=]
[]"), tr("Send a single output of the given key image to an address without change.")); m_cmd_binder.set_handler("donate", boost::bind(&simple_wallet::donate, this, _1), @@ -5262,7 +5262,7 @@ bool simple_wallet::sweep_main(uint64_t below, bool locked, const std::vector[,,...]] [] []
[]")) % (below ? "sweep_below" : "sweep_all"); + fail_msg_writer() << boost::format(tr("usage: %s [index=[,,...]] [] [] [outputs=]
[]")) % (below ? "sweep_below" : "sweep_all"); }; if (args_.size() == 0) { @@ -5360,6 +5360,25 @@ bool simple_wallet::sweep_main(uint64_t below, bool locked, const std::vector 0 && local_args[0].substr(0, 8) == "outputs=") + { + if (!epee::string_tools::get_xtype_from_string(outputs, local_args[0].substr(8))) + { + fail_msg_writer() << tr("Failed to parse number of outputs"); + return true; + } + else if (outputs < 1) + { + fail_msg_writer() << tr("Amount of outputs should be greater than 0"); + return true; + } + else + { + local_args.erase(local_args.begin()); + } + } + std::vector extra; bool payment_id_seen = false; if (local_args.size() >= 2) @@ -5444,7 +5463,7 @@ bool simple_wallet::sweep_main(uint64_t below, bool locked, const std::vectorcreate_transactions_all(below, info.address, info.is_subaddress, fake_outs_count, unlock_block /* unlock_time */, priority, extra, m_current_subaddress_account, subaddr_indices); + auto ptx_vector = m_wallet->create_transactions_all(below, info.address, info.is_subaddress, outputs, fake_outs_count, unlock_block /* unlock_time */, priority, extra, m_current_subaddress_account, subaddr_indices); if (ptx_vector.empty()) { @@ -5585,6 +5604,25 @@ bool simple_wallet::sweep_single(const std::vector &args_) return true; } + size_t outputs = 1; + if (local_args.size() > 0 && local_args[0].substr(0, 8) == "outputs=") + { + if (!epee::string_tools::get_xtype_from_string(outputs, local_args[0].substr(8))) + { + fail_msg_writer() << tr("Failed to parse number of outputs"); + return true; + } + else if (outputs < 1) + { + fail_msg_writer() << tr("Amount of outputs should be greater than 0"); + return true; + } + else + { + local_args.erase(local_args.begin()); + } + } + std::vector extra; bool payment_id_seen = false; if (local_args.size() == 3) @@ -5618,7 +5656,7 @@ bool simple_wallet::sweep_single(const std::vector &args_) if (local_args.size() != 2) { - fail_msg_writer() << tr("usage: sweep_single [] []
[]"); + fail_msg_writer() << tr("usage: sweep_single [] [] [outputs=]
[]"); return true; } @@ -5673,7 +5711,7 @@ bool simple_wallet::sweep_single(const std::vector &args_) try { // figure out what tx will be necessary - auto ptx_vector = m_wallet->create_transactions_single(ki, info.address, info.is_subaddress, fake_outs_count, 0 /* unlock_time */, priority, extra); + auto ptx_vector = m_wallet->create_transactions_single(ki, info.address, info.is_subaddress, outputs, fake_outs_count, 0 /* unlock_time */, priority, extra); if (ptx_vector.empty()) { diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index b266821d6..fad904031 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -8362,7 +8362,7 @@ skip_tx: return ptx_vector; } -std::vector wallet2::create_transactions_all(uint64_t below, const cryptonote::account_public_address &address, bool is_subaddress, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector& extra, uint32_t subaddr_account, std::set subaddr_indices) +std::vector wallet2::create_transactions_all(uint64_t below, const cryptonote::account_public_address &address, bool is_subaddress, const size_t outputs, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector& extra, uint32_t subaddr_account, std::set subaddr_indices) { std::vector unused_transfers_indices; std::vector unused_dust_indices; @@ -8413,10 +8413,10 @@ std::vector wallet2::create_transactions_all(uint64_t below } } - return create_transactions_from(address, is_subaddress, unused_transfers_indices, unused_dust_indices, fake_outs_count, unlock_time, priority, extra); + return create_transactions_from(address, is_subaddress, outputs, unused_transfers_indices, unused_dust_indices, fake_outs_count, unlock_time, priority, extra); } -std::vector wallet2::create_transactions_single(const crypto::key_image &ki, const cryptonote::account_public_address &address, bool is_subaddress, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector& extra) +std::vector wallet2::create_transactions_single(const crypto::key_image &ki, const cryptonote::account_public_address &address, bool is_subaddress, const size_t outputs, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector& extra) { std::vector unused_transfers_indices; std::vector unused_dust_indices; @@ -8434,10 +8434,10 @@ std::vector wallet2::create_transactions_single(const crypt break; } } - return create_transactions_from(address, is_subaddress, unused_transfers_indices, unused_dust_indices, fake_outs_count, unlock_time, priority, extra); + return create_transactions_from(address, is_subaddress, outputs, unused_transfers_indices, unused_dust_indices, fake_outs_count, unlock_time, priority, extra); } -std::vector wallet2::create_transactions_from(const cryptonote::account_public_address &address, bool is_subaddress, std::vector unused_transfers_indices, std::vector unused_dust_indices, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector& extra) +std::vector wallet2::create_transactions_from(const cryptonote::account_public_address &address, bool is_subaddress, const size_t outputs, std::vector unused_transfers_indices, std::vector unused_dust_indices, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector& extra) { //ensure device is let in NONE mode in any case hw::device &hwdev = m_account.get_device(); @@ -8799,7 +8799,7 @@ std::vector wallet2::create_unmixable_sweep_transactions() unmixable_transfer_outputs.push_back(n); } - return create_transactions_from(m_account_public_address, false, unmixable_transfer_outputs, unmixable_dust_outputs, 0 /*fake_outs_count */, 0 /* unlock_time */, 1 /*priority */, std::vector()); + return create_transactions_from(m_account_public_address, false, 1, unmixable_transfer_outputs, unmixable_dust_outputs, 0 /*fake_outs_count */, 0 /* unlock_time */, 1 /*priority */, std::vector()); } //---------------------------------------------------------------------------------------------------- void wallet2::discard_unmixable_outputs() diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 402066b50..62a72f461 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -748,9 +748,9 @@ namespace tools bool load_tx(const std::string &signed_filename, std::vector &ptx, std::function accept_func = NULL); bool parse_tx_from_str(const std::string &signed_tx_st, std::vector &ptx, std::function accept_func); std::vector create_transactions_2(std::vector dsts, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector& extra, uint32_t subaddr_account, std::set subaddr_indices); // pass subaddr_indices by value on purpose - std::vector create_transactions_all(uint64_t below, const cryptonote::account_public_address &address, bool is_subaddress, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector& extra, uint32_t subaddr_account, std::set subaddr_indices); - std::vector create_transactions_single(const crypto::key_image &ki, const cryptonote::account_public_address &address, bool is_subaddress, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector& extra); - std::vector create_transactions_from(const cryptonote::account_public_address &address, bool is_subaddress, std::vector unused_transfers_indices, std::vector unused_dust_indices, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector& extra); + std::vector create_transactions_all(uint64_t below, const cryptonote::account_public_address &address, bool is_subaddress, const size_t outputs, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector& extra, uint32_t subaddr_account, std::set subaddr_indices); + std::vector create_transactions_single(const crypto::key_image &ki, const cryptonote::account_public_address &address, bool is_subaddress, const size_t outputs, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector& extra); + std::vector create_transactions_from(const cryptonote::account_public_address &address, bool is_subaddress, const size_t outputs, std::vector unused_transfers_indices, std::vector unused_dust_indices, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector& extra); bool load_multisig_tx(cryptonote::blobdata blob, multisig_tx_set &exported_txs, std::function accept_func = NULL); bool load_multisig_tx_from_file(const std::string &filename, multisig_tx_set &exported_txs, std::function accept_func = NULL); bool sign_multisig_tx_from_file(const std::string &filename, std::vector &txids, std::function accept_func); diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index ee86587bc..a2cbbd391 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -1101,6 +1101,13 @@ namespace tools return false; } + if (req.outputs < 1) + { + er.code = WALLET_RPC_ERROR_CODE_TX_NOT_POSSIBLE; + er.message = "Amount of outputs should be greater than 0."; + return false; + } + try { uint64_t mixin; @@ -1113,7 +1120,7 @@ namespace tools mixin = m_wallet->adjust_mixin(req.mixin); } uint32_t priority = m_wallet->adjust_priority(req.priority); - std::vector ptx_vector = m_wallet->create_transactions_all(req.below_amount, dsts[0].addr, dsts[0].is_subaddress, mixin, req.unlock_time, priority, extra, req.account_index, req.subaddr_indices); + std::vector ptx_vector = m_wallet->create_transactions_all(req.below_amount, dsts[0].addr, dsts[0].is_subaddress, req.outputs, mixin, req.unlock_time, priority, extra, req.account_index, req.subaddr_indices); return fill_response(ptx_vector, req.get_tx_keys, res.tx_key_list, res.amount_list, res.fee_list, res.multisig_txset, res.unsigned_txset, req.do_not_relay, res.tx_hash_list, req.get_tx_hex, res.tx_blob_list, req.get_tx_metadata, res.tx_metadata_list, er); @@ -1139,6 +1146,13 @@ namespace tools return false; } + if (req.outputs < 1) + { + er.code = WALLET_RPC_ERROR_CODE_TX_NOT_POSSIBLE; + er.message = "Amount of outputs should be greater than 0."; + return false; + } + // validate the transfer requested and populate dsts & extra std::list destination; destination.push_back(wallet_rpc::transfer_destination()); @@ -1169,7 +1183,7 @@ namespace tools mixin = m_wallet->adjust_mixin(req.mixin); } uint32_t priority = m_wallet->adjust_priority(req.priority); - std::vector ptx_vector = m_wallet->create_transactions_single(ki, dsts[0].addr, dsts[0].is_subaddress, mixin, req.unlock_time, priority, extra); + std::vector ptx_vector = m_wallet->create_transactions_single(ki, dsts[0].addr, dsts[0].is_subaddress, req.outputs, mixin, req.unlock_time, priority, extra); if (ptx_vector.empty()) { diff --git a/src/wallet/wallet_rpc_server_commands_defs.h b/src/wallet/wallet_rpc_server_commands_defs.h index 4501cf575..5d9c22971 100644 --- a/src/wallet/wallet_rpc_server_commands_defs.h +++ b/src/wallet/wallet_rpc_server_commands_defs.h @@ -639,6 +639,7 @@ namespace wallet_rpc uint32_t priority; uint64_t mixin; uint64_t ring_size; + uint64_t outputs; uint64_t unlock_time; std::string payment_id; bool get_tx_keys; @@ -654,6 +655,7 @@ namespace wallet_rpc KV_SERIALIZE(priority) KV_SERIALIZE_OPT(mixin, (uint64_t)0) KV_SERIALIZE_OPT(ring_size, (uint64_t)0) + KV_SERIALIZE_OPT(outputs, (uint64_t)1) KV_SERIALIZE(unlock_time) KV_SERIALIZE(payment_id) KV_SERIALIZE(get_tx_keys) @@ -705,6 +707,7 @@ namespace wallet_rpc uint32_t priority; uint64_t mixin; uint64_t ring_size; + uint64_t outputs; uint64_t unlock_time; std::string payment_id; bool get_tx_key; @@ -718,6 +721,7 @@ namespace wallet_rpc KV_SERIALIZE(priority) KV_SERIALIZE_OPT(mixin, (uint64_t)0) KV_SERIALIZE_OPT(ring_size, (uint64_t)0) + KV_SERIALIZE_OPT(outputs, (uint64_t)1) KV_SERIALIZE(unlock_time) KV_SERIALIZE(payment_id) KV_SERIALIZE(get_tx_key) From 4ed30bab500dbe2ad94dcb44a0f198f94615836a Mon Sep 17 00:00:00 2001 From: whythat Date: Sun, 6 May 2018 11:45:04 +0300 Subject: [PATCH 4/6] wallet: implement coin splitting for sweep_* 'outputs' option Implemented strategy splits total amount into N equal parts, where N is a specified number of outputs. If N > 1, dummy change output is NOT created. rebased by moneromooo --- src/wallet/wallet2.cpp | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index fad904031..0ab1035dd 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -8532,7 +8532,9 @@ std::vector wallet2::create_transactions_from(const crypton needed_fee = estimate_fee(use_per_byte_fee, use_rct, tx.selected_transfers.size(), fake_outs_count, tx.dsts.size()+1, extra.size(), bulletproof, base_fee, fee_multiplier, fee_quantization_mask); - tx.dsts.push_back(tx_destination_entry(1, address, is_subaddress)); + // add N - 1 outputs for correct initial fee estimation + for (size_t i = 0; i < ((outputs > 1) ? outputs - 1 : outputs); ++i) + tx.dsts.push_back(tx_destination_entry(1, address, is_subaddress)); LOG_PRINT_L2("Trying to create a tx now, with " << tx.dsts.size() << " destinations and " << tx.selected_transfers.size() << " outputs"); @@ -8544,15 +8546,35 @@ std::vector wallet2::create_transactions_from(const crypton detail::digit_split_strategy, tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD), test_tx, test_ptx); auto txBlob = t_serializable_object_to_blob(test_ptx.tx); needed_fee = calculate_fee(use_per_byte_fee, test_ptx.tx, txBlob.size(), base_fee, fee_multiplier, fee_quantization_mask); - available_for_fee = test_ptx.fee + test_ptx.dests[0].amount + test_ptx.change_dts.amount; + available_for_fee = test_ptx.fee + test_ptx.change_dts.amount; + for (auto &dt: test_ptx.dests) + available_for_fee += dt.amount; LOG_PRINT_L2("Made a " << get_weight_string(test_ptx.tx, txBlob.size()) << " tx, with " << print_money(available_for_fee) << " available for fee (" << print_money(needed_fee) << " needed)"); + // add last output, missed for fee estimation + if (outputs > 1) + tx.dsts.push_back(tx_destination_entry(1, address, is_subaddress)); + THROW_WALLET_EXCEPTION_IF(needed_fee > available_for_fee, error::wallet_internal_error, "Transaction cannot pay for itself"); do { LOG_PRINT_L2("We made a tx, adjusting fee and saving it"); - tx.dsts[0].amount = available_for_fee - needed_fee; + // distribute total transferred amount between outputs + uint64_t amount_transferred = available_for_fee - needed_fee; + uint64_t dt_amount = amount_transferred / outputs; + // residue is distributed as one atomic unit per output until it reaches zero + uint64_t residue = amount_transferred % outputs; + for (auto &dt: tx.dsts) + { + uint64_t dt_residue = 0; + if (residue > 0) + { + dt_residue = 1; + residue -= 1; + } + dt.amount = dt_amount + dt_residue; + } if (use_rct) transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, outs, unlock_time, needed_fee, extra, test_tx, test_ptx, range_proof_type); From 8cd9840859ed1128f266f6853c3caa9cb8ada8b0 Mon Sep 17 00:00:00 2001 From: "Tuan M. Hoang" Date: Tue, 1 May 2018 00:13:10 -0500 Subject: [PATCH 5/6] disable AES on s390x architecture rebased by moneromooo --- CMakeLists.txt | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5e47edcca..545acfee5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -154,6 +154,10 @@ if(ARCH_ID STREQUAL "powerpc") set(PPC 1) endif() +if(ARCH_ID STREQUAL "s390x") + set(S390X 1) +endif() + if(WIN32 OR ARM OR PPC64LE OR PPC64 OR PPC) set(OPT_FLAGS_RELEASE "-O2") else() @@ -626,12 +630,14 @@ else() message(STATUS "AES support explicitly disabled") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DNO_AES") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DNO_AES") - elseif(NOT ARM AND NOT PPC64LE AND NOT PPC64 AND NOT PPC) + elseif(NOT ARM AND NOT PPC64LE AND NOT PPC64 AND NOT PPC AND NOT S390X) message(STATUS "AES support enabled") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -maes") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -maes") elseif(PPC64LE OR PPC64 OR PPC) message(STATUS "AES support not available on POWER") + elseif(S390X) + message(STATUS "AES support not available on s390x") elseif(ARM6) message(STATUS "AES support not available on ARMv6") elseif(ARM7) From 669019010e41247419a188be26df725068a0abc3 Mon Sep 17 00:00:00 2001 From: Andrea Date: Tue, 5 Jun 2018 20:45:48 -0500 Subject: [PATCH 6/6] README: harmonize command formatting inside README.md rebased by moneromooo --- README.md | 48 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 7f5dcf290..99c6cf3a9 100644 --- a/README.md +++ b/README.md @@ -116,6 +116,52 @@ X's indicate that these details have not been determined as of commit date. Approximately three months prior to a scheduled software upgrade, a branch from Master will be created with the new release version tag. Pull requests that address bugs should then be made to both Master and the new release branch. Pull requests that require extensive review and testing (generally, optimizations and new features) should *not* be made to the release branch. +<<<<<<< HEAD +======= +## Installing Monero from a package + +Packages are available for + +* Ubuntu and [snap supported](https://snapcraft.io/docs/core/install) systems, via a community contributed build. + + snap install monero --beta + +Installing a snap is very quick. Snaps are secure. They are isolated with all of their dependencies. Snaps also auto update when a new version is released. + +* Arch Linux (via [AUR](https://aur.archlinux.org/)): + - Stable release: [`monero`](https://aur.archlinux.org/packages/monero) + - Bleeding edge: [`monero-git`](https://aur.archlinux.org/packages/monero-git) + +* Void Linux: + + xbps-install -S monero + +* GuixSD + + guix package -i monero + +* OS X via [Homebrew](http://brew.sh) + + brew tap sammy007/cryptonight + brew install monero --build-from-source + +* Docker + + # Build using all available cores + docker build -t monero . + + # or build using a specific number of cores (reduce RAM requirement) + docker build --build-arg NPROC=1 -t monero . + + # either run in foreground + docker run -it -v /monero/chain:/root/.bitmonero -v /monero/wallet:/wallet -p 18080:18080 monero + + # or in background + docker run -it -d -v /monero/chain:/root/.bitmonero -v /monero/wallet:/wallet -p 18080:18080 monero + +Packaging for your favorite distribution would be a welcome contribution! + +>>>>>>> f6d62ab... Formating commands inside README.md ## Compiling Monero from source ### Dependencies @@ -497,7 +543,7 @@ Packages are available for * Ubuntu and [snap supported](https://snapcraft.io/docs/core/install) systems, via a community contributed build. - snap install monero --beta + snap install monero --beta Installing a snap is very quick. Snaps are secure. They are isolated with all of their dependencies. Snaps also auto update when a new version is released.