Compare commits

...

65 Commits

Author SHA1 Message Date
Riccardo Spagni 517faceb9e Merge pull request #4465
1f8bfe7f wallet2: fix transfers between subaddresses hitting the sanity check (moneromooo-monero)
2018-09-29 21:50:07 +02:00
moneromooo-monero 1f8bfe7ffa wallet2: fix transfers between subaddresses hitting the sanity check
Transfers between subaddresses are accounted for differently
2018-09-28 17:51:42 +00:00
Riccardo Spagni c6ce8235d8 Merge pull request #4437
3caa4038 wallet2: fix duplicate output making it to the RPC (moneromooo-monero)
58ee1f2b epee: fix invalid memory write reading an array entry (moneromooo-monero)
f61cd544 epee: fix stack overflow on crafted input (moneromooo-monero)
2018-09-25 13:57:51 +02:00
moneromooo-monero 3caa403893 wallet2: fix duplicate output making it to the RPC 2018-09-25 11:30:52 +00:00
moneromooo-monero 58ee1f2bde epee: fix invalid memory write reading an array entry
Reported by Lilith Wyatt at Talos.

Since this is not needed in normal operation, I just let this
error out.
2018-09-25 11:30:48 +00:00
moneromooo-monero f61cd54465 epee: fix stack overflow on crafted input 2018-09-25 11:30:03 +00:00
luigi1111 c7bca47b69 Merge pull request #4227
46b697f abstract_tcp_server2: fix race on shutdown (moneromooo-monero)
2018-08-22 20:53:48 -05:00
luigi1111 84a6e81de0 Merge pull request #4107
cfea525 simplewallet: reword 'seed encryption' to 'seed offset'
2018-08-22 20:29:20 -05:00
moneromooo-monero 46b697feb4 abstract_tcp_server2: fix race on shutdown 2018-08-05 16:31:40 +00:00
Riccardo Spagni a486cae407 Merge pull request #4120
1772c859 add .load() to make Boost 1.67 happy with its new is_integral check (Teutone)
2018-07-10 09:33:13 +02:00
Teutone 1772c8593a add .load() to make Boost 1.67 happy with its new is_integral check 2018-07-09 17:56:30 +01:00
Riccardo Spagni 9a4f1f0134 Merge pull request #4118
58f28cad wallet2: ensure outputs are processed only once (moneromooo-monero)
2018-07-09 17:52:01 +02:00
moneromooo-monero 58f28cadf8 wallet2: ensure outputs are processed only once
This should be proof against any way one might get to multiple
processing, such as generating the same derivation from the
same pubkey, etc
2018-07-08 12:05:04 +01:00
moneromooo-monero cfea525ea3 simplewallet: reword "seed encryption" to "seed offset"
avoids people thinking it's somehow a generic AE system
2018-07-07 11:35:04 +01:00
Riccardo Spagni 40530b294e Merge pull request #4102
424bfdc8 bump version to 12.3 (Riccardo Spagni)
2018-07-06 12:04:49 +02:00
Riccardo Spagni 424bfdc8d7 bump version to 12.3 2018-07-06 07:58:07 +02:00
Riccardo Spagni 1ce04b7574 Merge pull request #4092
3a1ad042 docker: update to new versions of dependencies (HomDx)
fc8726f1 fix sha256sum check, which requires two spaces. added set -ex to catch this, and other, errors in the future. (cornfeedhobo)
8c331a6d wallet2: fix double counting outs if the tx pubkey is duplicated (moneromooo-monero)
2daf54de abstract_tcp_server2: fix use after free (moneromooo-monero)
41662ebc device_ledger: fix buffer underflow on bad data from device (moneromooo-monero)
e389101c device: misc cleanup (moneromooo-monero)
076b7e10 device_ledger: fix potential buffer overflow from bad size calc (moneromooo-monero)
0429cabe simplewallet: init trusted daemon flag to false when autodetecting (moneromooo-monero)
b323d90f wallet2: fix read buffer overflow in import_key_images (moneromooo-monero)
47b42f8b wallet-rpc.getaddress: throw if index is out of bound (stoffu)
223429f0 zmq_server: fix bind call when address and/or port are empty (moneromooo-monero)
280e1a64 Fix RPC crashes that didn't check for an open wallet (Howard Chu)
43a12497 wallet2: fix out of sync account tag cache (moneromooo-monero)
e5ac16b0 abstract_tcp_server2: restart async accept on error (moneromooo-monero)
bea06d1a epee.string_tools: add conversion between UTF-8 and UTF-16 (stoffu)
e93058b4 wallet_api: fixups to build on the branch (moneromooo-monero)
8fb50b73 Wallet API: add support for wallet creation from hardware device (stoffu)
9e9cd108 Move parse_subaddress_lookahead() from simplewallet.cpp to util.cpp (stoffu)
fbdc3096 wallet2: lower default for subaddress lookahead when restoring with hardware (stoffu)
ed366efb add disclaimer about 3rd party packages (Jethro Grassie)
afa66965 wallet: allow unspendable unmixable outputs to be discarded (stoffu)
e70d80e8 wallet2: use decoded amount when reporting repeated output key (stoffu)
5e180c73 wallet2: use correct fee for split txes (stoffu)
d099dba9 epee: adaptive connection timeout system (moneromooo-monero)
04abe99f simplewallet: don't confirm missing payment ID when sending to only subaddresses (stoffu)
9c2f09df epee: fallback to a counter if gmtime fails when rotating logs (moneromooo-monero)
505fde2e Update readme to include pcslite dependency (Gingeropolous)
009feaca wallet2: fix get_approximate_blockchain_height for stagenet (stoffu)
7ce841cc wallet: do not log by default if we're not asked to log to console (moneromooo-monero)
4e2b279a tx_pool: initialize bitflags padding since it gets written to storage (moneromooo-monero)
b85169a5 README: mention --untrusted-daemon (moneromooo-monero)
082e0a1b util: consider Tor/I2P addresses to be non local (moneromooo-monero)
85d2ae4a simplewallet: add optional trusted/untrusted argument to set_daemon (moneromooo-monero)
233a1ead blockchain: pop forked blocks only when DB is not read-only (stoffu)
1380b70e Fixes #3645: error on freebsd lambda return values forced to std::string (rockhouse@users.noreply.github.com)
8e64b616 blockchain: return error when requesting non existent output (moneromooo-monero)
1d3874da epee: fix detection of 172.16.0.0/172.31.255.255 local IP range (moneromooo-monero)
74008527 daemon: fix readline interfering with std::cerr usage (moneromooo-monero)
81e39263 disable file size sanity check when loading the wallet cache (moneromooo-monero)
e04ae088 fix build with GCC 8.1.0 (moneromooo-monero)
f6896d99 core: lock incoming tx lock when checking the txpool and chain (moneromooo-monero)
f6dbb967 simplewallet: add --untrusted-daemon option (moneromooo-monero)
2018-07-05 21:05:44 +02:00
HomDx 3a1ad04234 docker: update to new versions of dependencies 2018-07-04 14:42:46 +01:00
cornfeedhobo fc8726f1c3 fix sha256sum check, which requires two spaces. added set -ex to catch this, and other, errors in the future. 2018-07-04 14:42:45 +01:00
moneromooo-monero 8c331a6d26 wallet2: fix double counting outs if the tx pubkey is duplicated 2018-07-04 10:40:56 +01:00
moneromooo-monero 2daf54deeb abstract_tcp_server2: fix use after free 2018-07-04 10:40:53 +01:00
moneromooo-monero 41662ebcc7 device_ledger: fix buffer underflow on bad data from device 2018-07-04 10:40:50 +01:00
moneromooo-monero e389101cb2 device: misc cleanup
use snprintf "just in case" where appropriate
consistently use unsigned for temp values
pass std::string by const ref rather than by value
add length check (which can't happen in practice) for memcpy
2018-07-04 10:40:46 +01:00
moneromooo-monero 076b7e1076 device_ledger: fix potential buffer overflow from bad size calc 2018-07-04 10:40:42 +01:00
moneromooo-monero 0429cabefd simplewallet: init trusted daemon flag to false when autodetecting 2018-07-04 10:40:39 +01:00
moneromooo-monero b323d90f67 wallet2: fix read buffer overflow in import_key_images 2018-07-04 10:40:35 +01:00
stoffu 47b42f8b01 wallet-rpc.getaddress: throw if index is out of bound 2018-07-04 10:40:32 +01:00
moneromooo-monero 223429f0fd zmq_server: fix bind call when address and/or port are empty 2018-07-04 10:40:29 +01:00
Howard Chu 280e1a64bd Fix RPC crashes that didn't check for an open wallet 2018-07-04 10:40:26 +01:00
moneromooo-monero 43a124979a wallet2: fix out of sync account tag cache
This would cause crashes when trying to tag an account that was
just created
2018-07-04 10:40:23 +01:00
moneromooo-monero e5ac16b077 abstract_tcp_server2: restart async accept on error 2018-07-04 10:40:19 +01:00
stoffu bea06d1a32 epee.string_tools: add conversion between UTF-8 and UTF-16 2018-07-04 10:40:16 +01:00
moneromooo-monero e93058b41c wallet_api: fixups to build on the branch 2018-07-04 10:40:13 +01:00
stoffu 8fb50b738f Wallet API: add support for wallet creation from hardware device 2018-07-04 10:40:09 +01:00
stoffu 9e9cd108a3 Move parse_subaddress_lookahead() from simplewallet.cpp to util.cpp 2018-07-04 10:40:06 +01:00
stoffu fbdc30966b wallet2: lower default for subaddress lookahead when restoring with hardware 2018-07-03 11:19:53 +01:00
Jethro Grassie ed366efb8c add disclaimer about 3rd party packages
Demoted the 3rd party maintained package installs to after compiling
from repository source and removed the broken Homebrew package
instructions.
2018-07-03 11:19:49 +01:00
stoffu afa669656b wallet: allow unspendable unmixable outputs to be discarded 2018-07-03 11:19:45 +01:00
stoffu e70d80e820 wallet2: use decoded amount when reporting repeated output key 2018-07-03 11:19:40 +01:00
stoffu 5e180c73f8 wallet2: use correct fee for split txes 2018-07-03 11:19:36 +01:00
moneromooo-monero d099dba9e1 epee: adaptive connection timeout system
a connection's timeout is halved for every extra connection
from the same host.

Also keep track of when we don't need to use a connection
anymore, so we can close it and free the resource for another
connection.

Also use the longer timeout for non routable local addresses.
2018-07-03 11:19:32 +01:00
stoffu 04abe99f81 simplewallet: don't confirm missing payment ID when sending to only subaddresses 2018-07-03 11:19:28 +01:00
moneromooo-monero 9c2f09df51 epee: fallback to a counter if gmtime fails when rotating logs 2018-07-03 11:19:25 +01:00
Gingeropolous 505fde2e09 Update readme to include pcslite dependency
Update readme to include pcslite dependency
2018-07-03 11:19:21 +01:00
stoffu 009feaca79 wallet2: fix get_approximate_blockchain_height for stagenet 2018-07-03 11:17:56 +01:00
moneromooo-monero 7ce841cc2f wallet: do not log by default if we're not asked to log to console
This means monero-wallet-rpc still does, but the user level program
does not.
2018-07-03 11:17:52 +01:00
moneromooo-monero 4e2b279a94 tx_pool: initialize bitflags padding since it gets written to storage
Avoids valgrind reporting uninitialized data usage
2018-07-03 11:17:48 +01:00
moneromooo-monero b85169a5b6 README: mention --untrusted-daemon
when connecting the wallet to a daemon on a tor hidden service
2018-07-03 11:17:44 +01:00
moneromooo-monero 082e0a1bef util: consider Tor/I2P addresses to be non local 2018-07-03 11:17:40 +01:00
moneromooo-monero 85d2ae4ad7 simplewallet: add optional trusted/untrusted argument to set_daemon
Otherwise the previous daemon's trustedness would carry over.
If not specified, the local address check is performed again.
2018-07-03 11:17:36 +01:00
stoffu 233a1ead22 blockchain: pop forked blocks only when DB is not read-only 2018-07-03 11:17:32 +01:00
rockhouse@users.noreply.github.com 1380b70e74 Fixes #3645: error on freebsd lambda return values forced to std::string 2018-07-03 11:17:28 +01:00
moneromooo-monero 8e64b61663 blockchain: return error when requesting non existent output
avoids RPC thread dying, causing the wallet to timeout
2018-07-03 11:17:24 +01:00
moneromooo-monero 1d3874dabf epee: fix detection of 172.16.0.0/172.31.255.255 local IP range 2018-07-03 11:17:19 +01:00
moneromooo-monero 740085271b daemon: fix readline interfering with std::cerr usage
Once readline is initialized, std::cerr's operator<< will
output a 0xff byte for unknown reasons.
2018-07-03 11:17:15 +01:00
moneromooo-monero 81e3926304 disable file size sanity check when loading the wallet cache 2018-07-03 11:17:11 +01:00
moneromooo-monero e04ae088e8 fix build with GCC 8.1.0 2018-07-03 11:17:07 +01:00
moneromooo-monero f6896d9974 core: lock incoming tx lock when checking the txpool and chain
This gets rid of an innocuous race trying to add the same tx
twice to the txpool
2018-07-03 11:17:03 +01:00
moneromooo-monero f6dbb967f8 simplewallet: add --untrusted-daemon option 2018-07-03 11:17:00 +01:00
luigi1111 06b0f9e870 Merge pull request #3976
f40cf1a device_ledger: fix bad memory access on connect error (moneromooo-monero)
2018-06-27 15:35:13 -05:00
luigi1111 0a7efa45f7 Merge pull request #3928
b1538bf Update readme to indicate recommended version (Gingeropolous)
2018-06-25 14:51:45 -05:00
luigi1111 db26776a35 Merge pull request #3526
66100f2 malloc scratchpad for all supported android archs (m2049r)
2018-06-12 12:10:00 -05:00
moneromooo-monero f40cf1a859 device_ledger: fix bad memory access on connect error 2018-06-09 20:49:05 +01:00
Gingeropolous b1538bff31 Update readme to indicate recommended version
... is 0.12.2.0
2018-06-04 22:34:35 -04:00
m2049r 66100f2fa4 malloc scratchpad for all supported android archs 2018-04-05 21:13:47 +02:00
42 changed files with 710 additions and 239 deletions
+52 -23
View File
@@ -3,7 +3,8 @@
# builder stage
FROM ubuntu:16.04 as builder
RUN apt-get update && \
RUN set -ex && \
apt-get update && \
apt-get --no-install-recommends --yes install \
ca-certificates \
cmake \
@@ -16,16 +17,31 @@ RUN apt-get update && \
curl \
libtool-bin \
autoconf \
automake
automake \
bzip2
WORKDIR /usr/local
#Cmake
ARG CMAKE_VERSION=3.11.4
ARG CMAKE_VERSION_DOT=v3.11
ARG CMAKE_HASH=8f864e9f78917de3e1483e256270daabc4a321741592c5b36af028e72bff87f5
RUN set -ex \
&& curl -s -O https://cmake.org/files/${CMAKE_VERSION_DOT}/cmake-${CMAKE_VERSION}.tar.gz \
&& echo "${CMAKE_HASH} cmake-${CMAKE_VERSION}.tar.gz" | sha256sum -c \
&& tar -xzf cmake-${CMAKE_VERSION}.tar.gz \
&& cd cmake-${CMAKE_VERSION} \
&& ./configure \
&& make \
&& make install
## Boost
ARG BOOST_VERSION=1_66_0
ARG BOOST_VERSION_DOT=1.66.0
ARG BOOST_HASH=5721818253e6a0989583192f96782c4a98eb6204965316df9f5ad75819225ca9
RUN curl -s -L -o boost_${BOOST_VERSION}.tar.bz2 https://dl.bintray.com/boostorg/release/${BOOST_VERSION_DOT}/source/boost_${BOOST_VERSION}.tar.bz2 \
&& echo "${BOOST_HASH} boost_${BOOST_VERSION}.tar.bz2" | sha256sum -c \
ARG BOOST_VERSION=1_67_0
ARG BOOST_VERSION_DOT=1.67.0
ARG BOOST_HASH=2684c972994ee57fc5632e03bf044746f6eb45d4920c343937a465fd67a5adba
RUN set -ex \
&& curl -s -L -o boost_${BOOST_VERSION}.tar.bz2 https://dl.bintray.com/boostorg/release/${BOOST_VERSION_DOT}/source/boost_${BOOST_VERSION}.tar.bz2 \
&& echo "${BOOST_HASH} boost_${BOOST_VERSION}.tar.bz2" | sha256sum -c \
&& tar -xvf boost_${BOOST_VERSION}.tar.bz2 \
&& cd boost_${BOOST_VERSION} \
&& ./bootstrap.sh \
@@ -33,21 +49,24 @@ RUN curl -s -L -o boost_${BOOST_VERSION}.tar.bz2 https://dl.bintray.com/boostor
ENV BOOST_ROOT /usr/local/boost_${BOOST_VERSION}
# OpenSSL
ARG OPENSSL_VERSION=1.0.2n
ARG OPENSSL_HASH=370babb75f278c39e0c50e8c4e7493bc0f18db6867478341a832a982fd15a8fe
RUN curl -s -O https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz \
&& echo "${OPENSSL_HASH} openssl-${OPENSSL_VERSION}.tar.gz" | sha256sum -c \
ARG OPENSSL_VERSION=1.1.0h
ARG OPENSSL_HASH=5835626cde9e99656585fc7aaa2302a73a7e1340bf8c14fd635a62c66802a517
RUN set -ex \
&& curl -s -O https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz \
&& echo "${OPENSSL_HASH} openssl-${OPENSSL_VERSION}.tar.gz" | sha256sum -c \
&& tar -xzf openssl-${OPENSSL_VERSION}.tar.gz \
&& cd openssl-${OPENSSL_VERSION} \
&& ./Configure linux-x86_64 no-shared --static -fPIC \
&& make build_crypto build_ssl \
&& make build_generated \
&& make libcrypto.a \
&& make install
ENV OPENSSL_ROOT_DIR=/usr/local/openssl-${OPENSSL_VERSION}
# ZMQ
ARG ZMQ_VERSION=v4.2.3
ARG ZMQ_HASH=3226b8ebddd9c6c738ba42986822c26418a49afb
RUN git clone https://github.com/zeromq/libzmq.git -b ${ZMQ_VERSION} \
ARG ZMQ_VERSION=v4.2.5
ARG ZMQ_HASH=d062edd8c142384792955796329baf1e5a3377cd
RUN set -ex \
&& git clone https://github.com/zeromq/libzmq.git -b ${ZMQ_VERSION} \
&& cd libzmq \
&& test `git rev-parse HEAD` = ${ZMQ_HASH} || exit 1 \
&& ./autogen.sh \
@@ -57,8 +76,10 @@ RUN git clone https://github.com/zeromq/libzmq.git -b ${ZMQ_VERSION} \
&& ldconfig
# zmq.hpp
ARG CPPZMQ_VERSION=v4.2.3
ARG CPPZMQ_HASH=6aa3ab686e916cb0e62df7fa7d12e0b13ae9fae6
RUN git clone https://github.com/zeromq/cppzmq.git -b ${ZMQ_VERSION} \
RUN set -ex \
&& git clone https://github.com/zeromq/cppzmq.git -b ${CPPZMQ_VERSION} \
&& cd cppzmq \
&& test `git rev-parse HEAD` = ${CPPZMQ_HASH} || exit 1 \
&& mv *.hpp /usr/local/include
@@ -66,8 +87,9 @@ RUN git clone https://github.com/zeromq/cppzmq.git -b ${ZMQ_VERSION} \
# Readline
ARG READLINE_VERSION=7.0
ARG READLINE_HASH=750d437185286f40a369e1e4f4764eda932b9459b5ec9a731628393dd3d32334
RUN curl -s -O https://ftp.gnu.org/gnu/readline/readline-${READLINE_VERSION}.tar.gz \
&& echo "${READLINE_HASH} readline-${READLINE_VERSION}.tar.gz" | sha256sum -c \
RUN set -ex \
&& curl -s -O https://ftp.gnu.org/gnu/readline/readline-${READLINE_VERSION}.tar.gz \
&& echo "${READLINE_HASH} readline-${READLINE_VERSION}.tar.gz" | sha256sum -c \
&& tar -xzf readline-${READLINE_VERSION}.tar.gz \
&& cd readline-${READLINE_VERSION} \
&& CFLAGS="-fPIC" CXXFLAGS="-fPIC" ./configure \
@@ -77,7 +99,8 @@ RUN curl -s -O https://ftp.gnu.org/gnu/readline/readline-${READLINE_VERSION}.tar
# Sodium
ARG SODIUM_VERSION=1.0.16
ARG SODIUM_HASH=675149b9b8b66ff44152553fb3ebf9858128363d
RUN git clone https://github.com/jedisct1/libsodium.git -b ${SODIUM_VERSION} \
RUN set -ex \
&& git clone https://github.com/jedisct1/libsodium.git -b ${SODIUM_VERSION} \
&& cd libsodium \
&& test `git rev-parse HEAD` = ${SODIUM_HASH} || exit 1 \
&& ./autogen.sh \
@@ -90,13 +113,18 @@ WORKDIR /src
COPY . .
ARG NPROC
RUN rm -rf build && \
if [ -z "$NPROC" ];then make -j$(nproc) release-static;else make -j$NPROC release-static;fi
RUN set -ex && \
rm -rf build && \
if [ -z "$NPROC" ] ; \
then make -j$(nproc) release-static ; \
else make -j$NPROC release-static ; \
fi
# runtime stage
FROM ubuntu:16.04
RUN apt-get update && \
RUN set -ex && \
apt-get update && \
apt-get --no-install-recommends --yes install ca-certificates && \
apt-get clean && \
rm -rf /var/lib/apt
@@ -114,4 +142,5 @@ VOLUME /wallet
EXPOSE 18080
EXPOSE 18081
ENTRYPOINT ["monerod", "--p2p-bind-ip=0.0.0.0", "--p2p-bind-port=18080", "--rpc-bind-ip=0.0.0.0", "--rpc-bind-port=18081", "--non-interactive", "--confirm-external-bind"]
ENTRYPOINT ["monerod", "--p2p-bind-ip=0.0.0.0", "--p2p-bind-port=18080", "--rpc-bind-ip=0.0.0.0", "--rpc-bind-port=18081", "--non-interactive", "--confirm-external-bind"]
+47 -44
View File
@@ -104,7 +104,7 @@ Dates are provided in the format YYYY-MM-DD.
| 1220516 | 2017-01-05 | v4 | v0.10.1 | v0.10.2.1 | Allow normal and RingCT transactions |
| 1288616 | 2017-04-15 | v5 | v0.10.3.0 | v0.10.3.1 | Adjusted minimum blocksize and fee algorithm |
| 1400000 | 2017-09-16 | v6 | v0.11.0.0 | v0.11.0.0 | Allow only RingCT transactions, allow only >= ringsize 5 |
| 1546000 | 2018-04-06 | v7 | v0.12.0.0 | v0.12.0.0 | Cryptonight variant 1, ringsize >= 7, sorted inputs
| 1546000 | 2018-04-06 | v7 | v0.12.0.0 | v0.12.2.0 | Cryptonight variant 1, ringsize >= 7, sorted inputs
| XXXXXXX | 2018-10-XX | XX | XXXXXXXXX | XXXXXXXXX | X
X's indicate that these details have not been determined as of commit date.
@@ -113,49 +113,6 @@ 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.
## 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!
## Compiling Monero from source
### Dependencies
@@ -188,6 +145,7 @@ library archives (`.a`).
| GTest | 1.5 | YES | `libgtest-dev`^ | `gtest` | `gtest-devel` | YES | Test suite |
| Doxygen | any | NO | `doxygen` | `doxygen` | `doxygen` | YES | Documentation |
| Graphviz | any | NO | `graphviz` | `graphviz` | `graphviz` | YES | Documentation |
| pcsclite | ? | NO | `libpcsclite-dev` | ? | `pcsc-lite pcsc-lite-devel` | NO | Ledger |
[^] On Debian/Ubuntu `libgtest-dev` only includes sources and headers. You must
@@ -494,6 +452,49 @@ By default, in either dynamically or statically linked builds, binaries target t
* ```make release-static-win64``` builds binaries on 64-bit Windows portable across 64-bit Windows systems
* ```make release-static-win32``` builds binaries on 64-bit or 32-bit Windows portable across 32-bit Windows systems
## Installing Monero from a package
**DISCLAIMER: These packages are not part of this repository or maintained by this project's contributors, and as such, do not go through the same review process to ensure their trustworthiness and security.**
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
* 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
* The build needs 3 GB space.
* Wait one hour or more
Packaging for your favorite distribution would be a welcome contribution!
## Running monerod
The build places the binary in `bin/` sub-directory within the build directory
@@ -547,6 +548,8 @@ setting the following configuration parameters and environment variables:
as well.
* Do NOT pass `--detach` when running through torsocks with systemd, (see
[utils/systemd/monerod.service](utils/systemd/monerod.service) for details).
* If you use the wallet with a Tor daemon via the loopback IP (eg, 127.0.0.1:9050),
then use `--untrusted-daemon` unless it is your own hidden service.
Example command line to start monerod through Tor:
+13 -18
View File
@@ -33,6 +33,7 @@
#include <boost/filesystem/operations.hpp>
#ifdef WIN32
#include <windows.h>
#include "string_tools.h"
#endif
// On Windows there is a problem with non-ASCII characters in path and file names
@@ -72,11 +73,9 @@ namespace file_io_utils
bool save_string_to_file(const std::string& path_to_file, const std::string& str)
{
#ifdef WIN32
WCHAR wide_path[1000];
int chars = MultiByteToWideChar(CP_UTF8, 0, path_to_file.c_str(), path_to_file.size() + 1, wide_path, 1000);
if (chars == 0)
return false;
HANDLE file_handle = CreateFileW(wide_path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
std::wstring wide_path;
try { wide_path = string_tools::utf8_to_utf16(path_to_file); } catch (...) { return false; }
HANDLE file_handle = CreateFileW(wide_path.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (file_handle == INVALID_HANDLE_VALUE)
return false;
DWORD bytes_written;
@@ -128,18 +127,16 @@ namespace file_io_utils
inline
bool load_file_to_string(const std::string& path_to_file, std::string& target_str)
bool load_file_to_string(const std::string& path_to_file, std::string& target_str, size_t max_size = 1000000000)
{
#ifdef WIN32
WCHAR wide_path[1000];
int chars = MultiByteToWideChar(CP_UTF8, 0, path_to_file.c_str(), path_to_file.size() + 1, wide_path, 1000);
if (chars == 0)
return false;
HANDLE file_handle = CreateFileW(wide_path, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
std::wstring wide_path;
try { wide_path = string_tools::utf8_to_utf16(path_to_file); } catch (...) { return false; }
HANDLE file_handle = CreateFileW(wide_path.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (file_handle == INVALID_HANDLE_VALUE)
return false;
DWORD file_size = GetFileSize(file_handle, NULL);
if ((file_size == INVALID_FILE_SIZE) || (file_size > 1000000000)) {
if ((file_size == INVALID_FILE_SIZE) || (uint64_t)file_size > (uint64_t)max_size) {
CloseHandle(file_handle);
return false;
}
@@ -159,7 +156,7 @@ namespace file_io_utils
std::ifstream::pos_type file_size = fstream.tellg();
if(file_size > 1000000000)
if((uint64_t)file_size > (uint64_t)max_size) // ensure a large domain for comparison, and negative -> too large
return false;//don't go crazy
size_t file_size_t = static_cast<size_t>(file_size);
@@ -202,11 +199,9 @@ namespace file_io_utils
bool get_file_size(const std::string& path_to_file, uint64_t &size)
{
#ifdef WIN32
WCHAR wide_path[1000];
int chars = MultiByteToWideChar(CP_UTF8, 0, path_to_file.c_str(), path_to_file.size() + 1, wide_path, 1000);
if (chars == 0)
return false;
HANDLE file_handle = CreateFileW(wide_path, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
std::wstring wide_path;
try { wide_path = string_tools::utf8_to_utf16(path_to_file); } catch (...) { return false; }
HANDLE file_handle = CreateFileW(wide_path.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (file_handle == INVALID_HANDLE_VALUE)
return false;
LARGE_INTEGER file_size;
@@ -119,6 +119,7 @@ namespace net_utils
//----------------- i_service_endpoint ---------------------
virtual bool do_send(const void* ptr, size_t cb); ///< (see do_send from i_service_endpoint)
virtual bool do_send_chunk(const void* ptr, size_t cb); ///< will send (or queue) a part of data
virtual bool send_done();
virtual bool close();
virtual bool call_run_once_service_io();
virtual bool request_callback();
@@ -137,8 +138,11 @@ namespace net_utils
/// reset connection timeout timer and callback
void reset_timer(boost::posix_time::milliseconds ms, bool add);
boost::posix_time::milliseconds get_default_time() const;
boost::posix_time::milliseconds get_timeout_from_bytes_read(size_t bytes) const;
boost::posix_time::milliseconds get_default_timeout();
boost::posix_time::milliseconds get_timeout_from_bytes_read(size_t bytes);
/// host connection count tracking
unsigned int host_count(const std::string &host, int delta = 0);
/// Buffer for incoming data.
boost::array<char, 8192> buffer_;
@@ -154,6 +158,7 @@ namespace net_utils
std::list<boost::shared_ptr<connection<t_protocol_handler> > > m_self_refs; // add_ref/release support
critical_section m_self_refs_lock;
critical_section m_chunking_lock; // held while we add small chunks of the big do_send() to small do_send_chunk()
critical_section m_shutdown_lock; // held while shutting down
t_connection_type m_connection_type;
@@ -165,6 +170,8 @@ namespace net_utils
boost::asio::deadline_timer m_timer;
bool m_local;
bool m_ready_to_close;
std::string m_host;
public:
void setRpcStation();
@@ -56,8 +56,8 @@
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "net"
#define DEFAULT_TIMEOUT_MS_LOCAL boost::posix_time::milliseconds(120000) // 2 minutes
#define DEFAULT_TIMEOUT_MS_REMOTE boost::posix_time::milliseconds(10000) // 10 seconds
#define DEFAULT_TIMEOUT_MS_LOCAL 1800000 // 30 minutes
#define DEFAULT_TIMEOUT_MS_REMOTE 300000 // 5 minutes
#define TIMEOUT_EXTRA_MS_PER_BYTE 0.2
PRAGMA_WARNING_PUSH
@@ -86,7 +86,8 @@ PRAGMA_WARNING_DISABLE_VS(4355)
m_throttle_speed_in("speed_in", "throttle_speed_in"),
m_throttle_speed_out("speed_out", "throttle_speed_out"),
m_timer(io_service),
m_local(false)
m_local(false),
m_ready_to_close(false)
{
MDEBUG("test, connection constructor set m_connection_type="<<m_connection_type);
}
@@ -146,7 +147,7 @@ PRAGMA_WARNING_DISABLE_VS(4355)
context = boost::value_initialized<t_connection_context>();
const unsigned long ip_{boost::asio::detail::socket_ops::host_to_network_long(remote_ep.address().to_v4().to_ulong())};
m_local = epee::net_utils::is_ip_loopback(ip_);
m_local = epee::net_utils::is_ip_loopback(ip_) || epee::net_utils::is_ip_local(ip_);
// create a random uuid
boost::uuids::uuid random_uuid;
@@ -165,9 +166,12 @@ PRAGMA_WARNING_DISABLE_VS(4355)
return false;
}
m_host = context.m_remote_address.host_str();
try { host_count(m_host, 1); } catch(...) { /* ignore */ }
m_protocol_handler.after_init_connection();
reset_timer(get_default_time(), false);
reset_timer(get_default_timeout(), false);
socket_.async_read_some(boost::asio::buffer(buffer_),
strand_.wrap(
@@ -324,6 +328,7 @@ PRAGMA_WARNING_DISABLE_VS(4355)
logger_handle_net_read(bytes_transferred);
context.m_last_recv = time(NULL);
context.m_recv_cnt += bytes_transferred;
m_ready_to_close = false;
bool recv_res = m_protocol_handler.handle_recv(buffer_.data(), bytes_transferred);
if(!recv_res)
{
@@ -356,6 +361,13 @@ PRAGMA_WARNING_DISABLE_VS(4355)
_dbg3("[sock " << socket_.native_handle() << "] Some problems at read: " << e.message() << ':' << e.value());
shutdown();
}
else
{
_dbg3("[sock " << socket_.native_handle() << "] peer closed connection");
if (m_ready_to_close)
shutdown();
}
m_ready_to_close = true;
}
// If an error occurs then no new asynchronous operations are started. This
// means that all shared_ptr references to the connection object will
@@ -531,7 +543,7 @@ PRAGMA_WARNING_DISABLE_VS(4355)
if(m_send_que.size() > 1)
{ // active operation should be in progress, nothing to do, just wait last operation callback
auto size_now = cb;
MDEBUG("do_send() NOW just queues: packet="<<size_now<<" B, is added to queue-size="<<m_send_que.size());
MDEBUG("do_send_chunk() NOW just queues: packet="<<size_now<<" B, is added to queue-size="<<m_send_que.size());
//do_send_handler_delayed( ptr , size_now ); // (((H))) // empty function
LOG_TRACE_CC(context, "[sock " << socket_.native_handle() << "] Async send requested " << m_send_que.front().size());
@@ -546,12 +558,12 @@ PRAGMA_WARNING_DISABLE_VS(4355)
}
auto size_now = m_send_que.front().size();
MDEBUG("do_send() NOW SENSD: packet="<<size_now<<" B");
MDEBUG("do_send_chunk() NOW SENSD: packet="<<size_now<<" B");
if (speed_limit_is_enabled())
do_send_handler_write( ptr , size_now ); // (((H)))
CHECK_AND_ASSERT_MES( size_now == m_send_que.front().size(), false, "Unexpected queue size");
reset_timer(get_default_time(), false);
reset_timer(get_default_timeout(), false);
boost::asio::async_write(socket_, boost::asio::buffer(m_send_que.front().data(), size_now ) ,
//strand_.wrap(
boost::bind(&connection<t_protocol_handler>::handle_write, self, _1, _2)
@@ -566,29 +578,51 @@ PRAGMA_WARNING_DISABLE_VS(4355)
return true;
CATCH_ENTRY_L0("connection<t_protocol_handler>::do_send", false);
CATCH_ENTRY_L0("connection<t_protocol_handler>::do_send_chunk", false);
} // do_send_chunk
//---------------------------------------------------------------------------------
template<class t_protocol_handler>
boost::posix_time::milliseconds connection<t_protocol_handler>::get_default_time() const
boost::posix_time::milliseconds connection<t_protocol_handler>::get_default_timeout()
{
unsigned count;
try { count = host_count(m_host); } catch (...) { count = 0; }
const unsigned shift = std::min(std::max(count, 1u) - 1, 8u);
boost::posix_time::milliseconds timeout(0);
if (m_local)
return DEFAULT_TIMEOUT_MS_LOCAL;
timeout = boost::posix_time::milliseconds(DEFAULT_TIMEOUT_MS_LOCAL >> shift);
else
return DEFAULT_TIMEOUT_MS_REMOTE;
timeout = boost::posix_time::milliseconds(DEFAULT_TIMEOUT_MS_REMOTE >> shift);
return timeout;
}
//---------------------------------------------------------------------------------
template<class t_protocol_handler>
boost::posix_time::milliseconds connection<t_protocol_handler>::get_timeout_from_bytes_read(size_t bytes) const
boost::posix_time::milliseconds connection<t_protocol_handler>::get_timeout_from_bytes_read(size_t bytes)
{
boost::posix_time::milliseconds ms = (boost::posix_time::milliseconds)(unsigned)(bytes * TIMEOUT_EXTRA_MS_PER_BYTE);
ms += m_timer.expires_from_now();
if (ms > get_default_time())
ms = get_default_time();
if (ms > get_default_timeout())
ms = get_default_timeout();
return ms;
}
//---------------------------------------------------------------------------------
template<class t_protocol_handler>
unsigned int connection<t_protocol_handler>::host_count(const std::string &host, int delta)
{
static boost::mutex hosts_mutex;
CRITICAL_REGION_LOCAL(hosts_mutex);
static std::map<std::string, unsigned int> hosts;
unsigned int &val = hosts[host];
if (delta > 0)
MTRACE("New connection from host " << host << ": " << val);
else if (delta < 0)
MTRACE("Closed connection from host " << host << ": " << val);
CHECK_AND_ASSERT_THROW_MES(delta >= 0 || val >= (unsigned)-delta, "Count would go negative");
CHECK_AND_ASSERT_THROW_MES(delta <= 0 || val <= std::numeric_limits<unsigned int>::max() - (unsigned)delta, "Count would wrap");
val += delta;
return val;
}
//---------------------------------------------------------------------------------
template<class t_protocol_handler>
void connection<t_protocol_handler>::reset_timer(boost::posix_time::milliseconds ms, bool add)
{
if (m_connection_type != e_connection_type_RPC)
@@ -615,11 +649,20 @@ PRAGMA_WARNING_DISABLE_VS(4355)
template<class t_protocol_handler>
bool connection<t_protocol_handler>::shutdown()
{
CRITICAL_REGION_BEGIN(m_shutdown_lock);
if (m_was_shutdown)
return true;
m_was_shutdown = true;
// Initiate graceful connection closure.
m_timer.cancel();
boost::system::error_code ignored_ec;
socket_.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored_ec);
m_was_shutdown = true;
if (!m_host.empty())
{
try { host_count(m_host, -1); } catch (...) { /* ignore */ }
m_host = "";
}
CRITICAL_REGION_END();
m_protocol_handler.release_protocol();
return true;
}
@@ -628,6 +671,9 @@ PRAGMA_WARNING_DISABLE_VS(4355)
bool connection<t_protocol_handler>::close()
{
TRY_ENTRY();
auto self = safe_shared_from_this();
if(!self)
return false;
//_info("[sock " << socket_.native_handle() << "] Que Shutdown called.");
m_timer.cancel();
size_t send_que_size = 0;
@@ -645,6 +691,15 @@ PRAGMA_WARNING_DISABLE_VS(4355)
}
//---------------------------------------------------------------------------------
template<class t_protocol_handler>
bool connection<t_protocol_handler>::send_done()
{
if (m_ready_to_close)
return close();
m_ready_to_close = true;
return true;
}
//---------------------------------------------------------------------------------
template<class t_protocol_handler>
bool connection<t_protocol_handler>::cancel()
{
return close();
@@ -687,7 +742,7 @@ PRAGMA_WARNING_DISABLE_VS(4355)
}else
{
//have more data to send
reset_timer(get_default_time(), false);
reset_timer(get_default_timeout(), false);
auto size_now = m_send_que.front().size();
MDEBUG("handle_write() NOW SENDS: packet="<<size_now<<" B" <<", from queue size="<<m_send_que.size());
if (speed_limit_is_enabled())
@@ -982,7 +1037,8 @@ POP_WARNINGS
void boosted_tcp_server<t_protocol_handler>::handle_accept(const boost::system::error_code& e)
{
MDEBUG("handle_accept");
TRY_ENTRY();
try
{
if (!e)
{
if (m_connection_type == e_connection_type_RPC) {
@@ -1000,11 +1056,25 @@ POP_WARNINGS
conn->start(true, 1 < m_threads_count);
conn->save_dbg_log();
}else
{
_erro("Some problems at accept: " << e.message() << ", connections_count = " << m_sock_count);
return;
}
CATCH_ENTRY_L0("boosted_tcp_server<t_protocol_handler>::handle_accept", void());
else
{
MERROR("Error in boosted_tcp_server<t_protocol_handler>::handle_accept: " << e);
}
}
catch (const std::exception &e)
{
MERROR("Exception in boosted_tcp_server<t_protocol_handler>::handle_accept: " << e.what());
}
// error path, if e or exception
_erro("Some problems at accept: " << e.message() << ", connections_count = " << m_sock_count);
misc_utils::sleep_no_w(100);
new_connection_.reset(new connection<t_protocol_handler>(io_service_, m_config, m_sock_count, m_sock_number, m_pfilter, m_connection_type));
acceptor_.async_accept(new_connection_->socket(),
boost::bind(&boosted_tcp_server<t_protocol_handler>::handle_accept, this,
boost::asio::placeholders::error));
}
//---------------------------------------------------------------------------------
template<class t_protocol_handler>
@@ -399,7 +399,7 @@ namespace net_utils
template<class t_connection_context>
bool simple_http_connection_handler<t_connection_context>::analize_cached_request_header_and_invoke_state(size_t pos)
{
//LOG_PRINT_L4("HTTP HEAD:\r\n" << m_cache.substr(0, pos));
LOG_PRINT_L3("HTTP HEAD:\r\n" << m_cache.substr(0, pos));
m_query_info.m_full_request_buf_size = pos;
m_query_info.m_request_head.assign(m_cache.begin(), m_cache.begin()+pos);
@@ -582,6 +582,7 @@ namespace net_utils
m_psnd_hndlr->do_send((void*)response_data.data(), response_data.size());
if ((response.m_body.size() && (query_info.m_http_method != http::http_method_head)) || (query_info.m_http_method == http::http_method_options))
m_psnd_hndlr->do_send((void*)response.m_body.data(), response.m_body.size());
m_psnd_hndlr->send_done();
return res;
}
//-----------------------------------------------------------------------------------
+1 -1
View File
@@ -48,7 +48,7 @@ namespace epee
if( (ip | 0xffffff00) == 0xffffffac)
{
uint32_t second_num = (ip << 8) & 0xff000000;
uint32_t second_num = (ip >> 8) & 0xff;
if(second_num >= 16 && second_num <= 31 )
return true;
}
@@ -281,6 +281,7 @@ namespace net_utils
{
virtual bool do_send(const void* ptr, size_t cb)=0;
virtual bool close()=0;
virtual bool send_done()=0;
virtual bool call_run_once_service_io()=0;
virtual bool request_callback()=0;
virtual boost::asio::io_service& get_io_service()=0;
@@ -59,6 +59,7 @@ namespace epee
storage_entry load_storage_entry();
void read(section& sec);
void read(std::string& str);
void read(array_entry &ae);
private:
struct recursuion_limitation_guard
{
@@ -114,6 +115,7 @@ namespace epee
void throwable_buffer_reader::read(t_pod_type& pod_val)
{
RECURSION_LIMITATION();
static_assert(std::is_pod<t_pod_type>::value, "POD type expected");
read(&pod_val, sizeof(pod_val));
}
@@ -277,5 +279,11 @@ namespace epee
m_ptr+=len;
m_count -= len;
}
inline
void throwable_buffer_reader::read(array_entry &ae)
{
RECURSION_LIMITATION();
CHECK_AND_ASSERT_THROW_MES(false, "Reading array entry is not supported");
}
}
}
@@ -30,6 +30,8 @@
#include "parserse_base_utils.h"
#include "file_io_utils.h"
#define EPEE_JSON_RECURSION_LIMIT_INTERNAL 100
namespace epee
{
using namespace misc_utils::parse;
@@ -44,8 +46,9 @@ namespace epee
ASSERT_MES_AND_THROW("json parse error");
}*/
template<class t_storage>
inline void run_handler(typename t_storage::hsection current_section, std::string::const_iterator& sec_buf_begin, std::string::const_iterator buf_end, t_storage& stg)
inline void run_handler(typename t_storage::hsection current_section, std::string::const_iterator& sec_buf_begin, std::string::const_iterator buf_end, t_storage& stg, unsigned int recursion)
{
CHECK_AND_ASSERT_THROW_MES(recursion < EPEE_JSON_RECURSION_LIMIT_INTERNAL, "Wrong JSON data: recursion limitation (" << EPEE_JSON_RECURSION_LIMIT_INTERNAL << ") exceeded");
std::string::const_iterator sub_element_start;
std::string name;
@@ -157,7 +160,7 @@ namespace epee
//sub section here
typename t_storage::hsection new_sec = stg.open_section(name, current_section, true);
CHECK_AND_ASSERT_THROW_MES(new_sec, "Failed to insert new section in json: " << std::string(it, buf_end));
run_handler(new_sec, it, buf_end, stg);
run_handler(new_sec, it, buf_end, stg, recursion + 1);
state = match_state_wonder_after_value;
}else if(*it == '[')
{//array of something
@@ -186,7 +189,7 @@ namespace epee
typename t_storage::hsection new_sec = nullptr;
h_array = stg.insert_first_section(name, new_sec, current_section);
CHECK_AND_ASSERT_THROW_MES(h_array&&new_sec, "failed to create new section");
run_handler(new_sec, it, buf_end, stg);
run_handler(new_sec, it, buf_end, stg, recursion + 1);
state = match_state_array_after_value;
array_md = array_mode_sections;
}else if(*it == '"')
@@ -260,7 +263,7 @@ namespace epee
typename t_storage::hsection new_sec = NULL;
bool res = stg.insert_next_section(h_array, new_sec);
CHECK_AND_ASSERT_THROW_MES(res&&new_sec, "failed to insert next section");
run_handler(new_sec, it, buf_end, stg);
run_handler(new_sec, it, buf_end, stg, recursion + 1);
state = match_state_array_after_value;
}else CHECK_ISSPACE();
break;
@@ -362,7 +365,7 @@ namespace epee
std::string::const_iterator sec_buf_begin = buff_json.begin();
try
{
run_handler(nullptr, sec_buf_begin, buff_json.end(), stg);
run_handler(nullptr, sec_buf_begin, buff_json.end(), stg, 0);
return true;
}
catch(const std::exception& ex)
+35
View File
@@ -381,6 +381,41 @@ POP_WARNINGS
res = str.substr(0, pos);
return res;
}
//----------------------------------------------------------------------------
#ifdef _WIN32
inline std::wstring utf8_to_utf16(const std::string& str)
{
if (str.empty())
return {};
int wstr_size = MultiByteToWideChar(CP_UTF8, 0, &str[0], str.size(), NULL, 0);
if (wstr_size == 0)
{
throw std::runtime_error(std::error_code(GetLastError(), std::system_category()).message());
}
std::wstring wstr(wstr_size, wchar_t{});
if (!MultiByteToWideChar(CP_UTF8, 0, &str[0], str.size(), &wstr[0], wstr_size))
{
throw std::runtime_error(std::error_code(GetLastError(), std::system_category()).message());
}
return wstr;
}
inline std::string utf16_to_utf8(const std::wstring& wstr)
{
if (wstr.empty())
return {};
int str_size = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], wstr.size(), NULL, 0, NULL, NULL);
if (str_size == 0)
{
throw std::runtime_error(std::error_code(GetLastError(), std::system_category()).message());
}
std::string str(str_size, char{});
if (!WideCharToMultiByte(CP_UTF8, 0, &wstr[0], wstr.size(), &str[0], str_size, NULL, NULL))
{
throw std::runtime_error(std::error_code(GetLastError(), std::system_category()).message());
}
return str;
}
#endif
}
}
#endif //_STRING_TOOLS_H_
+2 -1
View File
@@ -47,6 +47,7 @@ using namespace epee;
static std::string generate_log_filename(const char *base)
{
std::string filename(base);
static unsigned int fallback_counter = 0;
char tmp[200];
struct tm tm;
time_t now = time(NULL);
@@ -56,7 +57,7 @@ static std::string generate_log_filename(const char *base)
#else
(!gmtime_r(&now, &tm))
#endif
strcpy(tmp, "unknown");
snprintf(tmp, sizeof(tmp), "part-%u", ++fallback_counter);
else
strftime(tmp, sizeof(tmp), "%Y-%m-%d-%H-%M-%S", &tm);
tmp[sizeof(tmp) - 1] = 0;
+1
View File
@@ -148,6 +148,7 @@ struct txpool_tx_meta_t
uint8_t relayed;
uint8_t do_not_relay;
uint8_t double_spend_seen: 1;
uint8_t bf_padding: 7;
uint8_t padding[76]; // till 192 bytes
};
@@ -165,7 +165,7 @@ int main(int argc, char* argv[])
"blackball-db-dir", "Specify blackball database directory",
get_default_db_path(),
{{ &arg_testnet_on, &arg_stagenet_on }},
[](std::array<bool, 2> testnet_stagenet, bool defaulted, std::string val) {
[](std::array<bool, 2> testnet_stagenet, bool defaulted, std::string val)->std::string {
if (testnet_stagenet[0])
return (boost::filesystem::path(val) / "testnet").string();
else if (testnet_stagenet[1])
+43 -11
View File
@@ -440,10 +440,15 @@ std::string get_nix_version_display_string()
if (SHGetSpecialFolderPathW(NULL, psz_path, nfolder, iscreate))
{
int size_needed = WideCharToMultiByte(CP_UTF8, 0, psz_path, wcslen(psz_path), NULL, 0, NULL, NULL);
std::string folder_name(size_needed, 0);
WideCharToMultiByte(CP_UTF8, 0, psz_path, wcslen(psz_path), &folder_name[0], size_needed, NULL, NULL);
return folder_name;
try
{
return string_tools::utf16_to_utf8(psz_path);
}
catch (const std::exception &e)
{
MERROR("utf16_to_utf8 failed: " << e.what());
return "";
}
}
LOG_ERROR("SHGetSpecialFolderPathW() failed, could not obtain requested path.");
@@ -504,18 +509,20 @@ std::string get_nix_version_display_string()
int code;
#if defined(WIN32)
// Maximizing chances for success
WCHAR wide_replacement_name[1000];
MultiByteToWideChar(CP_UTF8, 0, replacement_name.c_str(), replacement_name.size() + 1, wide_replacement_name, 1000);
WCHAR wide_replaced_name[1000];
MultiByteToWideChar(CP_UTF8, 0, replaced_name.c_str(), replaced_name.size() + 1, wide_replaced_name, 1000);
std::wstring wide_replacement_name;
try { wide_replacement_name = string_tools::utf8_to_utf16(replacement_name); }
catch (...) { return std::error_code(GetLastError(), std::system_category()); }
std::wstring wide_replaced_name;
try { wide_replaced_name = string_tools::utf8_to_utf16(replaced_name); }
catch (...) { return std::error_code(GetLastError(), std::system_category()); }
DWORD attributes = ::GetFileAttributesW(wide_replaced_name);
DWORD attributes = ::GetFileAttributesW(wide_replaced_name.c_str());
if (INVALID_FILE_ATTRIBUTES != attributes)
{
::SetFileAttributesW(wide_replaced_name, attributes & (~FILE_ATTRIBUTE_READONLY));
::SetFileAttributesW(wide_replaced_name.c_str(), attributes & (~FILE_ATTRIBUTE_READONLY));
}
bool ok = 0 != ::MoveFileExW(wide_replacement_name, wide_replaced_name, MOVEFILE_REPLACE_EXISTING);
bool ok = 0 != ::MoveFileExW(wide_replacement_name.c_str(), wide_replaced_name.c_str(), MOVEFILE_REPLACE_EXISTING);
code = ok ? 0 : static_cast<int>(::GetLastError());
#else
bool ok = 0 == std::rename(replacement_name.c_str(), replaced_name.c_str());
@@ -657,6 +664,13 @@ std::string get_nix_version_display_string()
bool is_local_address(const std::string &address)
{
// always assume Tor/I2P addresses to be untrusted by default
if (boost::ends_with(address, ".onion") || boost::ends_with(address, ".i2p"))
{
MDEBUG("Address '" << address << "' is Tor/I2P, non local");
return false;
}
// extract host
epee::net_utils::http::url_content u_c;
if (!epee::net_utils::parse_url(address, u_c))
@@ -750,4 +764,22 @@ std::string get_nix_version_display_string()
return false;
return true;
}
boost::optional<std::pair<uint32_t, uint32_t>> parse_subaddress_lookahead(const std::string& str)
{
auto pos = str.find(":");
bool r = pos != std::string::npos;
uint32_t major;
r = r && epee::string_tools::get_xtype_from_string(major, str.substr(0, pos));
uint32_t minor;
r = r && epee::string_tools::get_xtype_from_string(minor, str.substr(pos + 1));
if (r)
{
return std::make_pair(major, minor);
}
else
{
return {};
}
}
}
+3
View File
@@ -32,6 +32,7 @@
#include <boost/thread/locks.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/optional.hpp>
#include <system_error>
#include <csignal>
#include <cstdio>
@@ -212,4 +213,6 @@ namespace tools
bool sha256sum(const uint8_t *data, size_t len, crypto::hash &hash);
bool sha256sum(const std::string &filename, crypto::hash &hash);
boost::optional<std::pair<uint32_t, uint32_t>> parse_subaddress_lookahead(const std::string& str);
}
+39 -2
View File
@@ -905,10 +905,35 @@ STATIC INLINE void aes_pseudo_round_xor(const uint8_t *in, uint8_t *out, const u
}
}
STATIC INLINE void* aligned_malloc(size_t size, size_t align)
{
void *result;
#ifdef _MSC_VER
result = _aligned_malloc(size, align);
#else
if (posix_memalign(&result, align, size)) result = NULL;
#endif
return result;
}
STATIC INLINE void aligned_free(void *ptr)
{
#ifdef _MSC_VER
_aligned_free(ptr);
#else
free(ptr);
#endif
}
void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int prehashed)
{
RDATA_ALIGN16 uint8_t expandedKey[240];
#ifndef FORCE_USE_HEAP
RDATA_ALIGN16 uint8_t hp_state[MEMORY];
#else
uint8_t *hp_state = (uint8_t *)aligned_malloc(MEMORY,16);
#endif
uint8_t text[INIT_SIZE_BYTE];
RDATA_ALIGN16 uint64_t a[2];
@@ -993,6 +1018,10 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int
memcpy(state.init, text, INIT_SIZE_BYTE);
hash_permutation(&state.hs);
extra_hashes[state.hs.b[0] & 3](&state, 200, hash);
#ifdef FORCE_USE_HEAP
aligned_free(hp_state);
#endif
}
#else /* aarch64 && crypto */
@@ -1127,8 +1156,7 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int
#ifndef FORCE_USE_HEAP
uint8_t long_state[MEMORY];
#else
uint8_t *long_state = NULL;
long_state = (uint8_t *)malloc(MEMORY);
uint8_t *long_state = (uint8_t *)malloc(MEMORY);
#endif
if (prehashed) {
@@ -1294,7 +1322,12 @@ union cn_slow_hash_state {
#pragma pack(pop)
void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int prehashed) {
#ifndef FORCE_USE_HEAP
uint8_t long_state[MEMORY];
#else
uint8_t *long_state = (uint8_t *)malloc(MEMORY);
#endif
union cn_slow_hash_state state;
uint8_t text[INIT_SIZE_BYTE];
uint8_t a[AES_BLOCK_SIZE];
@@ -1370,6 +1403,10 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int
/*memcpy(hash, &state, 32);*/
extra_hashes[state.hs.b[0] & 3](&state, 200, hash);
oaes_free((OAES_CTX **) &aes_ctx);
#ifdef FORCE_USE_HEAP
free(long_state);
#endif
}
#endif
+1 -1
View File
@@ -157,7 +157,7 @@ DISABLE_VS_WARNINGS(4244 4345)
void account_base::create_from_viewkey(const cryptonote::account_public_address& address, const crypto::secret_key& viewkey)
{
crypto::secret_key fake;
memset(&fake, 0, sizeof(fake));
memset(&unwrap(fake), 0, sizeof(fake));
create_from_keys(address, fake, viewkey);
}
//-----------------------------------------------------------------
+14 -7
View File
@@ -442,7 +442,7 @@ bool Blockchain::init(BlockchainDB* db, const network_type nettype, bool offline
m_db->block_txn_stop();
uint64_t num_popped_blocks = 0;
while (true)
while (!m_db->is_read_only())
{
const uint64_t top_height = m_db->height() - 1;
const crypto::hash top_id = m_db->top_block_hash();
@@ -1941,14 +1941,21 @@ bool Blockchain::get_outs(const COMMAND_RPC_GET_OUTPUTS_BIN::request& req, COMMA
res.outs.clear();
res.outs.reserve(req.outputs.size());
for (const auto &i: req.outputs)
try
{
// get tx_hash, tx_out_index from DB
const output_data_t od = m_db->get_output_key(i.amount, i.index);
tx_out_index toi = m_db->get_output_tx_and_index(i.amount, i.index);
bool unlocked = is_tx_spendtime_unlocked(m_db->get_tx_unlock_time(toi.first));
for (const auto &i: req.outputs)
{
// get tx_hash, tx_out_index from DB
const output_data_t od = m_db->get_output_key(i.amount, i.index);
tx_out_index toi = m_db->get_output_tx_and_index(i.amount, i.index);
bool unlocked = is_tx_spendtime_unlocked(m_db->get_tx_unlock_time(toi.first));
res.outs.push_back({od.pubkey, od.commitment, unlocked, od.height, toi.first});
res.outs.push_back({od.pubkey, od.commitment, unlocked, od.height, toi.first});
}
}
catch (const std::exception &e)
{
return false;
}
return true;
}
+1
View File
@@ -676,6 +676,7 @@ namespace cryptonote
bool core::handle_incoming_txs(const std::list<blobdata>& tx_blobs, std::vector<tx_verification_context>& tvc, bool keeped_by_block, bool relayed, bool do_not_relay)
{
TRY_ENTRY();
CRITICAL_REGION_LOCAL(m_incoming_tx_lock);
struct result { bool res; cryptonote::transaction tx; crypto::hash hash; crypto::hash prefix_hash; bool in_txpool; bool in_blockchain; };
std::vector<result> results(tx_blobs.size());
+2
View File
@@ -239,6 +239,7 @@ namespace cryptonote
meta.relayed = relayed;
meta.do_not_relay = do_not_relay;
meta.double_spend_seen = have_tx_keyimges_as_spent(tx);
meta.bf_padding = 0;
memset(meta.padding, 0, sizeof(meta.padding));
try
{
@@ -278,6 +279,7 @@ namespace cryptonote
meta.relayed = relayed;
meta.do_not_relay = do_not_relay;
meta.double_spend_seen = false;
meta.bf_padding = 0;
memset(meta.padding, 0, sizeof(meta.padding));
try
+3
View File
@@ -262,6 +262,9 @@ int main(int argc, char const * argv[])
}
else
{
#ifdef HAVE_READLINE
rdln::suspend_readline pause_readline;
#endif
std::cerr << "Unknown command: " << command.front() << std::endl;
return 1;
}
+1 -1
View File
@@ -973,7 +973,7 @@ bool t_rpc_command_executor::print_transaction_pool_stats() {
}
else
{
memset(&res.pool_stats, 0, sizeof(res.pool_stats));
res.pool_stats = {};
if (!m_rpc_server->on_get_transaction_pool_stats(req, res, false) || res.status != CORE_RPC_STATUS_OK)
{
tools::fail_msg_writer() << make_error(fail_message, res.status);
+9 -6
View File
@@ -187,14 +187,15 @@ namespace hw {
void device_ledger::logCMD() {
if (apdu_verbose) {
char strbuffer[1024];
sprintf(strbuffer, "%.02x %.02x %.02x %.02x %.02x ",
snprintf(strbuffer, sizeof(strbuffer), "%.02x %.02x %.02x %.02x %.02x ",
this->buffer_send[0],
this->buffer_send[1],
this->buffer_send[2],
this->buffer_send[3],
this->buffer_send[4]
);
buffer_to_str(strbuffer+strlen(strbuffer), sizeof(strbuffer), (char*)(this->buffer_send+5), this->length_send-5);
const size_t len = strlen(strbuffer);
buffer_to_str(strbuffer+len, sizeof(strbuffer)-len, (char*)(this->buffer_send+5), this->length_send-5);
MDEBUG( "CMD :" << strbuffer);
}
}
@@ -202,11 +203,12 @@ namespace hw {
void device_ledger::logRESP() {
if (apdu_verbose) {
char strbuffer[1024];
sprintf(strbuffer, "%.02x%.02x ",
snprintf(strbuffer, sizeof(strbuffer), "%.02x%.02x ",
this->buffer_recv[this->length_recv-2],
this->buffer_recv[this->length_recv-1]
);
buffer_to_str(strbuffer+strlen(strbuffer), sizeof(strbuffer), (char*)(this->buffer_recv), this->length_recv-2);
const size_t len = strlen(strbuffer);
buffer_to_str(strbuffer+len, sizeof(strbuffer)-len, (char*)(this->buffer_recv), this->length_recv-2);
MDEBUG( "RESP :" << strbuffer);
}
@@ -293,7 +295,7 @@ namespace hw {
unsigned int device_ledger::exchange(unsigned int ok, unsigned int mask) {
LONG rv;
int sw;
unsigned int sw;
ASSERT_T0(this->length_send <= BUFFER_SEND_SIZE);
logCMD();
@@ -302,6 +304,7 @@ namespace hw {
SCARD_PCI_T0, this->buffer_send, this->length_send,
NULL, this->buffer_recv, &this->length_recv);
ASSERT_RV(rv);
ASSERT_T0(this->length_recv >= 2);
ASSERT_T0(this->length_recv <= BUFFER_RECV_SIZE);
logRESP();
@@ -405,7 +408,7 @@ namespace hw {
}
}
if (mszReaders) {
if (rv == SCARD_S_SUCCESS && mszReaders) {
#ifdef SCARD_AUTOALLOCATE
SCardFreeMemory(this->hContext, mszReaders);
#else
+7 -5
View File
@@ -45,13 +45,13 @@ namespace hw {
}
}
void log_hexbuffer(std::string msg, const char* buff, size_t len) {
void log_hexbuffer(const std::string &msg, const char* buff, size_t len) {
char logstr[1025];
buffer_to_str(logstr, sizeof(logstr), buff, len);
MDEBUG(msg<< ": " << logstr);
}
void log_message(std::string msg, std::string info ) {
void log_message(const std::string &msg, const std::string &info ) {
MDEBUG(msg << ": " << info);
}
@@ -122,16 +122,18 @@ namespace hw {
rct::keyV decrypt(const rct::keyV &keys) {
rct::keyV x ;
x.reserve(keys.size());
for (unsigned int j = 0; j<keys.size(); j++) {
x.push_back(decrypt(keys[j]));
}
return x;
}
static void check(std::string msg, std::string info, const char *h, const char *d, int len, bool crypted) {
static void check(const std::string &msg, const std::string &info, const char *h, const char *d, size_t len, bool crypted) {
char dd[32];
char logstr[128];
CHECK_AND_ASSERT_THROW_MES(len <= sizeof(dd), "invalid len");
memmove(dd,d,len);
if (crypted) {
CHECK_AND_ASSERT_THROW_MES(len<=32, "encrypted data greater than 32");
@@ -149,11 +151,11 @@ namespace hw {
}
}
void check32(std::string msg, std::string info, const char *h, const char *d, bool crypted) {
void check32(const std::string &msg, const std::string &info, const char *h, const char *d, bool crypted) {
check(msg, info, h, d, 32, crypted);
}
void check8(std::string msg, std::string info, const char *h, const char *d, bool crypted) {
void check8(const std::string &msg, const std::string &info, const char *h, const char *d, bool crypted) {
check(msg, info, h, d, 8, crypted);
}
#endif
+4 -4
View File
@@ -44,8 +44,8 @@ namespace hw {
namespace ledger {
void buffer_to_str(char *to_buff, size_t to_len, const char *buff, size_t len) ;
void log_hexbuffer(std::string msg, const char* buff, size_t len);
void log_message(std::string msg, std::string info );
void log_hexbuffer(const std::string &msg, const char* buff, size_t len);
void log_message(const std::string &msg, const std::string &info );
#ifdef DEBUG_HWDEVICE
#define TRACK printf("file %s:%d\n",__FILE__, __LINE__)
//#define TRACK MCDEBUG("ledger"," At file " << __FILE__ << ":" << __LINE__)
@@ -59,8 +59,8 @@ namespace hw {
crypto::ec_scalar decrypt(const crypto::ec_scalar &res);
rct::keyV decrypt(const rct::keyV &keys);
void check32(std::string msg, std::string info, const char *h, const char *d, bool crypted=false);
void check8(std::string msg, std::string info, const char *h, const char *d, bool crypted=false);
void check32(const std::string &msg, const std::string &info, const char *h, const char *d, bool crypted=false);
void check8(const std::string &msg, const std::string &info, const char *h, const char *d, bool crypted=false);
void set_check_verbose(bool verbose);
#endif
+2
View File
@@ -1554,6 +1554,8 @@ namespace cryptonote
std::vector<txpool_histo> histo;
uint32_t num_double_spends;
txpool_stats(): bytes_total(0), bytes_min(0), bytes_max(0), bytes_med(0), fee_total(0), oldest(0), txs_total(0), num_failing(0), num_10m(0), num_not_relayed(0), histo_98pc(0), num_double_spends(0) {}
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(bytes_total)
KV_SERIALIZE(bytes_min)
+4
View File
@@ -104,6 +104,10 @@ bool ZmqServer::addTCPSocket(std::string address, std::string port)
rep_socket->setsockopt(ZMQ_RCVTIMEO, &DEFAULT_RPC_RECV_TIMEOUT_MS, sizeof(DEFAULT_RPC_RECV_TIMEOUT_MS));
if (address.empty())
address = "*";
if (port.empty())
port = "*";
std::string bind_address = addr_prefix + address + std::string(":") + port;
rep_socket->bind(bind_address.c_str());
}
+89 -48
View File
@@ -131,6 +131,7 @@ namespace
const command_line::arg_descriptor<bool> arg_restore_multisig_wallet = {"restore-multisig-wallet", sw::tr("Recover multisig wallet using Electrum-style mnemonic seed"), false};
const command_line::arg_descriptor<bool> arg_non_deterministic = {"non-deterministic", sw::tr("Generate non-deterministic view and spend keys"), false};
const command_line::arg_descriptor<bool> arg_trusted_daemon = {"trusted-daemon", sw::tr("Enable commands which rely on a trusted daemon"), false};
const command_line::arg_descriptor<bool> arg_untrusted_daemon = {"untrusted-daemon", sw::tr("Disable commands which rely on a trusted daemon"), false};
const command_line::arg_descriptor<bool> arg_allow_mismatched_daemon_version = {"allow-mismatched-daemon-version", sw::tr("Allow communicating with a daemon that uses a different RPC version"), false};
const command_line::arg_descriptor<uint64_t> arg_restore_height = {"restore-height", sw::tr("Restore from specific blockchain height"), 0};
const command_line::arg_descriptor<bool> arg_do_not_relay = {"do-not-relay", sw::tr("The newly created transaction will not be relayed to the monero network"), false};
@@ -380,21 +381,10 @@ namespace
boost::optional<std::pair<uint32_t, uint32_t>> parse_subaddress_lookahead(const std::string& str)
{
auto pos = str.find(":");
bool r = pos != std::string::npos;
uint32_t major;
r = r && epee::string_tools::get_xtype_from_string(major, str.substr(0, pos));
uint32_t minor;
r = r && epee::string_tools::get_xtype_from_string(minor, str.substr(pos + 1));
if (r)
{
return std::make_pair(major, minor);
}
else
{
auto r = tools::parse_subaddress_lookahead(str);
if (!r)
fail_msg_writer() << tr("invalid format for subaddress lookahead; must be <major>:<minor>");
return {};
}
return r;
}
void handle_transfer_exception(const std::exception_ptr &e, bool trusted_daemon)
@@ -640,7 +630,7 @@ bool simple_wallet::print_seed(bool encrypted)
epee::wipeable_string seed_pass;
if (encrypted)
{
auto pwd_container = password_prompter(tr("Enter optional seed encryption passphrase, empty to see raw seed"), true);
auto pwd_container = password_prompter(tr("Enter optional seed offset passphrase, empty to see raw seed"), true);
if (std::cin.eof() || !pwd_container)
return true;
seed_pass = pwd_container->password();
@@ -1077,7 +1067,7 @@ bool simple_wallet::import_multisig(const std::vector<std::string> &args)
fail_msg_writer() << tr("Failed to import multisig info: ") << e.what();
return true;
}
if (m_trusted_daemon)
if (is_daemon_trusted())
{
try
{
@@ -1229,7 +1219,7 @@ bool simple_wallet::submit_multisig(const std::vector<std::string> &args)
}
catch (const std::exception &e)
{
handle_transfer_exception(std::current_exception(), m_trusted_daemon);
handle_transfer_exception(std::current_exception(), is_daemon_trusted());
}
catch (...)
{
@@ -2027,7 +2017,7 @@ simple_wallet::simple_wallet()
tr("Stop mining in the daemon."));
m_cmd_binder.set_handler("set_daemon",
boost::bind(&simple_wallet::set_daemon, this, _1),
tr("set_daemon <host>[:<port>]"),
tr("set_daemon <host>[:<port>] [trusted|untrusted]"),
tr("Set another daemon to connect to."));
m_cmd_binder.set_handler("save_bc",
boost::bind(&simple_wallet::save_bc, this, _1),
@@ -2663,7 +2653,7 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
}
}
auto pwd_container = password_prompter(tr("Enter seed encryption passphrase, empty if none"), false);
auto pwd_container = password_prompter(tr("Enter seed offset passphrase, empty if none"), false);
if (std::cin.eof() || !pwd_container)
return false;
epee::wipeable_string seed_pass = pwd_container->password();
@@ -3117,18 +3107,22 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
return false;
}
// set --trusted-daemon if local
try
{
if (tools::is_local_address(m_wallet->get_daemon_address()))
{
MINFO(tr("Daemon is local, assuming trusted"));
m_trusted_daemon = true;
}
}
catch (const std::exception &e) { }
// set --trusted-daemon if local and not overridden
if (!m_trusted_daemon)
{
try
{
m_trusted_daemon = false;
if (tools::is_local_address(m_wallet->get_daemon_address()))
{
MINFO(tr("Daemon is local, assuming trusted"));
m_trusted_daemon = true;
}
}
catch (const std::exception &e) { }
}
if (!is_daemon_trusted())
message_writer() << (boost::format(tr("Warning: using an untrusted daemon at %s, privacy will be lessened")) % m_wallet->get_daemon_address()).str();
if (m_wallet->get_ring_database().empty())
@@ -3162,7 +3156,10 @@ bool simple_wallet::handle_command_line(const boost::program_options::variables_
m_restore_deterministic_wallet = command_line::get_arg(vm, arg_restore_deterministic_wallet);
m_restore_multisig_wallet = command_line::get_arg(vm, arg_restore_multisig_wallet);
m_non_deterministic = command_line::get_arg(vm, arg_non_deterministic);
m_trusted_daemon = command_line::get_arg(vm, arg_trusted_daemon);
if (!command_line::is_arg_defaulted(vm, arg_trusted_daemon) || !command_line::is_arg_defaulted(vm, arg_untrusted_daemon))
m_trusted_daemon = command_line::get_arg(vm, arg_trusted_daemon) && !command_line::get_arg(vm, arg_untrusted_daemon);
if (!command_line::is_arg_defaulted(vm, arg_trusted_daemon) && !command_line::is_arg_defaulted(vm, arg_untrusted_daemon))
message_writer() << tr("--trusted-daemon and --untrusted-daemon are both seen, assuming untrusted");
m_allow_mismatched_daemon_version = command_line::get_arg(vm, arg_allow_mismatched_daemon_version);
m_restore_height = command_line::get_arg(vm, arg_restore_height);
m_do_not_relay = command_line::get_arg(vm, arg_do_not_relay);
@@ -3649,7 +3646,7 @@ bool simple_wallet::save_watch_only(const std::vector<std::string> &args/* = std
//----------------------------------------------------------------------------------------------------
bool simple_wallet::start_mining(const std::vector<std::string>& args)
{
if (!m_trusted_daemon)
if (!is_daemon_trusted())
{
fail_msg_writer() << tr("this command requires a trusted daemon. Enable with --trusted-daemon");
return true;
@@ -3760,6 +3757,33 @@ bool simple_wallet::set_daemon(const std::vector<std::string>& args)
}
LOCK_IDLE_SCOPE();
m_wallet->init(daemon_url);
if (args.size() == 2)
{
if (args[1] == "trusted")
m_trusted_daemon = true;
else if (args[1] == "untrusted")
m_trusted_daemon = false;
else
{
fail_msg_writer() << tr("Expected trusted or untrusted, got ") << args[1] << ": assuming untrusted";
m_trusted_daemon = false;
}
}
else
{
m_trusted_daemon = false;
try
{
if (tools::is_local_address(m_wallet->get_daemon_address()))
{
MINFO(tr("Daemon is local, assuming trusted"));
m_trusted_daemon = true;
}
}
catch (const std::exception &e) { }
}
success_msg_writer() << boost::format("Daemon set to %s, %s") % daemon_url % (*m_trusted_daemon ? tr("trusted") : tr("untrusted"));
} else {
fail_msg_writer() << tr("This does not seem to be a valid daemon URL.");
}
@@ -4145,7 +4169,7 @@ bool simple_wallet::show_blockchain_height(const std::vector<std::string>& args)
//----------------------------------------------------------------------------------------------------
bool simple_wallet::rescan_spent(const std::vector<std::string> &args)
{
if (!m_trusted_daemon)
if (!is_daemon_trusted())
{
fail_msg_writer() << tr("this command requires a trusted daemon. Enable with --trusted-daemon");
return true;
@@ -4419,6 +4443,7 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri
}
vector<cryptonote::tx_destination_entry> dsts;
size_t num_subaddresses = 0;
for (size_t i = 0; i < local_args.size(); i += 2)
{
cryptonote::address_parse_info info;
@@ -4430,6 +4455,7 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri
}
de.addr = info.address;
de.is_subaddress = info.is_subaddress;
num_subaddresses += info.is_subaddress;
if (info.has_payment_id)
{
@@ -4462,7 +4488,7 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri
}
// prompt is there is no payment id and confirmation is required
if (!payment_id_seen && m_wallet->confirm_missing_payment_id())
if (!payment_id_seen && m_wallet->confirm_missing_payment_id() && dsts.size() > num_subaddresses)
{
std::string accepted = input_line(tr("No payment id is included with this transaction. Is this okay? (Y/Yes/N/No): "));
if (std::cin.eof())
@@ -4491,16 +4517,16 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri
return true;
}
unlock_block = bc_height + locked_blocks;
ptx_vector = m_wallet->create_transactions_2(dsts, fake_outs_count, unlock_block /* unlock_time */, priority, extra, m_current_subaddress_account, subaddr_indices, m_trusted_daemon);
ptx_vector = m_wallet->create_transactions_2(dsts, fake_outs_count, unlock_block /* unlock_time */, priority, extra, m_current_subaddress_account, subaddr_indices, is_daemon_trusted());
break;
case TransferNew:
ptx_vector = m_wallet->create_transactions_2(dsts, fake_outs_count, 0 /* unlock_time */, priority, extra, m_current_subaddress_account, subaddr_indices, m_trusted_daemon);
ptx_vector = m_wallet->create_transactions_2(dsts, fake_outs_count, 0 /* unlock_time */, priority, extra, m_current_subaddress_account, subaddr_indices, is_daemon_trusted());
break;
default:
LOG_ERROR("Unknown transfer method, using original");
/* FALLTHRU */
case TransferOriginal:
ptx_vector = m_wallet->create_transactions(dsts, fake_outs_count, 0 /* unlock_time */, priority, extra, m_trusted_daemon);
ptx_vector = m_wallet->create_transactions(dsts, fake_outs_count, 0 /* unlock_time */, priority, extra, is_daemon_trusted());
break;
}
@@ -4676,7 +4702,7 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri
}
catch (const std::exception &e)
{
handle_transfer_exception(std::current_exception(), m_trusted_daemon);
handle_transfer_exception(std::current_exception(), is_daemon_trusted());
}
catch (...)
{
@@ -4713,7 +4739,7 @@ bool simple_wallet::sweep_unmixable(const std::vector<std::string> &args_)
try
{
// figure out what tx will be necessary
auto ptx_vector = m_wallet->create_unmixable_sweep_transactions(m_trusted_daemon);
auto ptx_vector = m_wallet->create_unmixable_sweep_transactions(is_daemon_trusted());
if (ptx_vector.empty())
{
@@ -4782,9 +4808,23 @@ bool simple_wallet::sweep_unmixable(const std::vector<std::string> &args_)
commit_or_save(ptx_vector, m_do_not_relay);
}
}
catch (const tools::error::not_enough_unlocked_money& e)
{
fail_msg_writer() << tr("Not enough money in unlocked balance");
std::string accepted = input_line((boost::format(tr("Discarding %s of unmixable outputs that cannot be spent, which can be undone by \"rescan_spent\". Is this okay? (Y/Yes/N/No): ")) % print_money(e.available())).str());
if (std::cin.eof())
return true;
if (command_line::is_yes(accepted))
{
try
{
m_wallet->discard_unmixable_outputs(is_daemon_trusted());
} catch (...) {}
}
}
catch (const std::exception &e)
{
handle_transfer_exception(std::current_exception(), m_trusted_daemon);
handle_transfer_exception(std::current_exception(), is_daemon_trusted());
}
catch (...)
{
@@ -4915,7 +4955,7 @@ bool simple_wallet::sweep_main(uint64_t below, const std::vector<std::string> &a
}
// prompt is there is no payment id and confirmation is required
if (!payment_id_seen && m_wallet->confirm_missing_payment_id())
if (!payment_id_seen && m_wallet->confirm_missing_payment_id() && !info.is_subaddress)
{
std::string accepted = input_line(tr("No payment id is included with this transaction. Is this okay? (Y/Yes/N/No): "));
if (std::cin.eof())
@@ -4933,7 +4973,7 @@ bool simple_wallet::sweep_main(uint64_t below, const std::vector<std::string> &a
try
{
// figure out what tx will be necessary
auto ptx_vector = m_wallet->create_transactions_all(below, info.address, info.is_subaddress, fake_outs_count, 0 /* unlock_time */, priority, extra, m_current_subaddress_account, subaddr_indices, m_trusted_daemon);
auto ptx_vector = m_wallet->create_transactions_all(below, info.address, info.is_subaddress, fake_outs_count, 0 /* unlock_time */, priority, extra, m_current_subaddress_account, subaddr_indices, is_daemon_trusted());
if (ptx_vector.empty())
{
@@ -5017,7 +5057,7 @@ bool simple_wallet::sweep_main(uint64_t below, const std::vector<std::string> &a
}
catch (const std::exception& e)
{
handle_transfer_exception(std::current_exception(), m_trusted_daemon);
handle_transfer_exception(std::current_exception(), is_daemon_trusted());
}
catch (...)
{
@@ -5128,7 +5168,7 @@ bool simple_wallet::sweep_single(const std::vector<std::string> &args_)
}
// prompt if there is no payment id and confirmation is required
if (!payment_id_seen && m_wallet->confirm_missing_payment_id())
if (!payment_id_seen && m_wallet->confirm_missing_payment_id() && !info.is_subaddress)
{
std::string accepted = input_line(tr("No payment id is included with this transaction. Is this okay? (Y/Yes/N/No): "));
if (std::cin.eof())
@@ -5146,7 +5186,7 @@ bool simple_wallet::sweep_single(const std::vector<std::string> &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, m_trusted_daemon);
auto ptx_vector = m_wallet->create_transactions_single(ki, info.address, info.is_subaddress, fake_outs_count, 0 /* unlock_time */, priority, extra, is_daemon_trusted());
if (ptx_vector.empty())
{
@@ -5216,7 +5256,7 @@ bool simple_wallet::sweep_single(const std::vector<std::string> &args_)
}
catch (const std::exception& e)
{
handle_transfer_exception(std::current_exception(), m_trusted_daemon);
handle_transfer_exception(std::current_exception(), is_daemon_trusted());
}
catch (...)
{
@@ -5521,7 +5561,7 @@ bool simple_wallet::submit_transfer(const std::vector<std::string> &args_)
}
catch (const std::exception& e)
{
handle_transfer_exception(std::current_exception(), m_trusted_daemon);
handle_transfer_exception(std::current_exception(), is_daemon_trusted());
}
catch (...)
{
@@ -7109,7 +7149,7 @@ bool simple_wallet::import_key_images(const std::vector<std::string> &args)
fail_msg_writer() << tr("command not supported by HW wallet");
return true;
}
if (!m_trusted_daemon)
if (!is_daemon_trusted())
{
fail_msg_writer() << tr("this command requires a trusted daemon. Enable with --trusted-daemon");
return true;
@@ -7495,6 +7535,7 @@ int main(int argc, char* argv[])
command_line::add_arg(desc_params, arg_non_deterministic );
command_line::add_arg(desc_params, arg_electrum_seed );
command_line::add_arg(desc_params, arg_trusted_daemon);
command_line::add_arg(desc_params, arg_untrusted_daemon);
command_line::add_arg(desc_params, arg_allow_mismatched_daemon_version);
command_line::add_arg(desc_params, arg_restore_height);
command_line::add_arg(desc_params, arg_do_not_relay);
+2 -1
View File
@@ -229,6 +229,7 @@ namespace cryptonote
bool print_ring_members(const std::vector<tools::wallet2::pending_tx>& ptx_vector, std::ostream& ostr);
std::string get_prompt() const;
bool print_seed(bool encrypted);
bool is_daemon_trusted() const { return *m_trusted_daemon; }
/*!
* \brief Prints the seed with a nice message
@@ -331,7 +332,7 @@ namespace cryptonote
bool m_restore_deterministic_wallet; // recover flag
bool m_restore_multisig_wallet; // recover flag
bool m_non_deterministic; // old 2-random generation
bool m_trusted_daemon;
boost::optional<bool> m_trusted_daemon;
bool m_allow_mismatched_daemon_version;
bool m_restoring; // are we restoring, by whatever method?
uint64_t m_restore_height; // optional
+1 -1
View File
@@ -1,5 +1,5 @@
#define DEF_MONERO_VERSION_TAG "@VERSIONTAG@"
#define DEF_MONERO_VERSION "0.12.2.0"
#define DEF_MONERO_VERSION "0.12.3.0"
#define DEF_MONERO_RELEASE_NAME "Lithium Luna"
#define DEF_MONERO_VERSION_FULL DEF_MONERO_VERSION "-" DEF_MONERO_VERSION_TAG
+33 -2
View File
@@ -338,6 +338,7 @@ WalletImpl::WalletImpl(NetworkType nettype)
, m_trustedDaemon(false)
, m_wallet2Callback(nullptr)
, m_recoveringFromSeed(false)
, m_recoveringFromDevice(false)
, m_synchronized(false)
, m_rebuildWalletCache(false)
, m_is_connected(false)
@@ -385,6 +386,7 @@ bool WalletImpl::create(const std::string &path, const std::string &password, co
clearStatus();
m_recoveringFromSeed = false;
m_recoveringFromDevice = false;
bool keys_file_exists;
bool wallet_file_exists;
tools::wallet2::wallet_exists(path, keys_file_exists, wallet_file_exists);
@@ -584,11 +586,29 @@ bool WalletImpl::recoverFromKeysWithPassword(const std::string &path,
return true;
}
bool WalletImpl::recoverFromDevice(const std::string &path, const std::string &password, const std::string &device_name)
{
clearStatus();
m_recoveringFromSeed = false;
m_recoveringFromDevice = true;
try
{
m_wallet->restore(path, password, device_name);
LOG_PRINT_L1("Generated new wallet from device: " + device_name);
}
catch (const std::exception& e) {
m_errorString = string(tr("failed to generate new wallet: ")) + e.what();
m_status = Status_Error;
return false;
}
return true;
}
bool WalletImpl::open(const std::string &path, const std::string &password)
{
clearStatus();
m_recoveringFromSeed = false;
m_recoveringFromDevice = false;
try {
// TODO: handle "deprecated"
// Check if wallet cache exists
@@ -628,6 +648,7 @@ bool WalletImpl::recover(const std::string &path, const std::string &password, c
}
m_recoveringFromSeed = true;
m_recoveringFromDevice = false;
crypto::secret_key recovery_key;
std::string old_language;
if (!crypto::ElectrumWords::words_to_bytes(seed, recovery_key, old_language)) {
@@ -837,6 +858,16 @@ void WalletImpl::setRecoveringFromSeed(bool recoveringFromSeed)
m_recoveringFromSeed = recoveringFromSeed;
}
void WalletImpl::setRecoveringFromDevice(bool recoveringFromDevice)
{
m_recoveringFromDevice = recoveringFromDevice;
}
void WalletImpl::setSubaddressLookahead(uint32_t major, uint32_t minor)
{
m_wallet->set_subaddress_lookahead(major, minor);
}
uint64_t WalletImpl::balance(uint32_t accountIndex) const
{
return m_wallet->balance(accountIndex);
@@ -1752,7 +1783,7 @@ void WalletImpl::refreshThreadFunc()
// if auto refresh enabled, we wait for the "m_refreshIntervalSeconds" interval.
// if not - we wait forever
if (m_refreshIntervalMillis > 0) {
boost::posix_time::milliseconds wait_for_ms(m_refreshIntervalMillis);
boost::posix_time::milliseconds wait_for_ms(m_refreshIntervalMillis.load());
m_refreshCV.timed_wait(lock, wait_for_ms);
} else {
m_refreshCV.wait(lock);
@@ -1839,7 +1870,7 @@ bool WalletImpl::isNewWallet() const
// with the daemon (pull hashes instead of pull blocks).
// If wallet cache is rebuilt, creation height stored in .keys is used.
// Watch only wallet is a copy of an existing wallet.
return !(blockChainHeight() > 1 || m_recoveringFromSeed || m_rebuildWalletCache) && !watchOnly();
return !(blockChainHeight() > 1 || m_recoveringFromSeed || m_recoveringFromDevice || m_rebuildWalletCache) && !watchOnly();
}
bool WalletImpl::doInit(const string &daemon_address, uint64_t upper_transaction_size_limit, bool ssl)
+6
View File
@@ -76,6 +76,9 @@ public:
const std::string &address_string,
const std::string &viewkey_string,
const std::string &spendkey_string = "");
bool recoverFromDevice(const std::string &path,
const std::string &password,
const std::string &device_name);
bool close(bool store = true);
std::string seed() const;
std::string getSeedLanguage() const;
@@ -113,6 +116,8 @@ public:
void setRefreshFromBlockHeight(uint64_t refresh_from_block_height);
uint64_t getRefreshFromBlockHeight() const { return m_wallet->get_refresh_from_block_height(); };
void setRecoveringFromSeed(bool recoveringFromSeed);
void setRecoveringFromDevice(bool recoveringFromDevice);
void setSubaddressLookahead(uint32_t major, uint32_t minor);
bool watchOnly() const;
bool rescanSpent();
NetworkType nettype() const {return static_cast<NetworkType>(m_wallet->nettype());}
@@ -216,6 +221,7 @@ private:
// so it shouldn't be considered as new and pull blocks (slow-refresh)
// instead of pulling hashes (fast-refresh)
std::atomic<bool> m_recoveringFromSeed;
std::atomic<bool> m_recoveringFromDevice;
std::atomic<bool> m_synchronized;
std::atomic<bool> m_rebuildWalletCache;
// cache connection status to avoid unnecessary RPC calls
+32
View File
@@ -468,6 +468,21 @@ struct Wallet
*/
virtual void setRecoveringFromSeed(bool recoveringFromSeed) = 0;
/*!
* \brief setRecoveringFromDevice - set state to recovering from device
*
* \param recoveringFromDevice - true/false
*/
virtual void setRecoveringFromDevice(bool recoveringFromDevice) = 0;
/*!
* \brief setSubaddressLookahead - set size of subaddress lookahead
*
* \param major - size fot the major index
* \param minor - size fot the minor index
*/
virtual void setSubaddressLookahead(uint32_t major, uint32_t minor) = 0;
/**
* @brief connectToDaemon - connects to the daemon. TODO: check if it can be removed
* @return
@@ -916,6 +931,23 @@ struct WalletManager
return createWalletFromKeys(path, language, testnet ? TESTNET : MAINNET, restoreHeight, addressString, viewKeyString, spendKeyString);
}
/*!
* \brief creates wallet using hardware device.
* \param path Name of wallet file to be created
* \param password Password of wallet file
* \param nettype Network type
* \param deviceName Device name
* \param restoreHeight restore from start height (0 sets to current height)
* \param subaddressLookahead Size of subaddress lookahead (empty sets to some default low value)
* \return Wallet instance (Wallet::status() needs to be called to check if recovered successfully)
*/
virtual Wallet * createWalletFromDevice(const std::string &path,
const std::string &password,
NetworkType nettype,
const std::string &deviceName,
uint64_t restoreHeight = 0,
const std::string &subaddressLookahead = "") = 0;
/*!
* \brief Closes wallet. In case operation succeeded, wallet object deleted. in case operation failed, wallet object not deleted
* \param wallet previously opened / created wallet instance
+20
View File
@@ -114,6 +114,26 @@ Wallet *WalletManagerImpl::createWalletFromKeys(const std::string &path,
return wallet;
}
Wallet *WalletManagerImpl::createWalletFromDevice(const std::string &path,
const std::string &password,
NetworkType nettype,
const std::string &deviceName,
uint64_t restoreHeight,
const std::string &subaddressLookahead)
{
WalletImpl * wallet = new WalletImpl(nettype);
if(restoreHeight > 0){
wallet->setRefreshFromBlockHeight(restoreHeight);
}
auto lookahead = tools::parse_subaddress_lookahead(subaddressLookahead);
if (lookahead)
{
wallet->setSubaddressLookahead(lookahead->first, lookahead->second);
}
wallet->recoverFromDevice(path, password, deviceName);
return wallet;
}
bool WalletManagerImpl::closeWallet(Wallet *wallet, bool store)
{
WalletImpl * wallet_ = dynamic_cast<WalletImpl*>(wallet);
+6
View File
@@ -64,6 +64,12 @@ public:
const std::string &addressString,
const std::string &viewKeyString,
const std::string &spendKeyString = "");
virtual Wallet * createWalletFromDevice(const std::string &path,
const std::string &password,
NetworkType nettype,
const std::string &deviceName,
uint64_t restoreHeight = 0,
const std::string &subaddressLookahead = "");
virtual bool closeWallet(Wallet *wallet, bool store = true);
bool walletExists(const std::string &path);
bool verifyWalletPassword(const std::string &keys_file_name, const std::string &password, bool no_spend_key) const;
+100 -32
View File
@@ -940,6 +940,7 @@ void wallet2::expand_subaddresses(const cryptonote::subaddress_index& index)
}
m_subaddress_labels.resize(index.major + 1, {"Untitled account"});
m_subaddress_labels[index.major].resize(index.minor + 1);
get_account_tags();
}
else if (m_subaddress_labels[index.major].size() <= index.minor)
{
@@ -1029,6 +1030,16 @@ void wallet2::check_acc_out_precomp(const tx_out &o, const crypto::key_derivatio
tx_scan_info.error = false;
}
//----------------------------------------------------------------------------------------------------
void wallet2::check_acc_out_precomp_once(const tx_out &o, const crypto::key_derivation &derivation, const std::vector<crypto::key_derivation> &additional_derivations, size_t i, tx_scan_info_t &tx_scan_info, bool &already_seen) const
{
tx_scan_info.received = boost::none;
if (already_seen)
return;
check_acc_out_precomp(o, derivation, additional_derivations, i, tx_scan_info);
if (tx_scan_info.received)
already_seen = true;
}
//----------------------------------------------------------------------------------------------------
static uint64_t decodeRct(const rct::rctSig & rv, const crypto::key_derivation &derivation, unsigned int i, rct::key & mask, hw::device &hwdev)
{
crypto::secret_key scalar1;
@@ -1109,6 +1120,8 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
// Don't try to extract tx public key if tx has no ouputs
size_t pk_index = 0;
std::vector<tx_scan_info_t> tx_scan_info(tx.vout.size());
std::deque<bool> output_found(tx.vout.size(), false);
uint64_t total_received_1 = 0;
while (!tx.vout.empty())
{
// if tx.vout is not empty, we loop through all tx pubkeys
@@ -1143,13 +1156,16 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
// additional tx pubkeys and derivations for multi-destination transfers involving one or more subaddresses
std::vector<crypto::public_key> additional_tx_pub_keys = get_additional_tx_pub_keys_from_extra(tx);
std::vector<crypto::key_derivation> additional_derivations;
for (size_t i = 0; i < additional_tx_pub_keys.size(); ++i)
if (pk_index == 1)
{
additional_derivations.push_back({});
if (!hwdev.generate_key_derivation(additional_tx_pub_keys[i], keys.m_view_secret_key, additional_derivations.back()))
for (size_t i = 0; i < additional_tx_pub_keys.size(); ++i)
{
MWARNING("Failed to generate key derivation from tx pubkey, skipping");
additional_derivations.pop_back();
additional_derivations.push_back({});
if (!hwdev.generate_key_derivation(additional_tx_pub_keys[i], keys.m_view_secret_key, additional_derivations.back()))
{
MWARNING("Failed to generate key derivation from tx pubkey, skipping");
additional_derivations.pop_back();
}
}
}
hwdev_lock.unlock();
@@ -1160,7 +1176,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
}
else if (miner_tx && m_refresh_type == RefreshOptimizeCoinbase)
{
check_acc_out_precomp(tx.vout[0], derivation, additional_derivations, 0, tx_scan_info[0]);
check_acc_out_precomp_once(tx.vout[0], derivation, additional_derivations, 0, tx_scan_info[0], output_found[0]);
THROW_WALLET_EXCEPTION_IF(tx_scan_info[0].error, error::acc_outs_lookup_error, tx, tx_pub_key, m_account.get_keys());
// this assumes that the miner tx pays a single address
@@ -1170,8 +1186,8 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
// the first one was already checked
for (size_t i = 1; i < tx.vout.size(); ++i)
{
tpool.submit(&waiter, boost::bind(&wallet2::check_acc_out_precomp, this, std::cref(tx.vout[i]), std::cref(derivation), std::cref(additional_derivations), i,
std::ref(tx_scan_info[i])));
tpool.submit(&waiter, boost::bind(&wallet2::check_acc_out_precomp_once, this, std::cref(tx.vout[i]), std::cref(derivation), std::cref(additional_derivations), i,
std::ref(tx_scan_info[i]), std::ref(output_found[i])));
}
waiter.wait();
// then scan all outputs from 0
@@ -1193,8 +1209,8 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
{
for (size_t i = 0; i < tx.vout.size(); ++i)
{
tpool.submit(&waiter, boost::bind(&wallet2::check_acc_out_precomp, this, std::cref(tx.vout[i]), std::cref(derivation), std::cref(additional_derivations), i,
std::ref(tx_scan_info[i])));
tpool.submit(&waiter, boost::bind(&wallet2::check_acc_out_precomp_once, this, std::cref(tx.vout[i]), std::cref(derivation), std::cref(additional_derivations), i,
std::ref(tx_scan_info[i]), std::ref(output_found[i])));
}
waiter.wait();
@@ -1215,7 +1231,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
{
for (size_t i = 0; i < tx.vout.size(); ++i)
{
check_acc_out_precomp(tx.vout[i], derivation, additional_derivations, i, tx_scan_info[i]);
check_acc_out_precomp_once(tx.vout[i], derivation, additional_derivations, i, tx_scan_info[i], output_found[i]);
THROW_WALLET_EXCEPTION_IF(tx_scan_info[i].error, error::acc_outs_lookup_error, tx, tx_pub_key, m_account.get_keys());
if (tx_scan_info[i].received)
{
@@ -1251,6 +1267,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
+ ", m_transfers.size() is " + boost::lexical_cast<std::string>(m_transfers.size()));
if (kit == m_pub_keys.end())
{
uint64_t amount = tx.vout[o].amount ? tx.vout[o].amount : tx_scan_info[o].amount;
if (!pool)
{
m_transfers.push_back(boost::value_initialized<transfer_details>());
@@ -1263,14 +1280,13 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
td.m_key_image = tx_scan_info[o].ki;
td.m_key_image_known = !m_watch_only && !m_multisig;
td.m_key_image_partial = m_multisig;
td.m_amount = tx.vout[o].amount;
td.m_amount = amount;
td.m_pk_index = pk_index - 1;
td.m_subaddr_index = tx_scan_info[o].received->index;
expand_subaddresses(tx_scan_info[o].received->index);
if (td.m_amount == 0)
if (tx.vout[o].amount == 0)
{
td.m_mask = tx_scan_info[o].mask;
td.m_amount = tx_scan_info[o].amount;
td.m_rct = true;
}
else if (miner_tx && tx.version == 2)
@@ -1298,22 +1314,32 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
if (0 != m_callback)
m_callback->on_money_received(height, txid, tx, td.m_amount, td.m_subaddr_index);
}
total_received_1 += amount;
}
else if (m_transfers[kit->second].m_spent || m_transfers[kit->second].amount() >= tx.vout[o].amount)
else if (m_transfers[kit->second].m_spent || m_transfers[kit->second].amount() >= tx_scan_info[o].amount)
{
LOG_ERROR("Public key " << epee::string_tools::pod_to_hex(kit->first)
<< " from received " << print_money(tx.vout[o].amount) << " output already exists with "
<< " from received " << print_money(tx_scan_info[o].amount) << " output already exists with "
<< (m_transfers[kit->second].m_spent ? "spent" : "unspent") << " "
<< print_money(m_transfers[kit->second].amount()) << ", received output ignored");
<< print_money(m_transfers[kit->second].amount()) << " in tx " << m_transfers[kit->second].m_txid << ", received output ignored");
THROW_WALLET_EXCEPTION_IF(tx_money_got_in_outs[tx_scan_info[o].received->index] < tx_scan_info[o].amount,
error::wallet_internal_error, "Unexpected values of new and old outputs");
tx_money_got_in_outs[tx_scan_info[o].received->index] -= tx_scan_info[o].amount;
}
else
{
LOG_ERROR("Public key " << epee::string_tools::pod_to_hex(kit->first)
<< " from received " << print_money(tx.vout[o].amount) << " output already exists with "
<< " from received " << print_money(tx_scan_info[o].amount) << " output already exists with "
<< print_money(m_transfers[kit->second].amount()) << ", replacing with new output");
// The new larger output replaced a previous smaller one
tx_money_got_in_outs[tx_scan_info[o].received->index] -= tx.vout[o].amount;
THROW_WALLET_EXCEPTION_IF(tx_money_got_in_outs[tx_scan_info[o].received->index] < tx_scan_info[o].amount,
error::wallet_internal_error, "Unexpected values of new and old outputs");
THROW_WALLET_EXCEPTION_IF(m_transfers[kit->second].amount() > tx_scan_info[o].amount,
error::wallet_internal_error, "Unexpected values of new and old outputs");
tx_money_got_in_outs[tx_scan_info[o].received->index] -= m_transfers[kit->second].amount();
uint64_t amount = tx.vout[o].amount ? tx.vout[o].amount : tx_scan_info[o].amount;
uint64_t extra_amount = amount - m_transfers[kit->second].amount();
if (!pool)
{
transfer_details &td = m_transfers[kit->second];
@@ -1322,14 +1348,13 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
td.m_global_output_index = o_indices[o];
td.m_tx = (const cryptonote::transaction_prefix&)tx;
td.m_txid = txid;
td.m_amount = tx.vout[o].amount;
td.m_amount = amount;
td.m_pk_index = pk_index - 1;
td.m_subaddr_index = tx_scan_info[o].received->index;
expand_subaddresses(tx_scan_info[o].received->index);
if (td.m_amount == 0)
if (tx.vout[o].amount == 0)
{
td.m_mask = tx_scan_info[o].mask;
td.m_amount = tx_scan_info[o].amount;
td.m_rct = true;
}
else if (miner_tx && tx.version == 2)
@@ -1356,6 +1381,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
if (0 != m_callback)
m_callback->on_money_received(height, txid, tx, td.m_amount, td.m_subaddr_index);
}
total_received_1 += extra_amount;
}
}
}
@@ -1429,10 +1455,14 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
}
// remove change sent to the spending subaddress account from the list of received funds
uint64_t sub_change = 0;
for (auto i = tx_money_got_in_outs.begin(); i != tx_money_got_in_outs.end();)
{
if (subaddr_account && i->first.major == *subaddr_account)
{
sub_change += i->second;
i = tx_money_got_in_outs.erase(i);
}
else
++i;
}
@@ -1479,6 +1509,20 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
LOG_PRINT_L2("Found unencrypted payment ID: " << payment_id);
}
uint64_t total_received_2 = sub_change;
for (const auto& i : tx_money_got_in_outs)
total_received_2 += i.second;
if (total_received_1 != total_received_2)
{
const el::Level level = el::Level::Warning;
MCLOG_RED(level, "global", "**********************************************************************");
MCLOG_RED(level, "global", "Consistency failure in amounts received");
MCLOG_RED(level, "global", "Check transaction " << txid);
MCLOG_RED(level, "global", "**********************************************************************");
exit(1);
return;
}
for (const auto& i : tx_money_got_in_outs)
{
payment_details payment;
@@ -3260,6 +3304,12 @@ void wallet2::restore(const std::string& wallet_, const epee::wipeable_string& p
cryptonote::block b;
generate_genesis(b);
m_blockchain.push_back(get_block_hash(b));
if (m_subaddress_lookahead_major == SUBADDRESS_LOOKAHEAD_MAJOR && m_subaddress_lookahead_minor == SUBADDRESS_LOOKAHEAD_MINOR)
{
// the default lookahead setting (50:200) is clearly too much for hardware wallet
m_subaddress_lookahead_major = 5;
m_subaddress_lookahead_minor = 20;
}
add_subaddress_account(tr("Primary account"));
if (!wallet_.empty()) {
store();
@@ -3772,7 +3822,7 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass
{
wallet2::cache_file_data cache_file_data;
std::string buf;
bool r = epee::file_io_utils::load_file_to_string(m_wallet_file, buf);
bool r = epee::file_io_utils::load_file_to_string(m_wallet_file, buf, std::numeric_limits<size_t>::max());
THROW_WALLET_EXCEPTION_IF(!r, error::file_read_error, m_wallet_file);
// try to read it as an encrypted cache
@@ -7340,8 +7390,11 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
cryptonote::transaction tx;
pending_tx ptx;
size_t bytes;
uint64_t needed_fee;
std::vector<std::vector<tools::wallet2::get_outs_entry>> outs;
TX() : bytes(0), needed_fee(0) {}
void add(const account_public_address &addr, bool is_subaddress, uint64_t amount, unsigned int original_output_index, bool merge_destinations) {
if (merge_destinations)
{
@@ -7734,6 +7787,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
tx.ptx = test_ptx;
tx.bytes = txBlob.size();
tx.outs = outs;
tx.needed_fee = needed_fee;
accumulated_fee += test_ptx.fee;
accumulated_change += test_ptx.change_dts.amount;
adding_fee = false;
@@ -7785,7 +7839,7 @@ skip_tx:
fake_outs_count, /* CONST size_t fake_outputs_count, */
tx.outs, /* MOD std::vector<std::vector<tools::wallet2::get_outs_entry>> &outs, */
unlock_time, /* CONST uint64_t unlock_time, */
needed_fee, /* CONST uint64_t fee, */
tx.needed_fee, /* CONST uint64_t fee, */
extra, /* const std::vector<uint8_t>& extra, */
test_tx, /* OUT cryptonote::transaction& tx, */
test_ptx, /* OUT cryptonote::transaction& tx, */
@@ -7796,7 +7850,7 @@ skip_tx:
fake_outs_count,
tx.outs,
unlock_time,
needed_fee,
tx.needed_fee,
extra,
detail::digit_split_strategy,
tx_dust_policy(::config::DEFAULT_DUST_THRESHOLD),
@@ -7817,7 +7871,7 @@ skip_tx:
for (size_t idx: tx.selected_transfers)
tx_money += m_transfers[idx].amount();
LOG_PRINT_L1(" Transaction " << (1+std::distance(txes.begin(), i)) << "/" << txes.size() <<
": " << get_size_string(tx.bytes) << ", sending " << print_money(tx_money) << " in " << tx.selected_transfers.size() <<
" " << get_transaction_hash(tx.ptx.tx) << ": " << get_size_string(tx.bytes) << ", sending " << print_money(tx_money) << " in " << tx.selected_transfers.size() <<
" outputs to " << tx.dsts.size() << " destination(s), including " <<
print_money(tx.ptx.fee) << " fee, " << print_money(tx.ptx.change_dts.amount) << " change");
ptx_vector.push_back(tx.ptx);
@@ -7916,7 +7970,10 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton
cryptonote::transaction tx;
pending_tx ptx;
size_t bytes;
uint64_t needed_fee;
std::vector<std::vector<get_outs_entry>> outs;
TX() : bytes(0), needed_fee(0) {}
};
std::vector<TX> txes;
uint64_t needed_fee, available_for_fee = 0;
@@ -8014,6 +8071,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton
tx.ptx = test_ptx;
tx.bytes = txBlob.size();
tx.outs = outs;
tx.needed_fee = needed_fee;
accumulated_fee += test_ptx.fee;
accumulated_change += test_ptx.change_dts.amount;
if (!unused_transfers_indices.empty() || !unused_dust_indices.empty())
@@ -8034,10 +8092,10 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton
cryptonote::transaction test_tx;
pending_tx test_ptx;
if (use_rct) {
transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, tx.outs, unlock_time, needed_fee, extra,
transfer_selected_rct(tx.dsts, tx.selected_transfers, fake_outs_count, tx.outs, unlock_time, tx.needed_fee, extra,
test_tx, test_ptx, bulletproof);
} else {
transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, tx.outs, unlock_time, needed_fee, extra,
transfer_selected(tx.dsts, tx.selected_transfers, fake_outs_count, tx.outs, unlock_time, tx.needed_fee, extra,
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);
@@ -8054,7 +8112,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_from(const crypton
for (size_t idx: tx.selected_transfers)
tx_money += m_transfers[idx].amount();
LOG_PRINT_L1(" Transaction " << (1+std::distance(txes.begin(), i)) << "/" << txes.size() <<
": " << get_size_string(tx.bytes) << ", sending " << print_money(tx_money) << " in " << tx.selected_transfers.size() <<
" " << get_transaction_hash(tx.ptx.tx) << ": " << get_size_string(tx.bytes) << ", sending " << print_money(tx_money) << " in " << tx.selected_transfers.size() <<
" outputs to " << tx.dsts.size() << " destination(s), including " <<
print_money(tx.ptx.fee) << " fee, " << print_money(tx.ptx.change_dts.amount) << " change");
ptx_vector.push_back(tx.ptx);
@@ -8241,6 +8299,16 @@ std::vector<wallet2::pending_tx> wallet2::create_unmixable_sweep_transactions(bo
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<uint8_t>(), trusted_daemon);
}
//----------------------------------------------------------------------------------------------------
void wallet2::discard_unmixable_outputs(bool trusted_daemon)
{
// may throw
std::vector<size_t> unmixable_outputs = select_available_unmixable_outputs(trusted_daemon);
for (size_t idx : unmixable_outputs)
{
m_transfers[idx].m_spent = true;
}
}
bool wallet2::get_tx_key(const crypto::hash &txid, crypto::secret_key &tx_key, std::vector<crypto::secret_key> &additional_tx_keys) const
{
@@ -9145,9 +9213,9 @@ uint64_t wallet2::get_daemon_blockchain_target_height(string &err)
uint64_t wallet2::get_approximate_blockchain_height() const
{
// time of v2 fork
const time_t fork_time = m_nettype == TESTNET ? 1448285909 : m_nettype == STAGENET ? (time_t)-1/*TODO*/ : 1458748658;
const time_t fork_time = m_nettype == TESTNET ? 1448285909 : m_nettype == STAGENET ? 1520937818 : 1458748658;
// v2 fork block
const uint64_t fork_block = m_nettype == TESTNET ? 624634 : m_nettype == STAGENET ? (uint64_t)-1/*TODO*/ : 1009827;
const uint64_t fork_block = m_nettype == TESTNET ? 624634 : m_nettype == STAGENET ? 32000 : 1009827;
// avg seconds per block
const int seconds_per_block = DIFFICULTY_TARGET_V2;
// Calculated blockchain height
@@ -9523,7 +9591,7 @@ uint64_t wallet2::import_key_images(const std::vector<std::pair<crypto::key_imag
std::unordered_set<crypto::hash> spent_txids; // For each spent key image, search for a tx in m_transfers that uses it as input.
std::vector<size_t> swept_transfers; // If such a spending tx wasn't found in m_transfers, this means the spending tx
// was created by sweep_all, so we can't know the spent height and other detailed info.
for(size_t i = 0; i < m_transfers.size(); ++i)
for(size_t i = 0; i < signed_key_images.size(); ++i)
{
transfer_details &td = m_transfers[i];
uint64_t amount = td.amount();
+2
View File
@@ -704,6 +704,7 @@ namespace tools
bool sign_multisig_tx(multisig_tx_set &exported_txs, std::vector<crypto::hash> &txids);
bool sign_multisig_tx_to_file(multisig_tx_set &exported_txs, const std::string &filename, std::vector<crypto::hash> &txids);
std::vector<pending_tx> create_unmixable_sweep_transactions(bool trusted_daemon);
void discard_unmixable_outputs(bool trusted_daemon);
bool check_connection(uint32_t *version = NULL, uint32_t timeout = 200000);
void get_transfers(wallet2::transfer_container& incoming_transfers) const;
void get_payments(const crypto::hash& payment_id, std::list<wallet2::payment_details>& payments, uint64_t min_height = 0, const boost::optional<uint32_t>& subaddr_account = boost::none, const std::set<uint32_t>& subaddr_indices = {}) const;
@@ -1111,6 +1112,7 @@ namespace tools
bool generate_chacha_key_from_secret_keys(crypto::chacha_key &key) const;
crypto::hash get_payment_id(const pending_tx &ptx) const;
void check_acc_out_precomp(const cryptonote::tx_out &o, const crypto::key_derivation &derivation, const std::vector<crypto::key_derivation> &additional_derivations, size_t i, tx_scan_info_t &tx_scan_info) const;
void check_acc_out_precomp_once(const cryptonote::tx_out &o, const crypto::key_derivation &derivation, const std::vector<crypto::key_derivation> &additional_derivations, size_t i, tx_scan_info_t &tx_scan_info, bool &already_seen) const;
void parse_block_round(const cryptonote::blobdata &blob, cryptonote::block &bl, crypto::hash &bl_id, bool &error) const;
uint64_t get_upper_transaction_size_limit() const;
std::vector<uint64_t> get_unspent_amounts_vector() const;
+4
View File
@@ -179,6 +179,10 @@ namespace wallet_args
{
mlog_set_log(command_line::get_arg(vm, arg_log_level).c_str());
}
else if (!log_to_console)
{
mlog_set_categories("");
}
if (notice)
Print(print) << notice << ENDL;
+8
View File
@@ -362,6 +362,7 @@ namespace tools
if (!m_wallet) return not_open(er);
try
{
THROW_WALLET_EXCEPTION_IF(req.account_index >= m_wallet->get_num_subaddress_accounts(), error::account_index_outofbound);
res.addresses.clear();
std::vector<uint32_t> req_address_index;
if (req.address_index.empty())
@@ -377,6 +378,7 @@ namespace tools
m_wallet->get_transfers(transfers);
for (uint32_t i : req_address_index)
{
THROW_WALLET_EXCEPTION_IF(i >= m_wallet->get_num_subaddresses(req.account_index), error::address_index_outofbound);
res.addresses.resize(res.addresses.size() + 1);
auto& info = res.addresses.back();
const cryptonote::subaddress_index index = {req.account_index, i};
@@ -500,6 +502,7 @@ namespace tools
//------------------------------------------------------------------------------------------------------------------------------
bool wallet_rpc_server::on_get_account_tags(const wallet_rpc::COMMAND_RPC_GET_ACCOUNT_TAGS::request& req, wallet_rpc::COMMAND_RPC_GET_ACCOUNT_TAGS::response& res, epee::json_rpc::error& er)
{
if (!m_wallet) return not_open(er);
const std::pair<std::map<std::string, std::string>, std::vector<std::string>> account_tags = m_wallet->get_account_tags();
for (const std::pair<std::string, std::string>& p : account_tags.first)
{
@@ -518,6 +521,7 @@ namespace tools
//------------------------------------------------------------------------------------------------------------------------------
bool wallet_rpc_server::on_tag_accounts(const wallet_rpc::COMMAND_RPC_TAG_ACCOUNTS::request& req, wallet_rpc::COMMAND_RPC_TAG_ACCOUNTS::response& res, epee::json_rpc::error& er)
{
if (!m_wallet) return not_open(er);
try
{
m_wallet->set_account_tag(req.accounts, req.tag);
@@ -532,6 +536,7 @@ namespace tools
//------------------------------------------------------------------------------------------------------------------------------
bool wallet_rpc_server::on_untag_accounts(const wallet_rpc::COMMAND_RPC_UNTAG_ACCOUNTS::request& req, wallet_rpc::COMMAND_RPC_UNTAG_ACCOUNTS::response& res, epee::json_rpc::error& er)
{
if (!m_wallet) return not_open(er);
try
{
m_wallet->set_account_tag(req.accounts, "");
@@ -546,6 +551,7 @@ namespace tools
//------------------------------------------------------------------------------------------------------------------------------
bool wallet_rpc_server::on_set_account_tag_description(const wallet_rpc::COMMAND_RPC_SET_ACCOUNT_TAG_DESCRIPTION::request& req, wallet_rpc::COMMAND_RPC_SET_ACCOUNT_TAG_DESCRIPTION::response& res, epee::json_rpc::error& er)
{
if (!m_wallet) return not_open(er);
try
{
m_wallet->set_account_tag_description(req.tag, req.description);
@@ -2054,6 +2060,7 @@ namespace tools
//------------------------------------------------------------------------------------------------------------------------------
bool wallet_rpc_server::on_make_uri(const wallet_rpc::COMMAND_RPC_MAKE_URI::request& req, wallet_rpc::COMMAND_RPC_MAKE_URI::response& res, epee::json_rpc::error& er)
{
if (!m_wallet) return not_open(er);
std::string error;
std::string uri = m_wallet->make_uri(req.address, req.payment_id, req.amount, req.tx_description, req.recipient_name, error);
if (uri.empty())
@@ -2267,6 +2274,7 @@ namespace tools
//------------------------------------------------------------------------------------------------------------------------------
bool wallet_rpc_server::on_stop_mining(const wallet_rpc::COMMAND_RPC_STOP_MINING::request& req, wallet_rpc::COMMAND_RPC_STOP_MINING::response& res, epee::json_rpc::error& er)
{
if (!m_wallet) return not_open(er);
cryptonote::COMMAND_RPC_STOP_MINING::request daemon_req;
cryptonote::COMMAND_RPC_STOP_MINING::response daemon_res;
bool r = m_wallet->invoke_http_json("/stop_mining", daemon_req, daemon_res);
+1
View File
@@ -158,6 +158,7 @@ namespace
}
virtual bool close() { return true; }
virtual bool send_done() { return true; }
virtual bool call_run_once_service_io() { return true; }
virtual bool request_callback() { return true; }
virtual boost::asio::io_service& get_io_service() { return m_io_service; }
@@ -150,6 +150,7 @@ namespace
}
virtual bool close() { /*std::cout << "test_connection::close()" << std::endl; */return true; }
virtual bool send_done() { /*std::cout << "test_connection::send_done()" << std::endl; */return true; }
virtual bool call_run_once_service_io() { std::cout << "test_connection::call_run_once_service_io()" << std::endl; return true; }
virtual bool request_callback() { std::cout << "test_connection::request_callback()" << std::endl; return true; }
virtual boost::asio::io_service& get_io_service() { std::cout << "test_connection::get_io_service()" << std::endl; return m_io_service; }