mirror of
https://github.com/feather-wallet/feather.git
synced 2025-01-03 17:39:49 +00:00
Merge feather 2.7.0
This commit is contained in:
commit
5f26201cdf
191 changed files with 1623 additions and 1300 deletions
11
.github/workflows/guix.yml
vendored
11
.github/workflows/guix.yml
vendored
|
@ -80,7 +80,18 @@ jobs:
|
||||||
- uses: actions/download-artifact@v4
|
- uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
merge-multiple: true
|
merge-multiple: true
|
||||||
|
- name: print hashes
|
||||||
|
run: |
|
||||||
|
echo '```' >> $GITHUB_STEP_SUMMARY
|
||||||
|
uname --machine && find **/output/ -type f -print0 | env LC_ALL=C sort -z | xargs -r0 sha256sum >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo '```' >> $GITHUB_STEP_SUMMARY
|
||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: "logs"
|
name: "logs"
|
||||||
path: '**/logs/**'
|
path: '**/logs/**'
|
||||||
|
- uses: ncipollo/release-action@v1
|
||||||
|
if: startsWith(github.ref, 'refs/tags/')
|
||||||
|
with:
|
||||||
|
artifacts: "**/*.AppImage,**/*-linux-arm.zip,**/*-linux-arm64.zip,**/*-linux-riscv64.zip,**/*-linux.zip,**/*-mac-arm64.zip,**/*-mac.zip,**/*-win.zip,**/FeatherWalletSetup-*.exe,**/feather-{{github.ref_name}}.tar.gz"
|
||||||
|
draft: true
|
||||||
|
name: v${{github.ref_name}}
|
||||||
|
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,6 +1,7 @@
|
||||||
.DS_Store
|
.DS_Store
|
||||||
lib/*
|
lib/*
|
||||||
cmake-build-debug/*
|
cmake-build-debug/*
|
||||||
|
cmake-build-release/*
|
||||||
.idea
|
.idea
|
||||||
*.user
|
*.user
|
||||||
*.stash
|
*.stash
|
||||||
|
|
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -1,9 +1,6 @@
|
||||||
[submodule "monero"]
|
[submodule "monero"]
|
||||||
path = monero
|
path = monero
|
||||||
url = https://github.com/feather-wallet/monero.git
|
url = https://github.com/feather-wallet/monero.git
|
||||||
[submodule "src/third-party/singleapplication"]
|
|
||||||
path = src/third-party/singleapplication
|
|
||||||
url = https://github.com/itay-grudev/SingleApplication.git
|
|
||||||
[submodule "src/third-party/polyseed"]
|
[submodule "src/third-party/polyseed"]
|
||||||
path = src/third-party/polyseed
|
path = src/third-party/polyseed
|
||||||
url = https://github.com/tevador/polyseed.git
|
url = https://github.com/tevador/polyseed.git
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
cmake_minimum_required(VERSION 3.18)
|
cmake_minimum_required(VERSION 3.18)
|
||||||
|
|
||||||
project(feather
|
project(feather
|
||||||
VERSION "2.6.8"
|
VERSION "2.7.0"
|
||||||
DESCRIPTION "A free Monero desktop wallet"
|
DESCRIPTION "A free Monero desktop wallet"
|
||||||
LANGUAGES CXX C ASM
|
LANGUAGES CXX C ASM
|
||||||
)
|
)
|
||||||
|
@ -15,6 +15,8 @@ set(PACKAGE_URL "https://featherwallet.org/")
|
||||||
set(COPYRIGHT_YEAR "2024")
|
set(COPYRIGHT_YEAR "2024")
|
||||||
set(COPYRIGHT_HOLDERS "The Monero Project")
|
set(COPYRIGHT_HOLDERS "The Monero Project")
|
||||||
|
|
||||||
|
cmake_policy(SET CMP0074 NEW)
|
||||||
|
|
||||||
# Configurable options
|
# Configurable options
|
||||||
option(STATIC "Link libraries statically, requires static Qt" OFF)
|
option(STATIC "Link libraries statically, requires static Qt" OFF)
|
||||||
option(SELF_CONTAINED "Disable when building Feather for packages" OFF)
|
option(SELF_CONTAINED "Disable when building Feather for packages" OFF)
|
||||||
|
@ -71,9 +73,7 @@ if (NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/monero/CMakeLists.txt")
|
||||||
message(FATAL_ERROR "'monero/CMakeLists.txt' does not exist, did you forget to:\ngit submodule update --init --recursive --progress")
|
message(FATAL_ERROR "'monero/CMakeLists.txt' does not exist, did you forget to:\ngit submodule update --init --recursive --progress")
|
||||||
endif()
|
endif()
|
||||||
add_subdirectory(monero EXCLUDE_FROM_ALL)
|
add_subdirectory(monero EXCLUDE_FROM_ALL)
|
||||||
set_property(TARGET wallet_merged PROPERTY FOLDER "monero")
|
|
||||||
get_directory_property(ARCH_WIDTH DIRECTORY "monero" DEFINITION ARCH_WIDTH)
|
get_directory_property(ARCH_WIDTH DIRECTORY "monero" DEFINITION ARCH_WIDTH)
|
||||||
get_directory_property(UNBOUND_LIBRARY DIRECTORY "monero" DEFINITION UNBOUND_LIBRARY)
|
|
||||||
get_directory_property(DEVICE_TREZOR_READY DIRECTORY "monero" DEFINITION DEVICE_TREZOR_READY)
|
get_directory_property(DEVICE_TREZOR_READY DIRECTORY "monero" DEFINITION DEVICE_TREZOR_READY)
|
||||||
get_directory_property(TREZOR_DEP_LIBS DIRECTORY "monero" DEFINITION TREZOR_DEP_LIBS)
|
get_directory_property(TREZOR_DEP_LIBS DIRECTORY "monero" DEFINITION TREZOR_DEP_LIBS)
|
||||||
get_directory_property(OPENBSD DIRECTORY "monero" DEFINITION OPENBSD)
|
get_directory_property(OPENBSD DIRECTORY "monero" DEFINITION OPENBSD)
|
||||||
|
@ -90,10 +90,6 @@ endif()
|
||||||
# pthread
|
# pthread
|
||||||
find_package(Threads REQUIRED)
|
find_package(Threads REQUIRED)
|
||||||
|
|
||||||
# Sodium
|
|
||||||
find_library(SODIUM_LIBRARY sodium)
|
|
||||||
message(STATUS "libsodium: libraries at ${SODIUM_LIBRARY}")
|
|
||||||
|
|
||||||
# QrEncode
|
# QrEncode
|
||||||
find_package(QREncode REQUIRED)
|
find_package(QREncode REQUIRED)
|
||||||
|
|
||||||
|
@ -136,27 +132,12 @@ if(MINGW)
|
||||||
set(MINGW_FLAG "${MINGW_FLAG} -DWIN32_LEAN_AND_MEAN")
|
set(MINGW_FLAG "${MINGW_FLAG} -DWIN32_LEAN_AND_MEAN")
|
||||||
set(Boost_THREADAPI win32)
|
set(Boost_THREADAPI win32)
|
||||||
endif()
|
endif()
|
||||||
|
set(Boost_USE_MULTITHREADED ON)
|
||||||
set(BOOST_COMPONENTS
|
|
||||||
system
|
|
||||||
filesystem
|
|
||||||
thread
|
|
||||||
date_time
|
|
||||||
chrono
|
|
||||||
regex
|
|
||||||
serialization
|
|
||||||
program_options
|
|
||||||
locale
|
|
||||||
)
|
|
||||||
|
|
||||||
if(STACK_TRACE AND UNIX AND NOT APPLE)
|
if(STACK_TRACE AND UNIX AND NOT APPLE)
|
||||||
list(APPEND BOOST_COMPONENTS
|
find_package(Boost 1.58 REQUIRED COMPONENTS stacktrace_basic)
|
||||||
stacktrace_basic)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(Boost_USE_MULTITHREADED ON)
|
|
||||||
find_package(Boost 1.58 REQUIRED COMPONENTS ${BOOST_COMPONENTS})
|
|
||||||
|
|
||||||
if(UNIX AND NOT APPLE)
|
if(UNIX AND NOT APPLE)
|
||||||
if (NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
|
if (NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||||
# https://github.com/monero-project/monero-gui/issues/3142#issuecomment-705940446
|
# https://github.com/monero-project/monero-gui/issues/3142#issuecomment-705940446
|
||||||
|
@ -250,13 +231,6 @@ if (NOT WIN32 AND NOT OPENBSD AND NOT "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang"
|
||||||
add_cxx_flag_if_supported(-fstack-clash-protection CXX_SECURITY_FLAGS)
|
add_cxx_flag_if_supported(-fstack-clash-protection CXX_SECURITY_FLAGS)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# -mmitigate-rop
|
|
||||||
# removed in GCC 9.1 (or before ?), but still accepted, so spams the output
|
|
||||||
if (NOT (CMAKE_C_COMPILER_ID STREQUAL "GNU" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 9.1))
|
|
||||||
add_c_flag_if_supported(-mmitigate-rop C_SECURITY_FLAGS)
|
|
||||||
add_cxx_flag_if_supported(-mmitigate-rop CXX_SECURITY_FLAGS)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# linker
|
# linker
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
add_linker_flag_if_supported(-Wl,-bind_at_load LD_SECURITY_FLAGS)
|
add_linker_flag_if_supported(-Wl,-bind_at_load LD_SECURITY_FLAGS)
|
||||||
|
|
20
HACKING.md
20
HACKING.md
|
@ -1,29 +1,26 @@
|
||||||
# Documentation for developers
|
# Documentation for developers
|
||||||
|
|
||||||
Feather is developed primarily on Linux, but can also be built and debugged on macOS. Development on Windows is not
|
Feather is developed primarily on Linux, but can also be built on macOS. Development on Windows is not currently supported.
|
||||||
currently supported.
|
|
||||||
|
We support development on rolling release distributions and the latest version of Ubuntu. Building on older stable distributions is not guaranteed to work.
|
||||||
|
|
||||||
## Setting up a development environment
|
## Setting up a development environment
|
||||||
|
|
||||||
### Dependencies
|
### Dependencies
|
||||||
|
|
||||||
Note: Feather requires Qt 6.3 or later. Make sure your distro's package manager provides this version.
|
|
||||||
If not, it is recommended that you install Qt manually using the online installer, which can be found here:
|
|
||||||
https://www.qt.io/download (under open-source).
|
|
||||||
|
|
||||||
#### Arch Linux
|
#### Arch Linux
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pacman -S git cmake base-devel ccache unbound boost qrencode qt6-base qt6-svg qt6-websockets qt6-multimedia libzip hidapi protobuf zxing-cpp
|
pacman -S git cmake base-devel ccache unbound boost qrencode qt6-base qt6-svg qt6-websockets qt6-multimedia libzip hidapi protobuf zxing-cpp
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Ubuntu 22.04
|
#### Ubuntu 24.04
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
apt update
|
apt update
|
||||||
apt install git cmake build-essential ccache libssl-dev libunbound-dev libboost-all-dev libqrencode-dev \
|
apt install git cmake build-essential ccache libssl-dev libunbound-dev libboost-all-dev libqrencode-dev \
|
||||||
qt6-base-dev libgl1-mesa-dev libqt6svg6-dev libqt6websockets6-dev libzip-dev libsodium-dev libgcrypt-dev \
|
qt6-base-dev qt6-multimedia-dev libgl1-mesa-dev libqt6svg6-dev libqt6websockets6-dev libzip-dev libsodium-dev libgcrypt-dev \
|
||||||
libx11-xcb-dev libprotobuf-dev libhidapi-dev libzxing-dev
|
libx11-xcb-dev libprotobuf-dev protobuf-compiler libhidapi-dev libzxing-dev
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Void Linux
|
#### Void Linux
|
||||||
|
@ -92,9 +89,8 @@ git submodule update --init --recursive
|
||||||
We recommend using Jetbrains Clion for Feather development. It integrates nicely with CMake and comes with a built-in
|
We recommend using Jetbrains Clion for Feather development. It integrates nicely with CMake and comes with a built-in
|
||||||
debugger.
|
debugger.
|
||||||
|
|
||||||
To pass CMake flags to CLion, go to `File->Settings->Build->CMake`, set Build Type to `Debug` and set your
|
To pass CMake flags to CLion, go to `File -> Settings -> Build -> CMake`, set Build Type to `Debug` and set your
|
||||||
preferred CMake options. If you installed Qt using the online installer you may have to add
|
preferred CMake options. More CMake options are documented below.
|
||||||
`-DCMAKE_PREFIX_PATH=/path/to/qt/installation` in the CMake options. More CMake options are documented below.
|
|
||||||
|
|
||||||
Run CMake (`View -> Tool Windows -> CMake`). Click on the 🔃 (`Reload CMake Project`) button.
|
Run CMake (`View -> Tool Windows -> CMake`). Click on the 🔃 (`Reload CMake Project`) button.
|
||||||
|
|
||||||
|
|
|
@ -13,20 +13,36 @@ This document is written for developers and users interested in learning how Fea
|
||||||
- Review the diff of any altered package to mitigate the risk of supply chain attacks
|
- Review the diff of any altered package to mitigate the risk of supply chain attacks
|
||||||
- Update compilers and security flags for better binary security
|
- Update compilers and security flags for better binary security
|
||||||
- Reduce the number of third-party dependencies
|
- Reduce the number of third-party dependencies
|
||||||
- Keep the website VPS up-to-date and secure
|
- Keep the [website](https://github.com/feather-wallet/feather-site/blob/master/mirrors.txt) VPS up-to-date and secure
|
||||||
- Further harden the [release process](RELEASE.md)
|
- Contact relevant authorities to take [phishing sites](https://gist.github.com/tobtoht/4039fa3cf922d4fe8bca2f8e3ddac63b) offline
|
||||||
|
- Make improvements to the [release process](RELEASE.md)
|
||||||
|
|
||||||
Goals:
|
Goals:
|
||||||
|
|
||||||
- Set up a bug bounty program for issues that affect privacy or security
|
- Set up a bug bounty program for issues that affect privacy or security
|
||||||
- Set up a status page with information about project health
|
- Set up a status page with information about project health
|
||||||
- Set up a feed for security bulletins
|
- Set up a feed for security bulletins
|
||||||
|
- Sandbox components that handle untrusted input (e.g. QR code scanner)
|
||||||
|
- Create a package manager for secure distribution of portable binaries
|
||||||
|
- `-static-pie` release binaries for Linux targets
|
||||||
|
|
||||||
Security issues that affect Feather always warrant a new release as soon as possible.
|
Security issues that affect Feather always warrant a new release as soon as possible.
|
||||||
|
|
||||||
### 2. Reproducibility
|
### 2. Continuity
|
||||||
|
|
||||||
- Improve and maintain tools to check for reproducibility defects
|
- Keep the website and services online
|
||||||
|
- Keep source repositories accessible
|
||||||
|
- Make sure that running release builds is easy to set up and reproducible in time
|
||||||
|
|
||||||
|
Goals:
|
||||||
|
|
||||||
|
- Make sure the project is transmissible
|
||||||
|
- Make sure that setting up release infrastructure, release engineering, and maintenance are extensively documented
|
||||||
|
- Make the websocket server repository public
|
||||||
|
|
||||||
|
### 3. Reproducibility
|
||||||
|
|
||||||
|
- Improve and maintain tools to check for non-determinism
|
||||||
- Ensure releases are reproducible and stay that way
|
- Ensure releases are reproducible and stay that way
|
||||||
- Upload source archives to the fallback mirror
|
- Upload source archives to the fallback mirror
|
||||||
|
|
||||||
|
@ -36,31 +52,32 @@ To learn more about Feather's build system, see: [`contrib/guix/README.md`](http
|
||||||
Our Guix time-machine is currently pinned at a commit which implements the
|
Our Guix time-machine is currently pinned at a commit which implements the
|
||||||
[Full-Source Bootstrap](https://guix.gnu.org/en/blog/2023/the-full-source-bootstrap-building-from-source-all-the-way-down/).
|
[Full-Source Bootstrap](https://guix.gnu.org/en/blog/2023/the-full-source-bootstrap-building-from-source-all-the-way-down/).
|
||||||
|
|
||||||
### 3. Bugs
|
### 4. Bugs
|
||||||
|
|
||||||
- Fix reproducible bugs and crashes
|
- Fix bugs and crashes
|
||||||
|
|
||||||
To report a bug, please see: https://docs.featherwallet.org/guides/report-an-issue
|
To report a bug, please see: https://docs.featherwallet.org/guides/report-an-issue
|
||||||
|
|
||||||
### 4. Tests
|
### 5. Tests
|
||||||
|
|
||||||
- Improve test coverage
|
- Improve test coverage
|
||||||
- Write more test cases
|
- Write more test cases
|
||||||
|
|
||||||
Feather does not currently have a test suite (apart from the tests in the Monero submodule), this is a WIP.
|
Feather does not currently have a test suite (apart from the tests in the Monero submodule), this is a WIP.
|
||||||
|
|
||||||
### 5. Documentation
|
### 6. Documentation
|
||||||
|
|
||||||
- Make sure the documentation accurately reflects the latest release
|
- Make sure the documentation accurately reflects the latest release
|
||||||
- Add troubleshooting guides for common problems
|
- Add troubleshooting guides for common problems
|
||||||
- Ideally, most support questions can be answered with a link to the documentation
|
|
||||||
|
|
||||||
Goals:
|
Goals:
|
||||||
|
- Most support questions can be answered with a link to the documentation
|
||||||
- Reconsider and document default settings
|
- Reconsider and document default settings
|
||||||
|
- Write a document on threat modeling
|
||||||
|
|
||||||
Documentation is available at https://docs.featherwallet.org
|
Documentation is available at https://docs.featherwallet.org
|
||||||
|
|
||||||
### 6. Improvements
|
### 7. Improvements
|
||||||
|
|
||||||
- Improve existing features
|
- Improve existing features
|
||||||
- Improve UI/UX
|
- Improve UI/UX
|
||||||
|
@ -68,19 +85,15 @@ Documentation is available at https://docs.featherwallet.org
|
||||||
Feather should first and foremost be a good __wallet__.
|
Feather should first and foremost be a good __wallet__.
|
||||||
Improving features that are closer to this end should have priority.
|
Improving features that are closer to this end should have priority.
|
||||||
|
|
||||||
### 7. Packaging
|
### 8. Platform Support
|
||||||
|
|
||||||
- Add support for more architectures and operating systems
|
- Add support for more architectures and operating systems
|
||||||
- Drop support for End-of-Life distributions
|
- Drop support for End-of-Life distributions
|
||||||
|
- Add support for new hardware wallets
|
||||||
Goals:
|
|
||||||
|
|
||||||
- Debian and Guix packages
|
|
||||||
- Create a document with guidelines for packagers
|
|
||||||
|
|
||||||
See: https://docs.featherwallet.org/guides/supported-operating-systems
|
See: https://docs.featherwallet.org/guides/supported-operating-systems
|
||||||
|
|
||||||
### 8. Optimization, cleanup and continuity
|
### 9. Optimization
|
||||||
|
|
||||||
Miscellaneous maintenance tasks.
|
Miscellaneous maintenance tasks.
|
||||||
|
|
||||||
|
@ -98,9 +111,9 @@ Miscellaneous maintenance tasks.
|
||||||
|
|
||||||
Goals:
|
Goals:
|
||||||
|
|
||||||
- Make sure Feather is ready for the migration to [Seraphis](https://github.com/seraphis-migration/wallet3)
|
- Make sure Feather is ready for the migration to [FCMP++](https://www.getmonero.org/2024/04/27/fcmps.html)
|
||||||
|
|
||||||
### 9. Features
|
### 10. Features
|
||||||
|
|
||||||
- Implement new features
|
- Implement new features
|
||||||
- Allow Feather to be used or configured for higher, esoteric or new threat models
|
- Allow Feather to be used or configured for higher, esoteric or new threat models
|
||||||
|
@ -112,7 +125,7 @@ compared to its expected maintenance and support burden.
|
||||||
|
|
||||||
For a non-exhaustive list of potentially new features, see: https://featherwallet.org/ideas
|
For a non-exhaustive list of potentially new features, see: https://featherwallet.org/ideas
|
||||||
|
|
||||||
### 10. Upstreaming
|
### 11. Upstreaming
|
||||||
|
|
||||||
- Upstream tried and tested features, bugfixes and useful patches
|
- Upstream tried and tested features, bugfixes and useful patches
|
||||||
- Bugfixes should be upstreamed without delay
|
- Bugfixes should be upstreamed without delay
|
||||||
|
|
40
README.md
40
README.md
|
@ -37,27 +37,29 @@ If for some reason the swap isn't able to be completed when ran, one party goes
|
||||||
|
|
||||||
https://github.com/user-attachments/assets/b7871a2f-21d0-46e2-b575-b9ba885a810d
|
https://github.com/user-attachments/assets/b7871a2f-21d0-46e2-b575-b9ba885a810d
|
||||||
|
|
||||||
#### This video has been speed up in multiple sections time on the top right is accurate to real life time.
|
For release policy, see: [RELEASE.md](https://github.com/feather-wallet/feather/blob/master/RELEASE.md)
|
||||||
## Resources
|
|
||||||
|
|
||||||
* Web: [featherwallet.org](https://featherwallet.org)
|
|
||||||
* Docs: [docs.featherwallet.org](https://docs.featherwallet.org)
|
|
||||||
* Git: [github.com/feather-wallet/feather](https://github.com/feather-wallet/feather)
|
|
||||||
* Reddit: [/r/FeatherWallet](https://old.reddit.com/r/FeatherWallet)
|
|
||||||
* Lemmy: [monero.town/c/featherwallet](https://monero.town/c/featherwallet)
|
|
||||||
* Mail: dev@featherwallet.org
|
|
||||||
* IRC: `#feather` on [OFTC](https://www.oftc.net/)
|
|
||||||
* Matrix: [matrix.to/#/#feather:monero.social](https://matrix.to/#/#feather:monero.social)
|
|
||||||
|
|
||||||
|
|
||||||
## Deterministic builds
|
|
||||||
|
|
||||||
See [contrib/guix/README.md](https://github.com/feather-wallet/feather/blob/master/contrib/guix/README.md) for more information.
|
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|
||||||
If you are looking to set up a development environment for Feather, see [HACKING.md](https://github.com/feather-wallet/feather/blob/master/HACKING.md).
|
If you are looking to set up a development environment for Feather, see [HACKING.md](https://github.com/feather-wallet/feather/blob/master/HACKING.md).
|
||||||
|
|
||||||
It is highly recommended that you join the `#feather` IRC channel on [OFTC](https://www.oftc.net/) or [`#feather:monero.social`](https://matrix.to/#/#feather:monero.social) on Matrix if you
|
It is highly recommended that you join our Matrix or IRC channel if you are hacking on Feather.
|
||||||
are hacking on Feather. Due to the nature of this open source software project, idling in this channel is the best
|
Idling in this channel is the best way to stay updated on best practices and new developments.
|
||||||
way to stay updated on best practices and new developments.
|
|
||||||
|
For information on how Feather is maintained, see: [MAINTENANCE.md](https://github.com/feather-wallet/feather/blob/master/MAINTENANCE.md)
|
||||||
|
|
||||||
|
To report a security vulnerability, see: [SECURITY.md](https://github.com/feather-wallet/feather/blob/master/SECURITY.md)
|
||||||
|
|
||||||
|
## Support
|
||||||
|
|
||||||
|
Feather is funded entirely through donations. We don't take a cut from transaction fees and make no money from exchange integrations.
|
||||||
|
|
||||||
|
Donations help pay for hosting, build servers, domain names, e-mail and other recurring costs. Any amount helps.
|
||||||
|
|
||||||
|
`47ntfT2Z5384zku39pTM6hGcnLnvpRYW2Azm87GiAAH2bcTidtq278TL6HmwyL8yjMeERqGEBs3cqC8vvHPJd1cWQrGC65f`
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Feather is free and open-source software, [licensed under BSD-3](https://raw.githubusercontent.com/feather-wallet/feather/master/LICENSE).
|
||||||
|
|
||||||
|
Copyright (c) 2020-2024, The Monero Project
|
||||||
|
|
29
SECURITY.md
29
SECURITY.md
|
@ -13,3 +13,32 @@ The following keys may be used to communicate sensitive information to developer
|
||||||
| tobtoht | E87B D921 CDD8 85C9 D78A 38C5 E45B 10DD 027D 2472 |
|
| tobtoht | E87B D921 CDD8 85C9 D78A 38C5 E45B 10DD 027D 2472 |
|
||||||
|
|
||||||
Public keys can be found in [`utils/pubkeys`](utils/pubkeys).
|
Public keys can be found in [`utils/pubkeys`](utils/pubkeys).
|
||||||
|
|
||||||
|
## Bug Bounty Program
|
||||||
|
|
||||||
|
A bounty may be rewarded to a vulnerability report **if and only if** the issue can result in **a loss of funds**.
|
||||||
|
|
||||||
|
You must describe a **plausible scenario** in which a loss of funds can occur (or has occurred) that **isn't solely attributable to user error**.
|
||||||
|
|
||||||
|
Only **the code** of the **latest tagged release** of **[this repository](https://github.com/feather-wallet/feather/)** is in scope.
|
||||||
|
|
||||||
|
**The bounty can only be rewarded in XMR**. The bounty amount for your report is determined by the maintainers and ranges from USD 150 to USD 3000 (in terms of XMR) and depends on the severity of the issue and other factors.
|
||||||
|
|
||||||
|
Clarifications on scope:
|
||||||
|
|
||||||
|
- The issue **must be present in a [signed](https://docs.featherwallet.org/guides/release-signing-key) [release build](https://github.com/feather-wallet/feather/blob/master/contrib/guix/README.md)**. Custom builds, including distribution packages, are out of scope.
|
||||||
|
- The developers **must be able to reproduce and fix the issue**. If the issue cannot be fixed **in our code** for any reason, it is out of scope.
|
||||||
|
- The live [websites](https://github.com/feather-wallet/feather-site/blob/master/mirrors.txt) and their repositories are out of scope.
|
||||||
|
- Loss of funds due to malware on the user's machine is out of scope.
|
||||||
|
- Memory imaging, including cold boot attacks, is out of scope.
|
||||||
|
- Social engineering against users is out of scope. This includes messages received from the [websocket server](https://docs.featherwallet.org/guides/websocket).
|
||||||
|
- Any form of coercion, physical or psychological, is out of scope.
|
||||||
|
- Vulnerabilities that are attributable to hardware are out of scope.
|
||||||
|
- If the issue was fixed in the `master` branch before we receive your report, it is invalid and not eligible for a bounty from this program.
|
||||||
|
- If the vulnerability involves binary exploitation, we may ask you to provide a proof of concept of secret key exfiltration.
|
||||||
|
- Vulnerabilities that are present in the monero submodule but were not introduced in patches made by the Feather developers must
|
||||||
|
be reported [upstream](https://github.com/monero-project/meta/blob/master/VULNERABILITY_RESPONSE_PROCESS.md) and are not eligible for a bounty from this program.
|
||||||
|
- Vulnerabilities that are present in any of our third-party dependencies must be reported upstream and are not eligible for a bounty from this program.
|
||||||
|
- Vulnerabilities that are present in [supported hardware wallets](https://docs.featherwallet.org/guides/hardware-wallet-support) must be reported upstream and are not eligible for a bounty from this program.
|
||||||
|
- A bounty will not be awarded if the reported vulnerability was already known. We may make an exception if you demonstrate that the severity of the issue was underestimated and no immediate fix was planned.
|
||||||
|
- If, during your research, you disrupt Feather's release infrastructure or services, or attempt to coerce its developers, you will not be awarded a bounty.
|
||||||
|
|
|
@ -1,291 +0,0 @@
|
||||||
# Written in 2016 by Henrik Steffen Gaßmann <henrik@gassmann.onl>
|
|
||||||
#
|
|
||||||
# To the extent possible under law, the author(s) have dedicated all copyright
|
|
||||||
# and related and neighboring rights to this software to the public domain
|
|
||||||
# worldwide. This software is distributed without any warranty.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the CC0 Public Domain Dedication along with
|
|
||||||
# this software. If not, see
|
|
||||||
#
|
|
||||||
# http://creativecommons.org/publicdomain/zero/1.0/
|
|
||||||
#
|
|
||||||
# ##############################################################################
|
|
||||||
# Tries to find the local libsodium installation.
|
|
||||||
#
|
|
||||||
# On Windows the sodium_DIR environment variable is used as a default hint which
|
|
||||||
# can be overridden by setting the corresponding cmake variable.
|
|
||||||
#
|
|
||||||
# Once done the following variables will be defined:
|
|
||||||
#
|
|
||||||
# sodium_FOUND sodium_INCLUDE_DIR sodium_LIBRARY_DEBUG sodium_LIBRARY_RELEASE
|
|
||||||
# sodium_VERSION_STRING
|
|
||||||
#
|
|
||||||
# Furthermore an imported "sodium" target is created.
|
|
||||||
#
|
|
||||||
|
|
||||||
if(CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID STREQUAL "Clang")
|
|
||||||
set(_GCC_COMPATIBLE 1)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# static library option
|
|
||||||
if(NOT DEFINED sodium_USE_STATIC_LIBS)
|
|
||||||
option(sodium_USE_STATIC_LIBS "enable to statically link against sodium" OFF)
|
|
||||||
endif()
|
|
||||||
if(NOT (sodium_USE_STATIC_LIBS EQUAL sodium_USE_STATIC_LIBS_LAST))
|
|
||||||
unset(sodium_LIBRARY CACHE)
|
|
||||||
unset(sodium_LIBRARY_DEBUG CACHE)
|
|
||||||
unset(sodium_LIBRARY_RELEASE CACHE)
|
|
||||||
unset(sodium_DLL_DEBUG CACHE)
|
|
||||||
unset(sodium_DLL_RELEASE CACHE)
|
|
||||||
set(sodium_USE_STATIC_LIBS_LAST
|
|
||||||
${sodium_USE_STATIC_LIBS}
|
|
||||||
CACHE INTERNAL "internal change tracking variable")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# ##############################################################################
|
|
||||||
# UNIX
|
|
||||||
if(UNIX)
|
|
||||||
# import pkg-config
|
|
||||||
find_package(PkgConfig QUIET)
|
|
||||||
if(PKG_CONFIG_FOUND)
|
|
||||||
pkg_check_modules(sodium_PKG QUIET libsodium)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(sodium_USE_STATIC_LIBS)
|
|
||||||
if(sodium_PKG_STATIC_LIBRARIES)
|
|
||||||
foreach(_libname ${sodium_PKG_STATIC_LIBRARIES})
|
|
||||||
if(NOT _libname MATCHES "^lib.*\\.a$") # ignore strings already ending
|
|
||||||
# with .a
|
|
||||||
list(INSERT sodium_PKG_STATIC_LIBRARIES 0 "lib${_libname}.a")
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
list(REMOVE_DUPLICATES sodium_PKG_STATIC_LIBRARIES)
|
|
||||||
else()
|
|
||||||
# if pkgconfig for libsodium doesn't provide static lib info, then
|
|
||||||
# override PKG_STATIC here..
|
|
||||||
set(sodium_PKG_STATIC_LIBRARIES libsodium.a)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(XPREFIX sodium_PKG_STATIC)
|
|
||||||
else()
|
|
||||||
if(sodium_PKG_LIBRARIES STREQUAL "")
|
|
||||||
set(sodium_PKG_LIBRARIES sodium)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(XPREFIX sodium_PKG)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
find_path(sodium_INCLUDE_DIR sodium.h HINTS ${${XPREFIX}_INCLUDE_DIRS})
|
|
||||||
find_library(sodium_LIBRARY_DEBUG
|
|
||||||
NAMES ${${XPREFIX}_LIBRARIES}
|
|
||||||
HINTS ${${XPREFIX}_LIBRARY_DIRS})
|
|
||||||
find_library(sodium_LIBRARY_RELEASE
|
|
||||||
NAMES ${${XPREFIX}_LIBRARIES}
|
|
||||||
HINTS ${${XPREFIX}_LIBRARY_DIRS})
|
|
||||||
|
|
||||||
# ############################################################################
|
|
||||||
# Windows
|
|
||||||
elseif(WIN32)
|
|
||||||
set(sodium_DIR "$ENV{sodium_DIR}" CACHE FILEPATH "sodium install directory")
|
|
||||||
mark_as_advanced(sodium_DIR)
|
|
||||||
|
|
||||||
find_path(sodium_INCLUDE_DIR sodium.h
|
|
||||||
HINTS ${sodium_DIR}
|
|
||||||
PATH_SUFFIXES include)
|
|
||||||
|
|
||||||
if(MSVC)
|
|
||||||
# detect target architecture
|
|
||||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/arch.c" [=[
|
|
||||||
#if defined _M_IX86
|
|
||||||
#error ARCH_VALUE x86_32
|
|
||||||
#elif defined _M_X64
|
|
||||||
#error ARCH_VALUE x86_64
|
|
||||||
#endif
|
|
||||||
#error ARCH_VALUE unknown
|
|
||||||
]=])
|
|
||||||
try_compile(_UNUSED_VAR "${CMAKE_CURRENT_BINARY_DIR}"
|
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/arch.c"
|
|
||||||
OUTPUT_VARIABLE _COMPILATION_LOG)
|
|
||||||
string(REGEX
|
|
||||||
REPLACE ".*ARCH_VALUE ([a-zA-Z0-9_]+).*"
|
|
||||||
"\\1"
|
|
||||||
_TARGET_ARCH
|
|
||||||
"${_COMPILATION_LOG}")
|
|
||||||
|
|
||||||
# construct library path
|
|
||||||
if(_TARGET_ARCH STREQUAL "x86_32")
|
|
||||||
string(APPEND _PLATFORM_PATH "Win32")
|
|
||||||
elseif(_TARGET_ARCH STREQUAL "x86_64")
|
|
||||||
string(APPEND _PLATFORM_PATH "x64")
|
|
||||||
else()
|
|
||||||
message(
|
|
||||||
FATAL_ERROR
|
|
||||||
"the ${_TARGET_ARCH} architecture is not supported by Findsodium.cmake."
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
string(APPEND _PLATFORM_PATH "/$$CONFIG$$")
|
|
||||||
|
|
||||||
if(MSVC_VERSION LESS 1900)
|
|
||||||
math(EXPR _VS_VERSION "${MSVC_VERSION} / 10 - 60")
|
|
||||||
else()
|
|
||||||
math(EXPR _VS_VERSION "${MSVC_VERSION} / 10 - 50")
|
|
||||||
endif()
|
|
||||||
string(APPEND _PLATFORM_PATH "/v${_VS_VERSION}")
|
|
||||||
|
|
||||||
if(sodium_USE_STATIC_LIBS)
|
|
||||||
string(APPEND _PLATFORM_PATH "/static")
|
|
||||||
else()
|
|
||||||
string(APPEND _PLATFORM_PATH "/dynamic")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
string(REPLACE "$$CONFIG$$"
|
|
||||||
"Debug"
|
|
||||||
_DEBUG_PATH_SUFFIX
|
|
||||||
"${_PLATFORM_PATH}")
|
|
||||||
string(REPLACE "$$CONFIG$$"
|
|
||||||
"Release"
|
|
||||||
_RELEASE_PATH_SUFFIX
|
|
||||||
"${_PLATFORM_PATH}")
|
|
||||||
|
|
||||||
find_library(sodium_LIBRARY_DEBUG libsodium.lib
|
|
||||||
HINTS ${sodium_DIR}
|
|
||||||
PATH_SUFFIXES ${_DEBUG_PATH_SUFFIX})
|
|
||||||
find_library(sodium_LIBRARY_RELEASE libsodium.lib
|
|
||||||
HINTS ${sodium_DIR}
|
|
||||||
PATH_SUFFIXES ${_RELEASE_PATH_SUFFIX})
|
|
||||||
if(NOT sodium_USE_STATIC_LIBS)
|
|
||||||
set(CMAKE_FIND_LIBRARY_SUFFIXES_BCK ${CMAKE_FIND_LIBRARY_SUFFIXES})
|
|
||||||
set(CMAKE_FIND_LIBRARY_SUFFIXES ".dll")
|
|
||||||
find_library(sodium_DLL_DEBUG libsodium
|
|
||||||
HINTS ${sodium_DIR}
|
|
||||||
PATH_SUFFIXES ${_DEBUG_PATH_SUFFIX})
|
|
||||||
find_library(sodium_DLL_RELEASE libsodium
|
|
||||||
HINTS ${sodium_DIR}
|
|
||||||
PATH_SUFFIXES ${_RELEASE_PATH_SUFFIX})
|
|
||||||
set(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES_BCK})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
elseif(_GCC_COMPATIBLE)
|
|
||||||
if(sodium_USE_STATIC_LIBS)
|
|
||||||
find_library(sodium_LIBRARY_DEBUG libsodium.a
|
|
||||||
HINTS ${sodium_DIR}
|
|
||||||
PATH_SUFFIXES lib)
|
|
||||||
find_library(sodium_LIBRARY_RELEASE libsodium.a
|
|
||||||
HINTS ${sodium_DIR}
|
|
||||||
PATH_SUFFIXES lib)
|
|
||||||
else()
|
|
||||||
find_library(sodium_LIBRARY_DEBUG libsodium.dll.a
|
|
||||||
HINTS ${sodium_DIR}
|
|
||||||
PATH_SUFFIXES lib)
|
|
||||||
find_library(sodium_LIBRARY_RELEASE libsodium.dll.a
|
|
||||||
HINTS ${sodium_DIR}
|
|
||||||
PATH_SUFFIXES lib)
|
|
||||||
|
|
||||||
file(GLOB _DLL
|
|
||||||
LIST_DIRECTORIES false
|
|
||||||
RELATIVE "${sodium_DIR}/bin"
|
|
||||||
"${sodium_DIR}/bin/libsodium*.dll")
|
|
||||||
find_library(sodium_DLL_DEBUG ${_DLL} libsodium
|
|
||||||
HINTS ${sodium_DIR}
|
|
||||||
PATH_SUFFIXES bin)
|
|
||||||
find_library(sodium_DLL_RELEASE ${_DLL} libsodium
|
|
||||||
HINTS ${sodium_DIR}
|
|
||||||
PATH_SUFFIXES bin)
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
message(FATAL_ERROR "this platform is not supported by FindSodium.cmake")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# ############################################################################
|
|
||||||
# unsupported
|
|
||||||
else()
|
|
||||||
message(FATAL_ERROR "this platform is not supported by FindSodium.cmake")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# ##############################################################################
|
|
||||||
# common stuff
|
|
||||||
|
|
||||||
# extract sodium version
|
|
||||||
if(sodium_INCLUDE_DIR)
|
|
||||||
set(_VERSION_HEADER "${sodium_INCLUDE_DIR}/sodium/version.h")
|
|
||||||
if(EXISTS "${_VERSION_HEADER}")
|
|
||||||
file(READ "${_VERSION_HEADER}" _VERSION_HEADER_CONTENT)
|
|
||||||
string(REGEX
|
|
||||||
REPLACE ".*define[ \t]+SODIUM_VERSION_STRING[^\"]+\"([^\"]+)\".*"
|
|
||||||
"\\1"
|
|
||||||
sodium_VERSION_STRING
|
|
||||||
"${_VERSION_HEADER_CONTENT}")
|
|
||||||
set(sodium_VERSION_STRING "${sodium_VERSION_STRING}")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# communicate results
|
|
||||||
include(FindPackageHandleStandardArgs)
|
|
||||||
find_package_handle_standard_args(sodium
|
|
||||||
REQUIRED_VARS
|
|
||||||
sodium_LIBRARY_RELEASE
|
|
||||||
sodium_LIBRARY_DEBUG
|
|
||||||
sodium_INCLUDE_DIR
|
|
||||||
VERSION_VAR
|
|
||||||
sodium_VERSION_STRING)
|
|
||||||
|
|
||||||
# mark file paths as advanced
|
|
||||||
mark_as_advanced(sodium_INCLUDE_DIR)
|
|
||||||
mark_as_advanced(sodium_LIBRARY_DEBUG)
|
|
||||||
mark_as_advanced(sodium_LIBRARY_RELEASE)
|
|
||||||
if(WIN32)
|
|
||||||
mark_as_advanced(sodium_DLL_DEBUG)
|
|
||||||
mark_as_advanced(sodium_DLL_RELEASE)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# create imported target
|
|
||||||
if(sodium_USE_STATIC_LIBS)
|
|
||||||
set(_LIB_TYPE STATIC)
|
|
||||||
else()
|
|
||||||
set(_LIB_TYPE SHARED)
|
|
||||||
endif()
|
|
||||||
add_library(sodium ${_LIB_TYPE} IMPORTED)
|
|
||||||
|
|
||||||
set_target_properties(sodium
|
|
||||||
PROPERTIES INTERFACE_INCLUDE_DIRECTORIES
|
|
||||||
"${sodium_INCLUDE_DIR}"
|
|
||||||
IMPORTED_LINK_INTERFACE_LANGUAGES
|
|
||||||
"C")
|
|
||||||
|
|
||||||
if(sodium_USE_STATIC_LIBS)
|
|
||||||
set_target_properties(sodium
|
|
||||||
PROPERTIES INTERFACE_COMPILE_DEFINITIONS
|
|
||||||
"SODIUM_STATIC"
|
|
||||||
IMPORTED_LOCATION
|
|
||||||
"${sodium_LIBRARY_RELEASE}"
|
|
||||||
IMPORTED_LOCATION_DEBUG
|
|
||||||
"${sodium_LIBRARY_DEBUG}")
|
|
||||||
else()
|
|
||||||
if(UNIX)
|
|
||||||
set_target_properties(sodium
|
|
||||||
PROPERTIES IMPORTED_LOCATION
|
|
||||||
"${sodium_LIBRARY_RELEASE}"
|
|
||||||
IMPORTED_LOCATION_DEBUG
|
|
||||||
"${sodium_LIBRARY_DEBUG}")
|
|
||||||
elseif(WIN32)
|
|
||||||
set_target_properties(sodium
|
|
||||||
PROPERTIES IMPORTED_IMPLIB
|
|
||||||
"${sodium_LIBRARY_RELEASE}"
|
|
||||||
IMPORTED_IMPLIB_DEBUG
|
|
||||||
"${sodium_LIBRARY_DEBUG}")
|
|
||||||
if(NOT (sodium_DLL_DEBUG MATCHES ".*-NOTFOUND"))
|
|
||||||
set_target_properties(sodium
|
|
||||||
PROPERTIES IMPORTED_LOCATION_DEBUG
|
|
||||||
"${sodium_DLL_DEBUG}")
|
|
||||||
endif()
|
|
||||||
if(NOT (sodium_DLL_RELEASE MATCHES ".*-NOTFOUND"))
|
|
||||||
set_target_properties(sodium
|
|
||||||
PROPERTIES IMPORTED_LOCATION_RELWITHDEBINFO
|
|
||||||
"${sodium_DLL_RELEASE}"
|
|
||||||
IMPORTED_LOCATION_MINSIZEREL
|
|
||||||
"${sodium_DLL_RELEASE}"
|
|
||||||
IMPORTED_LOCATION_RELEASE
|
|
||||||
"${sodium_DLL_RELEASE}")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
endif()
|
|
27
contrib/depends/packages/abseil.mk
Normal file
27
contrib/depends/packages/abseil.mk
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
package=abseil
|
||||||
|
$(package)_version=$(native_$(package)_version)
|
||||||
|
$(package)_download_path=$(native_$(package)_download_path)
|
||||||
|
$(package)_download_file=$(native_$(package)_download_file)
|
||||||
|
$(package)_file_name=$(native_$(package)_file_name)
|
||||||
|
$(package)_sha256_hash=$(native_$(package)_sha256_hash)
|
||||||
|
$(package)_patches=no_librt.patch
|
||||||
|
|
||||||
|
define $(package)_set_vars
|
||||||
|
$(package)_cxxflags+=-std=c++17
|
||||||
|
endef
|
||||||
|
|
||||||
|
define $(package)_preprocess_cmds
|
||||||
|
patch -p1 -i $($(package)_patch_dir)/no_librt.patch
|
||||||
|
endef
|
||||||
|
|
||||||
|
define $(package)_config_cmds
|
||||||
|
$($(package)_cmake)
|
||||||
|
endef
|
||||||
|
|
||||||
|
define $(package)_build_cmds
|
||||||
|
$(MAKE)
|
||||||
|
endef
|
||||||
|
|
||||||
|
define $(package)_stage_cmds
|
||||||
|
$(MAKE) DESTDIR=$($(package)_staging_dir) install
|
||||||
|
endef
|
|
@ -3,7 +3,6 @@ $(package)_version=1.85.0
|
||||||
$(package)_download_path=https://boostorg.jfrog.io/artifactory/main/release/$($(package)_version)/source/
|
$(package)_download_path=https://boostorg.jfrog.io/artifactory/main/release/$($(package)_version)/source/
|
||||||
$(package)_file_name=$(package)_$(subst .,_,$($(package)_version)).tar.gz
|
$(package)_file_name=$(package)_$(subst .,_,$($(package)_version)).tar.gz
|
||||||
$(package)_sha256_hash=be0d91732d5b0cc6fbb275c7939974457e79b54d6f07ce2e3dfdd68bef883b0b
|
$(package)_sha256_hash=be0d91732d5b0cc6fbb275c7939974457e79b54d6f07ce2e3dfdd68bef883b0b
|
||||||
$(package)_dependencies=libiconv
|
|
||||||
$(package)_patches=disable_addr2line.patch
|
$(package)_patches=disable_addr2line.patch
|
||||||
|
|
||||||
define $(package)_set_vars
|
define $(package)_set_vars
|
||||||
|
@ -21,7 +20,8 @@ $(package)_toolset_$(host_os)=gcc
|
||||||
$(package)_archiver_$(host_os)=$($(package)_ar)
|
$(package)_archiver_$(host_os)=$($(package)_ar)
|
||||||
$(package)_toolset_darwin=darwin
|
$(package)_toolset_darwin=darwin
|
||||||
$(package)_archiver_darwin=$($(package)_libtool)
|
$(package)_archiver_darwin=$($(package)_libtool)
|
||||||
$(package)_config_libraries=chrono,filesystem,program_options,system,thread,test,date_time,regex,serialization,locale,stacktrace
|
$(package)_config_libraries_$(host_os)="chrono,filesystem,program_options,system,thread,test,date_time,regex,serialization,stacktrace"
|
||||||
|
$(package)_config_libraries_mingw32="chrono,filesystem,program_options,system,thread,test,date_time,regex,serialization,stacktrace,locale"
|
||||||
$(package)_cxxflags=-std=c++17
|
$(package)_cxxflags=-std=c++17
|
||||||
$(package)_cxxflags_linux=-fPIC
|
$(package)_cxxflags_linux=-fPIC
|
||||||
$(package)_cxxflags_freebsd=-fPIC
|
$(package)_cxxflags_freebsd=-fPIC
|
||||||
|
@ -33,7 +33,7 @@ define $(package)_preprocess_cmds
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define $(package)_config_cmds
|
define $(package)_config_cmds
|
||||||
./bootstrap.sh --without-icu --with-libraries=$(boost_config_libraries)
|
./bootstrap.sh --without-icu --with-libraries=$(boost_config_libraries_$(host_os))
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define $(package)_build_cmds
|
define $(package)_build_cmds
|
||||||
|
|
|
@ -1,21 +1,20 @@
|
||||||
package=expat
|
package=expat
|
||||||
$(package)_version=2.6.2
|
$(package)_version=2.6.3
|
||||||
$(package)_download_path=https://github.com/libexpat/libexpat/releases/download/R_$(subst .,_,$($(package)_version))/
|
$(package)_download_path=https://github.com/libexpat/libexpat/releases/download/R_$(subst .,_,$($(package)_version))/
|
||||||
$(package)_file_name=$(package)-$($(package)_version).tar.xz
|
$(package)_file_name=$(package)-$($(package)_version).tar.gz
|
||||||
$(package)_sha256_hash=ee14b4c5d8908b1bec37ad937607eab183d4d9806a08adee472c3c3121d27364
|
$(package)_sha256_hash=17aa6cfc5c4c219c09287abfc10bc13f0c06f30bb654b28bfe6f567ca646eb79
|
||||||
|
$(package)_build_subdir=build
|
||||||
|
|
||||||
# -D_DEFAULT_SOURCE defines __USE_MISC, which exposes additional
|
|
||||||
# definitions in endian.h, which are required for a working
|
|
||||||
# endianess check in configure when building with -flto.
|
|
||||||
define $(package)_set_vars
|
define $(package)_set_vars
|
||||||
$(package)_config_opts=--disable-shared --without-docbook --without-tests --without-examples
|
$(package)_config_opts := -DEXPAT_BUILD_TOOLS=OFF
|
||||||
$(package)_config_opts += --disable-dependency-tracking --enable-option-checking
|
$(package)_config_opts += -DEXPAT_BUILD_EXAMPLES=OFF
|
||||||
$(package)_config_opts += --without-xmlwf --with-pic
|
$(package)_config_opts += -DEXPAT_BUILD_TESTS=OFF
|
||||||
$(package)_cppflags += -D_DEFAULT_SOURCE
|
$(package)_config_opts += -DBUILD_SHARED_LIBS=OFF
|
||||||
|
$(package)_config_opts += -DCMAKE_POSITION_INDEPENDENT_CODE=ON
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define $(package)_config_cmds
|
define $(package)_config_cmds
|
||||||
$($(package)_autoconf)
|
$($(package)_cmake) -S .. -B .
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define $(package)_build_cmds
|
define $(package)_build_cmds
|
||||||
|
@ -27,5 +26,5 @@ define $(package)_stage_cmds
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define $(package)_postprocess_cmds
|
define $(package)_postprocess_cmds
|
||||||
rm -rf share lib/cmake lib/*.la
|
rm -rf share lib/cmake
|
||||||
endef
|
endef
|
||||||
|
|
|
@ -1,18 +1,20 @@
|
||||||
package=freetype
|
package=freetype
|
||||||
$(package)_version=2.13.2
|
$(package)_version=2.13.3
|
||||||
$(package)_download_path=https://sourceforge.net/projects/freetype/files/freetype2/$($(package)_version)/
|
$(package)_download_path=https://sourceforge.net/projects/freetype/files/freetype2/$($(package)_version)/
|
||||||
$(package)_file_name=freetype-$($(package)_version).tar.xz
|
$(package)_file_name=freetype-$($(package)_version).tar.gz
|
||||||
$(package)_sha256_hash=12991c4e55c506dd7f9b765933e62fd2be2e06d421505d7950a132e4f1bb484d
|
$(package)_sha256_hash=5c3a8e78f7b24c20b25b54ee575d6daa40007a5f4eea2845861c3409b3021747
|
||||||
|
|
||||||
define $(package)_set_vars
|
define $(package)_set_vars
|
||||||
$(package)_config_opts = --without-zlib --without-png --without-harfbuzz --without-bzip2 --enable-static --disable-shared
|
$(package)_config_opts := --without-zlib --without-png --without-harfbuzz --without-bzip2 --enable-static --disable-shared
|
||||||
$(package)_config_opts += --enable-option-checking --without-brotli
|
$(package)_config_opts += --enable-option-checking --without-brotli
|
||||||
$(package)_config_opts += --with-pic
|
$(package)_config_opts += --with-pic
|
||||||
endef
|
endef
|
||||||
|
|
||||||
|
define $(package)_preprocess_cmds
|
||||||
|
rm -rf docs
|
||||||
|
endef
|
||||||
|
|
||||||
define $(package)_config_cmds
|
define $(package)_config_cmds
|
||||||
printenv && \
|
|
||||||
echo "$($(package)_autoconf)" && \
|
|
||||||
$($(package)_autoconf)
|
$($(package)_autoconf)
|
||||||
endef
|
endef
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
package=libgcrypt
|
package=libgcrypt
|
||||||
$(package)_version=1.10.3
|
$(package)_version=1.11.0
|
||||||
$(package)_download_path=https://www.gnupg.org/ftp/gcrypt/libgcrypt/
|
$(package)_download_path=https://www.gnupg.org/ftp/gcrypt/libgcrypt/
|
||||||
$(package)_file_name=libgcrypt-$($(package)_version).tar.bz2
|
$(package)_file_name=libgcrypt-$($(package)_version).tar.gz
|
||||||
$(package)_sha256_hash=8b0870897ac5ac67ded568dcfadf45969cfa8a6beb0fd60af2a9eadc2a3272aa
|
$(package)_sha256_hash=2382891207d3b000b20c81dbf2036516a535d31abd80f57d455e711e1dde5ff5
|
||||||
$(package)_dependencies=libgpg-error
|
$(package)_dependencies=libgpg-error
|
||||||
|
|
||||||
define $(package)_set_vars
|
define $(package)_set_vars
|
||||||
|
@ -13,16 +13,9 @@ define $(package)_preprocess_cmds
|
||||||
cp -f $(BASEDIR)/config.guess $(BASEDIR)/config.sub build-aux
|
cp -f $(BASEDIR)/config.guess $(BASEDIR)/config.sub build-aux
|
||||||
endef
|
endef
|
||||||
|
|
||||||
# TODO: building on linux with $($(package)_autoconf) fails for mysterious reasons
|
|
||||||
ifeq ($(host_os),linux)
|
|
||||||
define $(package)_config_cmds
|
|
||||||
CFLAGS='-fPIE' CXXFLAGS='-fPIE' ./configure --host=$(host) --enable-digests="sha256 blake2" --enable-ciphers="aes chacha20" --disable-amd64-as-feature-detection --disable-asm --disable-avx-support --disable-avx2-support --disable-sse41-support --disable-shared --enable-static --disable-doc --with-libgpg-error-prefix=$(host_prefix) --prefix=$(host_prefix)
|
|
||||||
endef
|
|
||||||
else
|
|
||||||
define $(package)_config_cmds
|
define $(package)_config_cmds
|
||||||
$($(package)_autoconf) --disable-shared --enable-static --disable-doc --disable-asm --with-libgpg-error-prefix=$(host_prefix)
|
$($(package)_autoconf) --disable-shared --enable-static --disable-doc --disable-asm --with-libgpg-error-prefix=$(host_prefix)
|
||||||
endef
|
endef
|
||||||
endif
|
|
||||||
|
|
||||||
define $(package)_build_cmds
|
define $(package)_build_cmds
|
||||||
$(MAKE) $($(package)_build_opts)
|
$(MAKE) $($(package)_build_opts)
|
||||||
|
|
|
@ -1,25 +1,30 @@
|
||||||
package=libgpg-error
|
package=libgpg-error
|
||||||
$(package)_version=1.49
|
$(package)_version=1.50
|
||||||
$(package)_download_path=https://www.gnupg.org/ftp/gcrypt/libgpg-error/
|
$(package)_download_path=https://www.gnupg.org/ftp/gcrypt/libgpg-error/
|
||||||
$(package)_file_name=libgpg-error-$($(package)_version).tar.gz
|
$(package)_file_name=libgpg-error-$($(package)_version).tar.gz
|
||||||
$(package)_sha256_hash=e59cc3ced0ae86f49073e2f2344676919a82fc5033716bee7232f6f778158792
|
$(package)_sha256_hash=34a3b36ec8ad830f8f3ceb5db583d1f6dc8ae4c31d04f6da18ea18dd95396ab0
|
||||||
|
$(package)_patches=declare_environ_macos.patch
|
||||||
|
|
||||||
define $(package)_set_vars
|
define $(package)_set_vars
|
||||||
$(package)_build_opts=CFLAGS="-fPIE"
|
$(package)_config_opts := --enable-static --disable-shared
|
||||||
|
$(package)_config_opts += --disable-doc --disable-tests
|
||||||
|
$(package)_config_opts += --enable-install-gpg-error-config
|
||||||
|
$(package)_build_opts := CFLAGS="-fPIE"
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define $(package)_preprocess_cmds
|
define $(package)_preprocess_cmds
|
||||||
|
patch -p1 < $($(package)_patch_dir)/declare_environ_macos.patch && \
|
||||||
cp -f $(BASEDIR)/config.guess $(BASEDIR)/config.sub build-aux
|
cp -f $(BASEDIR)/config.guess $(BASEDIR)/config.sub build-aux
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define $(package)_config_cmds
|
define $(package)_config_cmds
|
||||||
$($(package)_autoconf) --enable-static --disable-shared --enable-install-gpg-error-config
|
$($(package)_autoconf)
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define $(package)_build_cmds
|
define $(package)_build_cmds
|
||||||
$(MAKE) $($(package)_build_opts)
|
$(MAKE) $($(package)_build_opts)
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define $(package)_stage_cmds
|
define $(package)_stage_cmds
|
||||||
$(MAKE) DESTDIR=$($(package)_staging_dir) install
|
$(MAKE) DESTDIR=$($(package)_staging_dir) install
|
||||||
endef
|
endef
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
package=libiconv
|
|
||||||
$(package)_version=1.17
|
|
||||||
$(package)_download_path=https://ftp.gnu.org/gnu/libiconv
|
|
||||||
$(package)_file_name=libiconv-$($(package)_version).tar.gz
|
|
||||||
$(package)_sha256_hash=8f74213b56238c85a50a5329f77e06198771e70dd9a739779f4c02f65d971313
|
|
||||||
|
|
||||||
define $(package)_set_vars
|
|
||||||
$(package)_config_opts=--disable-nls
|
|
||||||
$(package)_config_opts=--enable-static
|
|
||||||
$(package)_config_opts=--disable-shared
|
|
||||||
$(package)_config_opts_linux=--with-pic
|
|
||||||
$(package)_config_opts_freebsd=--with-pic
|
|
||||||
endef
|
|
||||||
|
|
||||||
define $(package)_config_cmds
|
|
||||||
$($(package)_autoconf) AR_FLAGS=$($(package)_arflags)
|
|
||||||
endef
|
|
||||||
|
|
||||||
define $(package)_build_cmds
|
|
||||||
$(MAKE)
|
|
||||||
endef
|
|
||||||
|
|
||||||
define $(package)_stage_cmds
|
|
||||||
$(MAKE) DESTDIR=$($(package)_staging_dir) install
|
|
||||||
endef
|
|
||||||
|
|
||||||
define $(package)_postprocess_cmds
|
|
||||||
rm lib/*.la
|
|
||||||
endef
|
|
|
@ -1,12 +1,12 @@
|
||||||
package=libxcb_util_cursor
|
package=libxcb_util_cursor
|
||||||
$(package)_version=0.1.4
|
$(package)_version=0.1.5
|
||||||
$(package)_download_path=https://xcb.freedesktop.org/dist
|
$(package)_download_path=https://xcb.freedesktop.org/dist
|
||||||
$(package)_file_name=xcb-util-cursor-$($(package)_version).tar.gz
|
$(package)_file_name=xcb-util-cursor-$($(package)_version).tar.gz
|
||||||
$(package)_sha256_hash=cc8608ebb695742b6cf84712be29b2b66aa5f6768039528794fca0fa283022bf
|
$(package)_sha256_hash=0e9c5446dc6f3beb8af6ebfcc9e27bcc6da6fe2860f7fc07b99144dfa568e93b
|
||||||
$(package)_dependencies=libxcb libxcb_util_render libxcb_util_image
|
$(package)_dependencies=libxcb libxcb_util_render libxcb_util_image
|
||||||
|
|
||||||
define $(package)_set_vars
|
define $(package)_set_vars
|
||||||
$(package)_config_opts=--disable-shared --disable-devel-docs --without-doxygen
|
$(package)_config_opts := --disable-shared --disable-devel-docs --without-doxygen
|
||||||
$(package)_config_opts += --disable-dependency-tracking --enable-option-checking
|
$(package)_config_opts += --disable-dependency-tracking --enable-option-checking
|
||||||
endef
|
endef
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,33 @@
|
||||||
package=libzip
|
package=libzip
|
||||||
$(package)_version=1.10.1
|
$(package)_version=1.11.1
|
||||||
$(package)_download_path=https://libzip.org/download/
|
$(package)_download_path=https://libzip.org/download/
|
||||||
$(package)_file_name=$(package)-$($(package)_version).tar.xz
|
$(package)_file_name=$(package)-$($(package)_version).tar.gz
|
||||||
$(package)_sha256_hash=dc3c8d5b4c8bbd09626864f6bcf93de701540f761d76b85d7c7d710f4bd90318
|
$(package)_sha256_hash=c0e6fa52a62ba11efd30262290dc6970947aef32e0cc294ee50e9005ceac092a
|
||||||
$(package)_dependencies=zlib
|
$(package)_dependencies=zlib
|
||||||
$(package)_patches += no-clonefile.patch
|
|
||||||
|
define $(package)_set_vars
|
||||||
|
$(package)_config_opts := -DENABLE_BZIP2=OFF
|
||||||
|
$(package)_config_opts += -DENABLE_LZMA=OFF
|
||||||
|
$(package)_config_opts += -DENABLE_ZSTD=OFF
|
||||||
|
$(package)_config_opts += -DENABLE_COMMONCRYPTO=OFF
|
||||||
|
$(package)_config_opts += -DENABLE_GNUTLS=OFF
|
||||||
|
$(package)_config_opts += -DENABLE_MBEDTLS=OFF
|
||||||
|
$(package)_config_opts += -DENABLE_OPENSSL=OFF
|
||||||
|
$(package)_config_opts += -DENABLE_WINDOWS_CRYPTO=OFF
|
||||||
|
$(package)_config_opts += -DBUILD_SHARED_LIBS=OFF
|
||||||
|
$(package)_config_opts += -DBUILD_TOOLS=OFF
|
||||||
|
$(package)_config_opts += -DBUILD_REGRESS=OFF
|
||||||
|
$(package)_config_opts += -DBUILD_OSSFUZZ=OFF
|
||||||
|
$(package)_config_opts += -DBUILD_EXAMPLES=OFF
|
||||||
|
$(package)_config_opts += -DBUILD_DOC=OFF
|
||||||
|
endef
|
||||||
|
|
||||||
define $(package)_preprocess_cmds
|
define $(package)_preprocess_cmds
|
||||||
patch -p1 < $($(package)_patch_dir)/no-clonefile.patch
|
rm -rf regress ossfuzz
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define $(package)_config_cmds
|
define $(package)_config_cmds
|
||||||
$($(package)_cmake) -DZLIB_ROOT=$(host_prefix) -DENABLE_BZIP2=Off -DBUILD_SHARED_LIBS=OFF -DCMAKE_INSTALL_PREFIX=$(host_prefix) .
|
$($(package)_cmake) .
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define $(package)_build_cmds
|
define $(package)_build_cmds
|
||||||
|
@ -20,4 +36,4 @@ endef
|
||||||
|
|
||||||
define $(package)_stage_cmds
|
define $(package)_stage_cmds
|
||||||
$(MAKE) DESTDIR=$($(package)_staging_dir) install
|
$(MAKE) DESTDIR=$($(package)_staging_dir) install
|
||||||
endef
|
endef
|
||||||
|
|
18
contrib/depends/packages/native_abseil.mk
Normal file
18
contrib/depends/packages/native_abseil.mk
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
package=native_abseil
|
||||||
|
$(package)_version=20240722.0
|
||||||
|
$(package)_download_path=https://github.com/abseil/abseil-cpp/archive/refs/tags/
|
||||||
|
$(package)_download_file=$($(package)_version).tar.gz
|
||||||
|
$(package)_file_name=abseil-$($(package)_version).tar.gz
|
||||||
|
$(package)_sha256_hash=f50e5ac311a81382da7fa75b97310e4b9006474f9560ac46f54a9967f07d4ae3
|
||||||
|
|
||||||
|
define $(package)_config_cmds
|
||||||
|
$($(package)_cmake)
|
||||||
|
endef
|
||||||
|
|
||||||
|
define $(package)_build_cmds
|
||||||
|
$(MAKE)
|
||||||
|
endef
|
||||||
|
|
||||||
|
define $(package)_stage_cmds
|
||||||
|
$(MAKE) DESTDIR=$($(package)_staging_dir) install
|
||||||
|
endef
|
|
@ -1,27 +1,34 @@
|
||||||
package=native_protobuf
|
package=native_protobuf
|
||||||
$(package)_version=3.21.12
|
$(package)_version=28.2
|
||||||
$(package)_download_path=https://github.com/protocolbuffers/protobuf/releases/download/v21.12/
|
$(package)_download_path=https://github.com/protocolbuffers/protobuf/releases/download/v$($(package)_version)
|
||||||
$(package)_file_name=protobuf-cpp-$($(package)_version).tar.gz
|
$(package)_file_name=protobuf-$($(package)_version).tar.gz
|
||||||
$(package)_sha256_hash=4eab9b524aa5913c6fffb20b2a8abf5ef7f95a80bc0701f3a6dbb4c607f73460
|
$(package)_sha256_hash=b2340aa47faf7ef10a0328190319d3f3bee1b24f426d4ce8f4253b6f27ce16db
|
||||||
$(package)_cxxflags=-std=c++11
|
$(package)_dependencies=native_abseil
|
||||||
|
|
||||||
define $(package)_set_vars
|
define $(package)_set_vars
|
||||||
$(package)_config_opts=--disable-shared --prefix=$(build_prefix)
|
$(package)_cxxflags+=-std=c++17
|
||||||
$(package)_config_opts_linux=--with-pic
|
$(package)_config_opts=-Dprotobuf_BUILD_TESTS=OFF
|
||||||
|
$(package)_config_opts+=-Dprotobuf_ABSL_PROVIDER=package
|
||||||
|
$(package)_config_opts+=-Dprotobuf_BUILD_SHARED_LIBS=OFF
|
||||||
|
$(package)_config_opts+=-Dprotobuf_WITH_ZLIB=OFF
|
||||||
|
endef
|
||||||
|
|
||||||
|
define $(package)_preprocess_cmds
|
||||||
|
rm -rf docs php/src/GPBMetadata compatibility objectivec/Tests csharp/keys php/tests src/google/protobuf/testdata csharp/src/Google.Protobuf.Test
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define $(package)_config_cmds
|
define $(package)_config_cmds
|
||||||
$($(package)_autoconf)
|
$($(package)_cmake)
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define $(package)_build_cmds
|
define $(package)_build_cmds
|
||||||
$(MAKE) -C src protoc
|
$(MAKE)
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define $(package)_stage_cmds
|
define $(package)_stage_cmds
|
||||||
$(MAKE) DESTDIR=$($(package)_staging_dir) -C src install-binPROGRAMS install-nobase_dist_protoDATA
|
$(MAKE) DESTDIR=$($(package)_staging_dir) install
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define $(package)_postprocess_cmds
|
define $(package)_postprocess_cmds
|
||||||
rm -rf lib/
|
rm -rf lib64
|
||||||
endef
|
endef
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
package=native_qt
|
package=native_qt
|
||||||
$(package)_version=6.7.2
|
$(package)_version=6.7.3
|
||||||
$(package)_download_path=https://download.qt.io/official_releases/qt/6.7/$($(package)_version)/submodules
|
$(package)_download_path=https://download.qt.io/official_releases/qt/6.7/$($(package)_version)/submodules
|
||||||
$(package)_suffix=everywhere-src-$($(package)_version).tar.xz
|
$(package)_suffix=everywhere-src-$($(package)_version).tar.xz
|
||||||
$(package)_file_name=qtbase-$($(package)_suffix)
|
$(package)_file_name=qtbase-$($(package)_suffix)
|
||||||
$(package)_sha256_hash=c5f22a5e10fb162895ded7de0963328e7307611c688487b5d152c9ee64767599
|
$(package)_sha256_hash=8ccbb9ab055205ac76632c9eeddd1ed6fc66936fc56afc2ed0fd5d9e23da3097
|
||||||
$(package)_qt_libs=corelib network widgets gui plugins testlib
|
$(package)_qt_libs=corelib network widgets gui plugins testlib
|
||||||
$(package)_patches = dont_hardcode_pwd.patch
|
$(package)_patches = dont_hardcode_pwd.patch
|
||||||
$(package)_patches += fast_fixed_dtoa_no_optimize.patch
|
$(package)_patches += fast_fixed_dtoa_no_optimize.patch
|
||||||
|
@ -13,16 +13,16 @@ $(package)_patches += rcc_hardcode_timestamp.patch
|
||||||
$(package)_patches += root_CMakeLists.txt
|
$(package)_patches += root_CMakeLists.txt
|
||||||
|
|
||||||
$(package)_qttools_file_name=qttools-$($(package)_suffix)
|
$(package)_qttools_file_name=qttools-$($(package)_suffix)
|
||||||
$(package)_qttools_sha256_hash=58e855ad1b2533094726c8a425766b63a04a0eede2ed85086860e54593aa4b2a
|
$(package)_qttools_sha256_hash=f03bb7df619cd9ac9dba110e30b7bcab5dd88eb8bdc9cc752563b4367233203f
|
||||||
|
|
||||||
$(package)_qtsvg_file_name=qtsvg-$($(package)_suffix)
|
$(package)_qtsvg_file_name=qtsvg-$($(package)_suffix)
|
||||||
$(package)_qtsvg_sha256_hash=fb0d1286a35be3583fee34aeb5843c94719e07193bdf1d4d8b0dc14009caef01
|
$(package)_qtsvg_sha256_hash=40142cb71fb1e07ad612bc361b67f5d54cd9367f9979ae6b86124a064deda06b
|
||||||
|
|
||||||
$(package)_qtmultimedia_file_name=qtmultimedia-$($(package)_suffix)
|
$(package)_qtmultimedia_file_name=qtmultimedia-$($(package)_suffix)
|
||||||
$(package)_qtmultimedia_sha256_hash=8ef835115acb9a1d3d2c9f23cfacb43f2c537e3786a8ab822299a2a7765651d3
|
$(package)_qtmultimedia_sha256_hash=304d28b8e592435293893b0110d5f3534407604d1e04d8a0b0e5b34afe577303
|
||||||
|
|
||||||
$(package)_qtshadertools_file_name=qtshadertools-$($(package)_suffix)
|
$(package)_qtshadertools_file_name=qtshadertools-$($(package)_suffix)
|
||||||
$(package)_qtshadertools_sha256_hash=edfa34c0ac8c00fcaa949df1d8e7a77d89dadd6386e683ce6c3e3b117e2f7cc1
|
$(package)_qtshadertools_sha256_hash=74e512798c7ddbda354a2d8d975211454bbabb47afb7e598892067a5828c0995
|
||||||
|
|
||||||
$(package)_extra_sources += $($(package)_qttools_file_name)
|
$(package)_extra_sources += $($(package)_qttools_file_name)
|
||||||
$(package)_extra_sources += $($(package)_qtsvg_file_name)
|
$(package)_extra_sources += $($(package)_qtsvg_file_name)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
packages := boost openssl libiconv unbound qrencode libsodium polyseed hidapi protobuf libusb zlib libgpg-error libgcrypt expat libzip zxing-cpp libarchive
|
packages := boost openssl unbound qrencode libsodium polyseed hidapi abseil protobuf libusb zlib libgpg-error libgcrypt expat libzip zxing-cpp
|
||||||
native_packages := native_qt native_protobuf
|
native_packages := native_qt native_abseil native_protobuf
|
||||||
|
|
||||||
linux_packages := eudev libfuse libsquashfuse zstd appimage_runtime
|
linux_packages := eudev libfuse libsquashfuse zstd appimage_runtime
|
||||||
linux_native_packages =
|
linux_native_packages =
|
||||||
|
|
|
@ -3,27 +3,30 @@ $(package)_version=$(native_$(package)_version)
|
||||||
$(package)_download_path=$(native_$(package)_download_path)
|
$(package)_download_path=$(native_$(package)_download_path)
|
||||||
$(package)_file_name=$(native_$(package)_file_name)
|
$(package)_file_name=$(native_$(package)_file_name)
|
||||||
$(package)_sha256_hash=$(native_$(package)_sha256_hash)
|
$(package)_sha256_hash=$(native_$(package)_sha256_hash)
|
||||||
$(package)_dependencies=native_$(package)
|
$(package)_dependencies=abseil
|
||||||
$(package)_cxxflags=-std=c++11
|
|
||||||
|
|
||||||
define $(package)_set_vars
|
define $(package)_set_vars
|
||||||
$(package)_config_opts=--disable-shared --with-protoc=$(build_prefix)/bin/protoc
|
$(package)_cxxflags+=-std=c++17
|
||||||
$(package)_config_opts_linux=--with-pic
|
$(package)_config_opts=-Dprotobuf_ABSL_PROVIDER=package
|
||||||
|
$(package)_config_opts+=-Dprotobuf_BUILD_TESTS=OFF
|
||||||
|
$(package)_config_opts+=-Dprotobuf_BUILD_SHARED_LIBS=OFF
|
||||||
|
$(package)_config_opts+=-Dprotobuf_BUILD_PROTOC_BINARIES=OFF
|
||||||
|
$(package)_config_opts+=-Dprotobuf_WITH_ZLIB=OFF
|
||||||
|
$(package)_config_opts+=-Dprotobuf_BUILD_LIBUPB=OFF
|
||||||
|
endef
|
||||||
|
|
||||||
|
define $(package)_preprocess_cmds
|
||||||
|
rm -rf docs php/src/GPBMetadata compatibility objectivec/Tests csharp/keys php/tests src/google/protobuf/testdata csharp/src/Google.Protobuf.Test
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define $(package)_config_cmds
|
define $(package)_config_cmds
|
||||||
cp -f $(BASEDIR)/config.guess $(BASEDIR)/config.sub . && \
|
$($(package)_cmake)
|
||||||
cp -f $(BASEDIR)/config.guess $(BASEDIR)/config.sub ./third_party/googletest/googletest/build-aux/ && \
|
|
||||||
cp -f $(BASEDIR)/config.guess $(BASEDIR)/config.sub ./third_party/googletest/googlemock/build-aux/ && \
|
|
||||||
$($(package)_autoconf)
|
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define $(package)_build_cmds
|
define $(package)_build_cmds
|
||||||
$(MAKE) -C src libprotobuf.la
|
$(MAKE)
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define $(package)_stage_cmds
|
define $(package)_stage_cmds
|
||||||
$(MAKE) DESTDIR=$($(package)_staging_dir) -C src install-nobase_includeHEADERS &&\
|
$(MAKE) DESTDIR=$($(package)_staging_dir) install
|
||||||
$(MAKE) DESTDIR=$($(package)_staging_dir) install-pkgconfigDATA &&\
|
|
||||||
cp -f src/.libs/libprotobuf.a $($(package)_staging_prefix_dir)/lib/
|
|
||||||
endef
|
endef
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
package=qt
|
package=qt
|
||||||
$(package)_version=6.7.2
|
$(package)_version=6.7.3
|
||||||
$(package)_download_path=https://download.qt.io/official_releases/qt/6.7/$($(package)_version)/submodules
|
$(package)_download_path=https://download.qt.io/official_releases/qt/6.7/$($(package)_version)/submodules
|
||||||
$(package)_suffix=everywhere-src-$($(package)_version).tar.xz
|
$(package)_suffix=everywhere-src-$($(package)_version).tar.xz
|
||||||
$(package)_file_name=qtbase-$($(package)_suffix)
|
$(package)_file_name=qtbase-$($(package)_suffix)
|
||||||
$(package)_sha256_hash=c5f22a5e10fb162895ded7de0963328e7307611c688487b5d152c9ee64767599
|
$(package)_sha256_hash=8ccbb9ab055205ac76632c9eeddd1ed6fc66936fc56afc2ed0fd5d9e23da3097
|
||||||
$(package)_darwin_dependencies=native_cctools native_qt openssl
|
$(package)_darwin_dependencies=native_cctools native_qt openssl
|
||||||
$(package)_mingw32_dependencies=openssl native_qt
|
$(package)_mingw32_dependencies=openssl native_qt
|
||||||
$(package)_linux_dependencies=openssl native_qt freetype fontconfig libxcb libxkbcommon libxcb_util libxcb_util_render libxcb_util_keysyms libxcb_util_image libxcb_util_wm libxcb_util_cursor dbus
|
$(package)_linux_dependencies=openssl native_qt freetype fontconfig libxcb libxkbcommon libxcb_util libxcb_util_render libxcb_util_keysyms libxcb_util_image libxcb_util_wm libxcb_util_cursor dbus
|
||||||
|
@ -22,23 +22,22 @@ $(package)_patches += revert-macOS-Silence-warning-about-supporting-secure.patch
|
||||||
$(package)_patches += no-resonance-audio.patch
|
$(package)_patches += no-resonance-audio.patch
|
||||||
$(package)_patches += fix_static_qt_darwin_camera_permissions.patch
|
$(package)_patches += fix_static_qt_darwin_camera_permissions.patch
|
||||||
$(package)_patches += revert-f67ee7c39.patch
|
$(package)_patches += revert-f67ee7c39.patch
|
||||||
$(package)_patches += CVE-2024-39936.patch
|
|
||||||
#$(package)_patches += fix-static-fontconfig-static-linking.patch
|
#$(package)_patches += fix-static-fontconfig-static-linking.patch
|
||||||
|
|
||||||
$(package)_qttools_file_name=qttools-$($(package)_suffix)
|
$(package)_qttools_file_name=qttools-$($(package)_suffix)
|
||||||
$(package)_qttools_sha256_hash=58e855ad1b2533094726c8a425766b63a04a0eede2ed85086860e54593aa4b2a
|
$(package)_qttools_sha256_hash=f03bb7df619cd9ac9dba110e30b7bcab5dd88eb8bdc9cc752563b4367233203f
|
||||||
|
|
||||||
$(package)_qtsvg_file_name=qtsvg-$($(package)_suffix)
|
$(package)_qtsvg_file_name=qtsvg-$($(package)_suffix)
|
||||||
$(package)_qtsvg_sha256_hash=fb0d1286a35be3583fee34aeb5843c94719e07193bdf1d4d8b0dc14009caef01
|
$(package)_qtsvg_sha256_hash=40142cb71fb1e07ad612bc361b67f5d54cd9367f9979ae6b86124a064deda06b
|
||||||
|
|
||||||
$(package)_qtwebsockets_file_name=qtwebsockets-$($(package)_suffix)
|
$(package)_qtwebsockets_file_name=qtwebsockets-$($(package)_suffix)
|
||||||
$(package)_qtwebsockets_sha256_hash=5bde4af6ec9ce8c8632b782ab77b82d910721be2c714e6d38902521bcd1d215f
|
$(package)_qtwebsockets_sha256_hash=ba03007db7ee68a5bc3e3bd1d71e11f3e1f84e470bcb8c54cd7c01bbe1c5990e
|
||||||
|
|
||||||
$(package)_qtmultimedia_file_name=qtmultimedia-$($(package)_suffix)
|
$(package)_qtmultimedia_file_name=qtmultimedia-$($(package)_suffix)
|
||||||
$(package)_qtmultimedia_sha256_hash=8ef835115acb9a1d3d2c9f23cfacb43f2c537e3786a8ab822299a2a7765651d3
|
$(package)_qtmultimedia_sha256_hash=304d28b8e592435293893b0110d5f3534407604d1e04d8a0b0e5b34afe577303
|
||||||
|
|
||||||
$(package)_qtshadertools_file_name=qtshadertools-$($(package)_suffix)
|
$(package)_qtshadertools_file_name=qtshadertools-$($(package)_suffix)
|
||||||
$(package)_qtshadertools_sha256_hash=edfa34c0ac8c00fcaa949df1d8e7a77d89dadd6386e683ce6c3e3b117e2f7cc1
|
$(package)_qtshadertools_sha256_hash=74e512798c7ddbda354a2d8d975211454bbabb47afb7e598892067a5828c0995
|
||||||
|
|
||||||
$(package)_extra_sources += $($(package)_qttools_file_name)
|
$(package)_extra_sources += $($(package)_qttools_file_name)
|
||||||
$(package)_extra_sources += $($(package)_qtsvg_file_name)
|
$(package)_extra_sources += $($(package)_qtsvg_file_name)
|
||||||
|
@ -55,7 +54,6 @@ $(package)_config_opts += -DINSTALL_LIBEXECDIR=$(build_prefix)/bin
|
||||||
$(package)_config_opts += -DQT_BUILD_EXAMPLES=FALSE
|
$(package)_config_opts += -DQT_BUILD_EXAMPLES=FALSE
|
||||||
$(package)_config_opts += -DQT_BUILD_TESTS=FALSE
|
$(package)_config_opts += -DQT_BUILD_TESTS=FALSE
|
||||||
$(package)_config_opts += -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake
|
$(package)_config_opts += -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake
|
||||||
|
|
||||||
$(package)_config_opts += -DINPUT_cups=no
|
$(package)_config_opts += -DINPUT_cups=no
|
||||||
$(package)_config_opts += -DINPUT_egl=no
|
$(package)_config_opts += -DINPUT_egl=no
|
||||||
$(package)_config_opts += -DINPUT_eglfs=no
|
$(package)_config_opts += -DINPUT_eglfs=no
|
||||||
|
@ -200,7 +198,6 @@ define $(package)_preprocess_cmds
|
||||||
patch -p1 -i $($(package)_patch_dir)/libxau-fix.patch && \
|
patch -p1 -i $($(package)_patch_dir)/libxau-fix.patch && \
|
||||||
patch -p1 -i $($(package)_patch_dir)/revert-macOS-Silence-warning-about-supporting-secure.patch && \
|
patch -p1 -i $($(package)_patch_dir)/revert-macOS-Silence-warning-about-supporting-secure.patch && \
|
||||||
patch -p1 -i $($(package)_patch_dir)/fix_static_qt_darwin_camera_permissions.patch && \
|
patch -p1 -i $($(package)_patch_dir)/fix_static_qt_darwin_camera_permissions.patch && \
|
||||||
patch -p1 -i $($(package)_patch_dir)/CVE-2024-39936.patch && \
|
|
||||||
cd ../qtmultimedia && \
|
cd ../qtmultimedia && \
|
||||||
patch -p1 -i $($(package)_patch_dir)/qtmultimedia-fixes.patch && \
|
patch -p1 -i $($(package)_patch_dir)/qtmultimedia-fixes.patch && \
|
||||||
patch -p1 -i $($(package)_patch_dir)/v4l2.patch && \
|
patch -p1 -i $($(package)_patch_dir)/v4l2.patch && \
|
||||||
|
|
|
@ -4,6 +4,7 @@ $(package)_download_path=https://www.nlnetlabs.nl/downloads/$(package)/
|
||||||
$(package)_file_name=$(package)-$($(package)_version).tar.gz
|
$(package)_file_name=$(package)-$($(package)_version).tar.gz
|
||||||
$(package)_sha256_hash=e7dca7d6b0f81bdfa6fa64ebf1053b5a999a5ae9278a87ef182425067ea14521
|
$(package)_sha256_hash=e7dca7d6b0f81bdfa6fa64ebf1053b5a999a5ae9278a87ef182425067ea14521
|
||||||
$(package)_dependencies=openssl expat
|
$(package)_dependencies=openssl expat
|
||||||
|
$(package)_patches += CVE-2024-8508.patch
|
||||||
|
|
||||||
define $(package)_set_vars
|
define $(package)_set_vars
|
||||||
$(package)_config_opts=--disable-shared --enable-static --without-pyunbound --prefix=$(host_prefix)
|
$(package)_config_opts=--disable-shared --enable-static --without-pyunbound --prefix=$(host_prefix)
|
||||||
|
@ -18,6 +19,7 @@ endef
|
||||||
define $(package)_preprocess_cmds
|
define $(package)_preprocess_cmds
|
||||||
rm configure~ doc/IP-BasedActions.pdf doc/ietf67-design-02.odp doc/ietf67-design-02.pdf doc/CNAME-basedRedirectionDesignNotes.pdf &&\
|
rm configure~ doc/IP-BasedActions.pdf doc/ietf67-design-02.odp doc/ietf67-design-02.pdf doc/CNAME-basedRedirectionDesignNotes.pdf &&\
|
||||||
rm -rf testdata dnscrypt/testdata &&\
|
rm -rf testdata dnscrypt/testdata &&\
|
||||||
|
patch -p1 -i $($(package)_patch_dir)/CVE-2024-8508.patch && \
|
||||||
autoconf
|
autoconf
|
||||||
endef
|
endef
|
||||||
|
|
||||||
|
|
|
@ -1,28 +1,23 @@
|
||||||
package=utf8proc
|
package=utf8proc
|
||||||
$(package)_version=2.8.0
|
$(package)_version=2.9.0
|
||||||
$(package)_download_path=https://github.com/JuliaStrings/utf8proc/archive/refs/tags/
|
$(package)_download_path=https://github.com/JuliaStrings/utf8proc/releases/download/v$($(package)_version)/
|
||||||
$(package)_download_file=v$($(package)_version).tar.gz
|
|
||||||
$(package)_file_name=$(package)-$($(package)_version).tar.gz
|
$(package)_file_name=$(package)-$($(package)_version).tar.gz
|
||||||
$(package)_sha256_hash=a0a60a79fe6f6d54e7d411facbfcc867a6e198608f2cd992490e46f04b1bcecc
|
$(package)_sha256_hash=bd215d04313b5bc42c1abedbcb0a6574667e31acee1085543a232204e36384c4
|
||||||
$(package)_patches=force_static.patch
|
$(package)_patches=force_static.patch
|
||||||
|
$(package)_build_subdir=build
|
||||||
|
|
||||||
define $(package)_preprocess_cmds
|
define $(package)_preprocess_cmds
|
||||||
patch -p1 < $($(package)_patch_dir)/force_static.patch
|
patch -p1 < $($(package)_patch_dir)/force_static.patch
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define $(package)_config_cmds
|
define $(package)_config_cmds
|
||||||
echo "$($(package)_cmake)" && \
|
$($(package)_cmake) -S .. -B .
|
||||||
mkdir build && \
|
|
||||||
cd build && \
|
|
||||||
$($(package)_cmake) ..
|
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define $(package)_build_cmds
|
define $(package)_build_cmds
|
||||||
cd build && \
|
$(MAKE)
|
||||||
$(MAKE)
|
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define $(package)_stage_cmds
|
define $(package)_stage_cmds
|
||||||
cd build && \
|
$(MAKE) DESTDIR=$($(package)_staging_dir) install
|
||||||
$(MAKE) DESTDIR=$($(package)_staging_dir) install
|
|
||||||
endef
|
endef
|
||||||
|
|
12
contrib/depends/patches/abseil/no_librt.patch
Normal file
12
contrib/depends/patches/abseil/no_librt.patch
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
diff --git a/absl/base/CMakeLists.txt b/absl/base/CMakeLists.txt
|
||||||
|
index 97994fc6..06ab426c 100644
|
||||||
|
--- a/absl/base/CMakeLists.txt
|
||||||
|
+++ b/absl/base/CMakeLists.txt
|
||||||
|
@@ -240,7 +240,6 @@ absl_cc_library(
|
||||||
|
${ABSL_DEFAULT_COPTS}
|
||||||
|
LINKOPTS
|
||||||
|
${ABSL_DEFAULT_LINKOPTS}
|
||||||
|
- $<$<BOOL:${LIBRT}>:-lrt>
|
||||||
|
$<$<BOOL:${MINGW}>:-ladvapi32>
|
||||||
|
DEPS
|
||||||
|
absl::atomic_hook
|
|
@ -13,6 +13,7 @@ endian = 'little'
|
||||||
|
|
||||||
[project options]
|
[project options]
|
||||||
utils = false
|
utils = false
|
||||||
|
examples = false
|
||||||
|
|
||||||
[built-in options]
|
[built-in options]
|
||||||
default_library = 'static'
|
default_library = 'static'
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
Subject: [PATCH] core: Declare environ for macOS and others.
|
||||||
|
---
|
||||||
|
Index: src/spawn-posix.c
|
||||||
|
IDEA additional info:
|
||||||
|
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
|
||||||
|
<+>UTF-8
|
||||||
|
===================================================================
|
||||||
|
diff --git a/src/spawn-posix.c b/src/spawn-posix.c
|
||||||
|
--- a/src/spawn-posix.c (revision d18e28a948307fab016b1eed467a70653ca9576e)
|
||||||
|
+++ b/src/spawn-posix.c (revision a59e902b887fd92337c9728f668cf9c89da3957a)
|
||||||
|
@@ -57,6 +57,9 @@
|
||||||
|
|
||||||
|
#include "gpgrt-int.h"
|
||||||
|
|
||||||
|
+/* (Only glibc's unistd.h declares this iff _GNU_SOURCE is used.) */
|
||||||
|
+extern char **environ;
|
||||||
|
+
|
||||||
|
|
||||||
|
/* Definition for the gpgrt_spawn_actions_t. Note that there is a
|
||||||
|
* different one for Windows. */
|
|
@ -1,13 +0,0 @@
|
||||||
diff --git a/preload/configure b/preload/configure
|
|
||||||
index aab5c77..e20b8f0 100755
|
|
||||||
--- a/preload/configure
|
|
||||||
+++ b/preload/configure
|
|
||||||
@@ -588,7 +588,7 @@ MAKEFLAGS=
|
|
||||||
PACKAGE_NAME='libiconv'
|
|
||||||
PACKAGE_TARNAME='libiconv'
|
|
||||||
PACKAGE_VERSION='0'
|
|
||||||
-PACKAGE_STRING='libiconv 0'
|
|
||||||
+PACKAGE_STRING='libiconv0'
|
|
||||||
PACKAGE_BUGREPORT=''
|
|
||||||
PACKAGE_URL=''
|
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
--- a/CMakeLists.txt
|
|
||||||
+++ b/CMakeLists.txt
|
|
||||||
@@ -99,7 +99,6 @@ check_function_exists(_strtoi64 HAVE__STRTOI64)
|
|
||||||
check_function_exists(_strtoui64 HAVE__STRTOUI64)
|
|
||||||
check_function_exists(_unlink HAVE__UNLINK)
|
|
||||||
check_function_exists(arc4random HAVE_ARC4RANDOM)
|
|
||||||
-check_function_exists(clonefile HAVE_CLONEFILE)
|
|
||||||
check_function_exists(explicit_bzero HAVE_EXPLICIT_BZERO)
|
|
||||||
check_function_exists(explicit_memset HAVE_EXPLICIT_MEMSET)
|
|
||||||
check_function_exists(fchmod HAVE_FCHMOD)
|
|
|
@ -1,235 +0,0 @@
|
||||||
From 2b1e36e183ce75c224305c7a94457b92f7a5cf58 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Mårten Nordheim <marten.nordheim@qt.io>
|
|
||||||
Date: Tue, 25 Jun 2024 17:09:35 +0200
|
|
||||||
Subject: [PATCH] HTTP2: Delay any communication until encrypted() can be responded to
|
|
||||||
|
|
||||||
We have the encrypted() signal that lets users do extra checks on the
|
|
||||||
established connection. It is emitted as BlockingQueued, so the HTTP
|
|
||||||
thread stalls until it is done emitting. Users can potentially call
|
|
||||||
abort() on the QNetworkReply at that point, which is passed as a Queued
|
|
||||||
call back to the HTTP thread. That means that any currently queued
|
|
||||||
signal emission will be processed before the abort() call is processed.
|
|
||||||
|
|
||||||
In the case of HTTP2 it is a little special since it is multiplexed and
|
|
||||||
the code is built to start requests as they are available. This means
|
|
||||||
that, while the code worked fine for HTTP1, since one connection only
|
|
||||||
has one request, it is not working for HTTP2, since we try to send more
|
|
||||||
requests in-between the encrypted() signal and the abort() call.
|
|
||||||
|
|
||||||
This patch changes the code to delay any communication until the
|
|
||||||
encrypted() signal has been emitted and processed, for HTTP2 only.
|
|
||||||
It's done by adding a few booleans, both to know that we have to return
|
|
||||||
early and so we can keep track of what events arose and what we need to
|
|
||||||
resume once enough time has passed that any abort() call must have been
|
|
||||||
processed.
|
|
||||||
|
|
||||||
Fixes: QTBUG-126610
|
|
||||||
Pick-to: 6.5 6.2 5.15 5.12
|
|
||||||
Change-Id: Ic25a600c278203256e35f541026f34a8783235ae
|
|
||||||
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
|
|
||||||
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
|
|
||||||
(cherry picked from commit b1e75376cc3adfc7da5502a277dfe9711f3e0536)
|
|
||||||
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
|
|
||||||
(cherry picked from commit 0fb43e4395da34d561814242a0186999e4956e28)
|
|
||||||
---
|
|
||||||
|
|
||||||
diff --git a/src/network/access/qhttp2protocolhandler.cpp b/src/network/access/qhttp2protocolhandler.cpp
|
|
||||||
index 0abd99b..3631b13 100644
|
|
||||||
--- a/src/network/access/qhttp2protocolhandler.cpp
|
|
||||||
+++ b/src/network/access/qhttp2protocolhandler.cpp
|
|
||||||
@@ -303,12 +303,12 @@
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- if (!prefaceSent && !sendClientPreface())
|
|
||||||
- return false;
|
|
||||||
-
|
|
||||||
if (!requests.size())
|
|
||||||
return true;
|
|
||||||
|
|
||||||
+ if (!prefaceSent && !sendClientPreface())
|
|
||||||
+ return false;
|
|
||||||
+
|
|
||||||
m_channel->state = QHttpNetworkConnectionChannel::WritingState;
|
|
||||||
// Check what was promised/pushed, maybe we do not have to send a request
|
|
||||||
// and have a response already?
|
|
||||||
diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp
|
|
||||||
index 6766989..1e4161d 100644
|
|
||||||
--- a/src/network/access/qhttpnetworkconnectionchannel.cpp
|
|
||||||
+++ b/src/network/access/qhttpnetworkconnectionchannel.cpp
|
|
||||||
@@ -209,6 +209,10 @@
|
|
||||||
bool QHttpNetworkConnectionChannel::sendRequest()
|
|
||||||
{
|
|
||||||
Q_ASSERT(protocolHandler);
|
|
||||||
+ if (waitingForPotentialAbort) {
|
|
||||||
+ needInvokeSendRequest = true;
|
|
||||||
+ return false; // this return value is unused
|
|
||||||
+ }
|
|
||||||
return protocolHandler->sendRequest();
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -221,21 +225,28 @@
|
|
||||||
void QHttpNetworkConnectionChannel::sendRequestDelayed()
|
|
||||||
{
|
|
||||||
QMetaObject::invokeMethod(this, [this] {
|
|
||||||
- Q_ASSERT(protocolHandler);
|
|
||||||
if (reply)
|
|
||||||
- protocolHandler->sendRequest();
|
|
||||||
+ sendRequest();
|
|
||||||
}, Qt::ConnectionType::QueuedConnection);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QHttpNetworkConnectionChannel::_q_receiveReply()
|
|
||||||
{
|
|
||||||
Q_ASSERT(protocolHandler);
|
|
||||||
+ if (waitingForPotentialAbort) {
|
|
||||||
+ needInvokeReceiveReply = true;
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
protocolHandler->_q_receiveReply();
|
|
||||||
}
|
|
||||||
|
|
||||||
void QHttpNetworkConnectionChannel::_q_readyRead()
|
|
||||||
{
|
|
||||||
Q_ASSERT(protocolHandler);
|
|
||||||
+ if (waitingForPotentialAbort) {
|
|
||||||
+ needInvokeReadyRead = true;
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
protocolHandler->_q_readyRead();
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1239,7 +1250,18 @@
|
|
||||||
if (!h2RequestsToSend.isEmpty()) {
|
|
||||||
// Similar to HTTP/1.1 counterpart below:
|
|
||||||
const auto &pair = std::as_const(h2RequestsToSend).first();
|
|
||||||
+ waitingForPotentialAbort = true;
|
|
||||||
emit pair.second->encrypted();
|
|
||||||
+
|
|
||||||
+ // We don't send or handle any received data until any effects from
|
|
||||||
+ // emitting encrypted() have been processed. This is necessary
|
|
||||||
+ // because the user may have called abort(). We may also abort the
|
|
||||||
+ // whole connection if the request has been aborted and there is
|
|
||||||
+ // no more requests to send.
|
|
||||||
+ QMetaObject::invokeMethod(this,
|
|
||||||
+ &QHttpNetworkConnectionChannel::checkAndResumeCommunication,
|
|
||||||
+ Qt::QueuedConnection);
|
|
||||||
+
|
|
||||||
// In case our peer has sent us its settings (window size, max concurrent streams etc.)
|
|
||||||
// let's give _q_receiveReply a chance to read them first ('invokeMethod', QueuedConnection).
|
|
||||||
}
|
|
||||||
@@ -1257,6 +1279,28 @@
|
|
||||||
QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection);
|
|
||||||
}
|
|
||||||
|
|
||||||
+
|
|
||||||
+void QHttpNetworkConnectionChannel::checkAndResumeCommunication()
|
|
||||||
+{
|
|
||||||
+ Q_ASSERT(connection->connectionType() == QHttpNetworkConnection::ConnectionTypeHTTP2
|
|
||||||
+ || connection->connectionType() == QHttpNetworkConnection::ConnectionTypeHTTP2Direct);
|
|
||||||
+
|
|
||||||
+ // Because HTTP/2 requires that we send a SETTINGS frame as the first thing we do, and respond
|
|
||||||
+ // to a SETTINGS frame with an ACK, we need to delay any handling until we can ensure that any
|
|
||||||
+ // effects from emitting encrypted() have been processed.
|
|
||||||
+ // This function is called after encrypted() was emitted, so check for changes.
|
|
||||||
+
|
|
||||||
+ if (!reply && h2RequestsToSend.isEmpty())
|
|
||||||
+ abort();
|
|
||||||
+ waitingForPotentialAbort = false;
|
|
||||||
+ if (needInvokeReadyRead)
|
|
||||||
+ _q_readyRead();
|
|
||||||
+ if (needInvokeReceiveReply)
|
|
||||||
+ _q_receiveReply();
|
|
||||||
+ if (needInvokeSendRequest)
|
|
||||||
+ sendRequest();
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
void QHttpNetworkConnectionChannel::requeueHttp2Requests()
|
|
||||||
{
|
|
||||||
const auto h2RequestsToSendCopy = std::exchange(h2RequestsToSend, {});
|
|
||||||
diff --git a/src/network/access/qhttpnetworkconnectionchannel_p.h b/src/network/access/qhttpnetworkconnectionchannel_p.h
|
|
||||||
index c42290f..061f20f 100644
|
|
||||||
--- a/src/network/access/qhttpnetworkconnectionchannel_p.h
|
|
||||||
+++ b/src/network/access/qhttpnetworkconnectionchannel_p.h
|
|
||||||
@@ -74,6 +74,10 @@
|
|
||||||
QAbstractSocket *socket;
|
|
||||||
bool ssl;
|
|
||||||
bool isInitialized;
|
|
||||||
+ bool waitingForPotentialAbort = false;
|
|
||||||
+ bool needInvokeReceiveReply = false;
|
|
||||||
+ bool needInvokeReadyRead = false;
|
|
||||||
+ bool needInvokeSendRequest = false;
|
|
||||||
ChannelState state;
|
|
||||||
QHttpNetworkRequest request; // current request, only used for HTTP
|
|
||||||
QHttpNetworkReply *reply; // current reply for this request, only used for HTTP
|
|
||||||
@@ -146,6 +150,8 @@
|
|
||||||
void closeAndResendCurrentRequest();
|
|
||||||
void resendCurrentRequest();
|
|
||||||
|
|
||||||
+ void checkAndResumeCommunication();
|
|
||||||
+
|
|
||||||
bool isSocketBusy() const;
|
|
||||||
bool isSocketWriting() const;
|
|
||||||
bool isSocketWaiting() const;
|
|
||||||
diff --git a/tests/auto/network/access/http2/tst_http2.cpp b/tests/auto/network/access/http2/tst_http2.cpp
|
|
||||||
index 00efbc9..c02e7b7 100644
|
|
||||||
--- a/tests/auto/network/access/http2/tst_http2.cpp
|
|
||||||
+++ b/tests/auto/network/access/http2/tst_http2.cpp
|
|
||||||
@@ -106,6 +106,8 @@
|
|
||||||
|
|
||||||
void duplicateRequestsWithAborts();
|
|
||||||
|
|
||||||
+ void abortOnEncrypted();
|
|
||||||
+
|
|
||||||
protected slots:
|
|
||||||
// Slots to listen to our in-process server:
|
|
||||||
void serverStarted(quint16 port);
|
|
||||||
@@ -1479,6 +1481,48 @@
|
|
||||||
QCOMPARE(finishedCount, ExpectedSuccessfulRequests);
|
|
||||||
}
|
|
||||||
|
|
||||||
+void tst_Http2::abortOnEncrypted()
|
|
||||||
+{
|
|
||||||
+#if !QT_CONFIG(ssl)
|
|
||||||
+ QSKIP("TLS support is needed for this test");
|
|
||||||
+#else
|
|
||||||
+ clearHTTP2State();
|
|
||||||
+ serverPort = 0;
|
|
||||||
+
|
|
||||||
+ ServerPtr targetServer(newServer(defaultServerSettings, H2Type::h2Direct));
|
|
||||||
+
|
|
||||||
+ QMetaObject::invokeMethod(targetServer.data(), "startServer", Qt::QueuedConnection);
|
|
||||||
+ runEventLoop();
|
|
||||||
+
|
|
||||||
+ nRequests = 1;
|
|
||||||
+ nSentRequests = 0;
|
|
||||||
+
|
|
||||||
+ const auto url = requestUrl(H2Type::h2Direct);
|
|
||||||
+ QNetworkRequest request(url);
|
|
||||||
+ request.setAttribute(QNetworkRequest::Http2DirectAttribute, true);
|
|
||||||
+
|
|
||||||
+ std::unique_ptr<QNetworkReply> reply{manager->get(request)};
|
|
||||||
+ reply->ignoreSslErrors();
|
|
||||||
+ connect(reply.get(), &QNetworkReply::encrypted, reply.get(), [reply = reply.get()](){
|
|
||||||
+ reply->abort();
|
|
||||||
+ });
|
|
||||||
+ connect(reply.get(), &QNetworkReply::errorOccurred, this, &tst_Http2::replyFinishedWithError);
|
|
||||||
+
|
|
||||||
+ runEventLoop();
|
|
||||||
+ STOP_ON_FAILURE
|
|
||||||
+
|
|
||||||
+ QCOMPARE(nRequests, 0);
|
|
||||||
+ QCOMPARE(reply->error(), QNetworkReply::OperationCanceledError);
|
|
||||||
+
|
|
||||||
+ const bool res = QTest::qWaitFor(
|
|
||||||
+ [this, server = targetServer.get()]() {
|
|
||||||
+ return serverGotSettingsACK || prefaceOK || nSentRequests > 0;
|
|
||||||
+ },
|
|
||||||
+ 500);
|
|
||||||
+ QVERIFY(!res);
|
|
||||||
+#endif // QT_CONFIG(ssl)
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
void tst_Http2::serverStarted(quint16 port)
|
|
||||||
{
|
|
||||||
serverPort = port;
|
|
236
contrib/depends/patches/unbound/CVE-2024-8508.patch
Normal file
236
contrib/depends/patches/unbound/CVE-2024-8508.patch
Normal file
|
@ -0,0 +1,236 @@
|
||||||
|
diff --git a/util/data/msgencode.c b/util/data/msgencode.c
|
||||||
|
index 898ff841..6d116fb5 100644
|
||||||
|
--- a/util/data/msgencode.c
|
||||||
|
+++ b/util/data/msgencode.c
|
||||||
|
@@ -62,6 +62,10 @@
|
||||||
|
#define RETVAL_TRUNC -4
|
||||||
|
/** return code that means all is peachy keen. Equal to DNS rcode NOERROR */
|
||||||
|
#define RETVAL_OK 0
|
||||||
|
+/** Max compressions we are willing to perform; more than that will result
|
||||||
|
+ * in semi-compressed messages, or truncated even on TCP for huge messages, to
|
||||||
|
+ * avoid locking the CPU for long */
|
||||||
|
+#define MAX_COMPRESSION_PER_MESSAGE 120
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data structure to help domain name compression in outgoing messages.
|
||||||
|
@@ -284,15 +288,17 @@ write_compressed_dname(sldns_buffer* pkt, uint8_t* dname, int labs,
|
||||||
|
|
||||||
|
/** compress owner name of RR, return RETVAL_OUTMEM RETVAL_TRUNC */
|
||||||
|
static int
|
||||||
|
-compress_owner(struct ub_packed_rrset_key* key, sldns_buffer* pkt,
|
||||||
|
- struct regional* region, struct compress_tree_node** tree,
|
||||||
|
- size_t owner_pos, uint16_t* owner_ptr, int owner_labs)
|
||||||
|
+compress_owner(struct ub_packed_rrset_key* key, sldns_buffer* pkt,
|
||||||
|
+ struct regional* region, struct compress_tree_node** tree,
|
||||||
|
+ size_t owner_pos, uint16_t* owner_ptr, int owner_labs,
|
||||||
|
+ size_t* compress_count)
|
||||||
|
{
|
||||||
|
struct compress_tree_node* p;
|
||||||
|
struct compress_tree_node** insertpt = NULL;
|
||||||
|
if(!*owner_ptr) {
|
||||||
|
/* compress first time dname */
|
||||||
|
- if((p = compress_tree_lookup(tree, key->rk.dname,
|
||||||
|
+ if(*compress_count < MAX_COMPRESSION_PER_MESSAGE &&
|
||||||
|
+ (p = compress_tree_lookup(tree, key->rk.dname,
|
||||||
|
owner_labs, &insertpt))) {
|
||||||
|
if(p->labs == owner_labs)
|
||||||
|
/* avoid ptr chains, since some software is
|
||||||
|
@@ -301,6 +307,7 @@ compress_owner(struct ub_packed_rrset_key* key, sldns_buffer* pkt,
|
||||||
|
if(!write_compressed_dname(pkt, key->rk.dname,
|
||||||
|
owner_labs, p))
|
||||||
|
return RETVAL_TRUNC;
|
||||||
|
+ (*compress_count)++;
|
||||||
|
/* check if typeclass+4 ttl + rdatalen is available */
|
||||||
|
if(sldns_buffer_remaining(pkt) < 4+4+2)
|
||||||
|
return RETVAL_TRUNC;
|
||||||
|
@@ -313,7 +320,8 @@ compress_owner(struct ub_packed_rrset_key* key, sldns_buffer* pkt,
|
||||||
|
if(owner_pos <= PTR_MAX_OFFSET)
|
||||||
|
*owner_ptr = htons(PTR_CREATE(owner_pos));
|
||||||
|
}
|
||||||
|
- if(!compress_tree_store(key->rk.dname, owner_labs,
|
||||||
|
+ if(*compress_count < MAX_COMPRESSION_PER_MESSAGE &&
|
||||||
|
+ !compress_tree_store(key->rk.dname, owner_labs,
|
||||||
|
owner_pos, region, p, insertpt))
|
||||||
|
return RETVAL_OUTMEM;
|
||||||
|
} else {
|
||||||
|
@@ -333,20 +341,24 @@ compress_owner(struct ub_packed_rrset_key* key, sldns_buffer* pkt,
|
||||||
|
|
||||||
|
/** compress any domain name to the packet, return RETVAL_* */
|
||||||
|
static int
|
||||||
|
-compress_any_dname(uint8_t* dname, sldns_buffer* pkt, int labs,
|
||||||
|
- struct regional* region, struct compress_tree_node** tree)
|
||||||
|
+compress_any_dname(uint8_t* dname, sldns_buffer* pkt, int labs,
|
||||||
|
+ struct regional* region, struct compress_tree_node** tree,
|
||||||
|
+ size_t* compress_count)
|
||||||
|
{
|
||||||
|
struct compress_tree_node* p;
|
||||||
|
struct compress_tree_node** insertpt = NULL;
|
||||||
|
size_t pos = sldns_buffer_position(pkt);
|
||||||
|
- if((p = compress_tree_lookup(tree, dname, labs, &insertpt))) {
|
||||||
|
+ if(*compress_count < MAX_COMPRESSION_PER_MESSAGE &&
|
||||||
|
+ (p = compress_tree_lookup(tree, dname, labs, &insertpt))) {
|
||||||
|
if(!write_compressed_dname(pkt, dname, labs, p))
|
||||||
|
return RETVAL_TRUNC;
|
||||||
|
+ (*compress_count)++;
|
||||||
|
} else {
|
||||||
|
if(!dname_buffer_write(pkt, dname))
|
||||||
|
return RETVAL_TRUNC;
|
||||||
|
}
|
||||||
|
- if(!compress_tree_store(dname, labs, pos, region, p, insertpt))
|
||||||
|
+ if(*compress_count < MAX_COMPRESSION_PER_MESSAGE &&
|
||||||
|
+ !compress_tree_store(dname, labs, pos, region, p, insertpt))
|
||||||
|
return RETVAL_OUTMEM;
|
||||||
|
return RETVAL_OK;
|
||||||
|
}
|
||||||
|
@@ -364,9 +376,9 @@ type_rdata_compressable(struct ub_packed_rrset_key* key)
|
||||||
|
|
||||||
|
/** compress domain names in rdata, return RETVAL_* */
|
||||||
|
static int
|
||||||
|
-compress_rdata(sldns_buffer* pkt, uint8_t* rdata, size_t todolen,
|
||||||
|
- struct regional* region, struct compress_tree_node** tree,
|
||||||
|
- const sldns_rr_descriptor* desc)
|
||||||
|
+compress_rdata(sldns_buffer* pkt, uint8_t* rdata, size_t todolen,
|
||||||
|
+ struct regional* region, struct compress_tree_node** tree,
|
||||||
|
+ const sldns_rr_descriptor* desc, size_t* compress_count)
|
||||||
|
{
|
||||||
|
int labs, r, rdf = 0;
|
||||||
|
size_t dname_len, len, pos = sldns_buffer_position(pkt);
|
||||||
|
@@ -380,8 +392,8 @@ compress_rdata(sldns_buffer* pkt, uint8_t* rdata, size_t todolen,
|
||||||
|
switch(desc->_wireformat[rdf]) {
|
||||||
|
case LDNS_RDF_TYPE_DNAME:
|
||||||
|
labs = dname_count_size_labels(rdata, &dname_len);
|
||||||
|
- if((r=compress_any_dname(rdata, pkt, labs, region,
|
||||||
|
- tree)) != RETVAL_OK)
|
||||||
|
+ if((r=compress_any_dname(rdata, pkt, labs, region,
|
||||||
|
+ tree, compress_count)) != RETVAL_OK)
|
||||||
|
return r;
|
||||||
|
rdata += dname_len;
|
||||||
|
todolen -= dname_len;
|
||||||
|
@@ -449,7 +461,8 @@ static int
|
||||||
|
packed_rrset_encode(struct ub_packed_rrset_key* key, sldns_buffer* pkt,
|
||||||
|
uint16_t* num_rrs, time_t timenow, struct regional* region,
|
||||||
|
int do_data, int do_sig, struct compress_tree_node** tree,
|
||||||
|
- sldns_pkt_section s, uint16_t qtype, int dnssec, size_t rr_offset)
|
||||||
|
+ sldns_pkt_section s, uint16_t qtype, int dnssec, size_t rr_offset,
|
||||||
|
+ size_t* compress_count)
|
||||||
|
{
|
||||||
|
size_t i, j, owner_pos;
|
||||||
|
int r, owner_labs;
|
||||||
|
@@ -477,9 +490,9 @@ packed_rrset_encode(struct ub_packed_rrset_key* key, sldns_buffer* pkt,
|
||||||
|
for(i=0; i<data->count; i++) {
|
||||||
|
/* rrset roundrobin */
|
||||||
|
j = (i + rr_offset) % data->count;
|
||||||
|
- if((r=compress_owner(key, pkt, region, tree,
|
||||||
|
- owner_pos, &owner_ptr, owner_labs))
|
||||||
|
- != RETVAL_OK)
|
||||||
|
+ if((r=compress_owner(key, pkt, region, tree,
|
||||||
|
+ owner_pos, &owner_ptr, owner_labs,
|
||||||
|
+ compress_count)) != RETVAL_OK)
|
||||||
|
return r;
|
||||||
|
sldns_buffer_write(pkt, &key->rk.type, 2);
|
||||||
|
sldns_buffer_write(pkt, &key->rk.rrset_class, 2);
|
||||||
|
@@ -489,8 +502,8 @@ packed_rrset_encode(struct ub_packed_rrset_key* key, sldns_buffer* pkt,
|
||||||
|
else sldns_buffer_write_u32(pkt, data->rr_ttl[j]-adjust);
|
||||||
|
if(c) {
|
||||||
|
if((r=compress_rdata(pkt, data->rr_data[j],
|
||||||
|
- data->rr_len[j], region, tree, c))
|
||||||
|
- != RETVAL_OK)
|
||||||
|
+ data->rr_len[j], region, tree, c,
|
||||||
|
+ compress_count)) != RETVAL_OK)
|
||||||
|
return r;
|
||||||
|
} else {
|
||||||
|
if(sldns_buffer_remaining(pkt) < data->rr_len[j])
|
||||||
|
@@ -510,9 +523,9 @@ packed_rrset_encode(struct ub_packed_rrset_key* key, sldns_buffer* pkt,
|
||||||
|
return RETVAL_TRUNC;
|
||||||
|
sldns_buffer_write(pkt, &owner_ptr, 2);
|
||||||
|
} else {
|
||||||
|
- if((r=compress_any_dname(key->rk.dname,
|
||||||
|
- pkt, owner_labs, region, tree))
|
||||||
|
- != RETVAL_OK)
|
||||||
|
+ if((r=compress_any_dname(key->rk.dname,
|
||||||
|
+ pkt, owner_labs, region, tree,
|
||||||
|
+ compress_count)) != RETVAL_OK)
|
||||||
|
return r;
|
||||||
|
if(sldns_buffer_remaining(pkt) <
|
||||||
|
4+4+data->rr_len[i])
|
||||||
|
@@ -544,7 +557,8 @@ static int
|
||||||
|
insert_section(struct reply_info* rep, size_t num_rrsets, uint16_t* num_rrs,
|
||||||
|
sldns_buffer* pkt, size_t rrsets_before, time_t timenow,
|
||||||
|
struct regional* region, struct compress_tree_node** tree,
|
||||||
|
- sldns_pkt_section s, uint16_t qtype, int dnssec, size_t rr_offset)
|
||||||
|
+ sldns_pkt_section s, uint16_t qtype, int dnssec, size_t rr_offset,
|
||||||
|
+ size_t* compress_count)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
size_t i, setstart;
|
||||||
|
@@ -560,7 +574,7 @@ insert_section(struct reply_info* rep, size_t num_rrsets, uint16_t* num_rrs,
|
||||||
|
setstart = sldns_buffer_position(pkt);
|
||||||
|
if((r=packed_rrset_encode(rep->rrsets[rrsets_before+i],
|
||||||
|
pkt, num_rrs, timenow, region, 1, 1, tree,
|
||||||
|
- s, qtype, dnssec, rr_offset))
|
||||||
|
+ s, qtype, dnssec, rr_offset, compress_count))
|
||||||
|
!= RETVAL_OK) {
|
||||||
|
/* Bad, but if due to size must set TC bit */
|
||||||
|
/* trim off the rrset neatly. */
|
||||||
|
@@ -573,7 +587,7 @@ insert_section(struct reply_info* rep, size_t num_rrsets, uint16_t* num_rrs,
|
||||||
|
setstart = sldns_buffer_position(pkt);
|
||||||
|
if((r=packed_rrset_encode(rep->rrsets[rrsets_before+i],
|
||||||
|
pkt, num_rrs, timenow, region, 1, 0, tree,
|
||||||
|
- s, qtype, dnssec, rr_offset))
|
||||||
|
+ s, qtype, dnssec, rr_offset, compress_count))
|
||||||
|
!= RETVAL_OK) {
|
||||||
|
sldns_buffer_set_position(pkt, setstart);
|
||||||
|
return r;
|
||||||
|
@@ -584,7 +598,7 @@ insert_section(struct reply_info* rep, size_t num_rrsets, uint16_t* num_rrs,
|
||||||
|
setstart = sldns_buffer_position(pkt);
|
||||||
|
if((r=packed_rrset_encode(rep->rrsets[rrsets_before+i],
|
||||||
|
pkt, num_rrs, timenow, region, 0, 1, tree,
|
||||||
|
- s, qtype, dnssec, rr_offset))
|
||||||
|
+ s, qtype, dnssec, rr_offset, compress_count))
|
||||||
|
!= RETVAL_OK) {
|
||||||
|
sldns_buffer_set_position(pkt, setstart);
|
||||||
|
return r;
|
||||||
|
@@ -677,6 +691,7 @@ reply_info_encode(struct query_info* qinfo, struct reply_info* rep,
|
||||||
|
struct compress_tree_node* tree = 0;
|
||||||
|
int r;
|
||||||
|
size_t rr_offset;
|
||||||
|
+ size_t compress_count=0;
|
||||||
|
|
||||||
|
sldns_buffer_clear(buffer);
|
||||||
|
if(udpsize < sldns_buffer_limit(buffer))
|
||||||
|
@@ -723,7 +738,7 @@ reply_info_encode(struct query_info* qinfo, struct reply_info* rep,
|
||||||
|
arep.rrsets = &qinfo->local_alias->rrset;
|
||||||
|
if((r=insert_section(&arep, 1, &ancount, buffer, 0,
|
||||||
|
timezero, region, &tree, LDNS_SECTION_ANSWER,
|
||||||
|
- qinfo->qtype, dnssec, rr_offset)) != RETVAL_OK) {
|
||||||
|
+ qinfo->qtype, dnssec, rr_offset, &compress_count)) != RETVAL_OK) {
|
||||||
|
if(r == RETVAL_TRUNC) {
|
||||||
|
/* create truncated message */
|
||||||
|
sldns_buffer_write_u16_at(buffer, 6, ancount);
|
||||||
|
@@ -738,7 +753,7 @@ reply_info_encode(struct query_info* qinfo, struct reply_info* rep,
|
||||||
|
/* insert answer section */
|
||||||
|
if((r=insert_section(rep, rep->an_numrrsets, &ancount, buffer,
|
||||||
|
0, timenow, region, &tree, LDNS_SECTION_ANSWER, qinfo->qtype,
|
||||||
|
- dnssec, rr_offset)) != RETVAL_OK) {
|
||||||
|
+ dnssec, rr_offset, &compress_count)) != RETVAL_OK) {
|
||||||
|
if(r == RETVAL_TRUNC) {
|
||||||
|
/* create truncated message */
|
||||||
|
sldns_buffer_write_u16_at(buffer, 6, ancount);
|
||||||
|
@@ -756,7 +771,7 @@ reply_info_encode(struct query_info* qinfo, struct reply_info* rep,
|
||||||
|
if((r=insert_section(rep, rep->ns_numrrsets, &nscount, buffer,
|
||||||
|
rep->an_numrrsets, timenow, region, &tree,
|
||||||
|
LDNS_SECTION_AUTHORITY, qinfo->qtype,
|
||||||
|
- dnssec, rr_offset)) != RETVAL_OK) {
|
||||||
|
+ dnssec, rr_offset, &compress_count)) != RETVAL_OK) {
|
||||||
|
if(r == RETVAL_TRUNC) {
|
||||||
|
/* create truncated message */
|
||||||
|
sldns_buffer_write_u16_at(buffer, 8, nscount);
|
||||||
|
@@ -773,7 +788,7 @@ reply_info_encode(struct query_info* qinfo, struct reply_info* rep,
|
||||||
|
if((r=insert_section(rep, rep->ar_numrrsets, &arcount, buffer,
|
||||||
|
rep->an_numrrsets + rep->ns_numrrsets, timenow, region,
|
||||||
|
&tree, LDNS_SECTION_ADDITIONAL, qinfo->qtype,
|
||||||
|
- dnssec, rr_offset)) != RETVAL_OK) {
|
||||||
|
+ dnssec, rr_offset, &compress_count)) != RETVAL_OK) {
|
||||||
|
if(r == RETVAL_TRUNC) {
|
||||||
|
/* no need to set TC bit, this is the additional */
|
||||||
|
sldns_buffer_write_u16_at(buffer, 10, arcount);
|
|
@ -40,6 +40,9 @@ SET(Terminfo_LIBRARY @prefix@/lib/libtinfo.a)
|
||||||
SET(UNBOUND_INCLUDE_DIR @prefix@/include)
|
SET(UNBOUND_INCLUDE_DIR @prefix@/include)
|
||||||
SET(UNBOUND_LIBRARIES @prefix@/lib/libunbound.a)
|
SET(UNBOUND_LIBRARIES @prefix@/lib/libunbound.a)
|
||||||
|
|
||||||
|
SET(CMAKE_FIND_USE_PACKAGE_ROOT_PATH ON)
|
||||||
|
SET(absl_ROOT @prefix@)
|
||||||
|
|
||||||
SET(NATIVE_BIN_PATH @prefix@/native/bin CACHE FILEPATH "path to native binaries" FORCE)
|
SET(NATIVE_BIN_PATH @prefix@/native/bin CACHE FILEPATH "path to native binaries" FORCE)
|
||||||
SET(LRELEASE_PATH @prefix@/native/bin CACHE FILEPATH "path to lrelease" FORCE)
|
SET(LRELEASE_PATH @prefix@/native/bin CACHE FILEPATH "path to lrelease" FORCE)
|
||||||
|
|
||||||
|
@ -52,17 +55,10 @@ if(NOT CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
|
||||||
SET(LIBUSB-1.0_LIBRARY @prefix@/lib/libusb-1.0.a)
|
SET(LIBUSB-1.0_LIBRARY @prefix@/lib/libusb-1.0.a)
|
||||||
SET(LIBUDEV_LIBRARY @prefix@/lib/libudev.a)
|
SET(LIBUDEV_LIBRARY @prefix@/lib/libudev.a)
|
||||||
|
|
||||||
SET(Protobuf_FOUND 1)
|
|
||||||
SET(Protobuf_PROTOC_EXECUTABLE @prefix@/native/bin/protoc CACHE FILEPATH "Path to the native protoc")
|
|
||||||
SET(Protobuf_INCLUDE_DIR @prefix@/include CACHE PATH "Protobuf include dir")
|
|
||||||
SET(Protobuf_INCLUDE_DIRS @prefix@/include CACHE PATH "Protobuf include dir")
|
|
||||||
SET(Protobuf_LIBRARY @prefix@/lib/libprotobuf.a CACHE FILEPATH "Protobuf library")
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(ICONV_LIBRARIES @prefix@/lib/libiconv.a)
|
|
||||||
|
|
||||||
SET(ZMQ_INCLUDE_PATH @prefix@/include)
|
SET(ZMQ_INCLUDE_PATH @prefix@/include)
|
||||||
SET(ZMQ_LIB @prefix@/lib/libzmq.a)
|
SET(ZMQ_LIB @prefix@/lib/libzmq.a)
|
||||||
|
|
||||||
|
@ -123,22 +119,6 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
|
||||||
SET(CMAKE_CXX_STANDARD 17)
|
SET(CMAKE_CXX_STANDARD 17)
|
||||||
SET(LLVM_ENABLE_PIC OFF)
|
SET(LLVM_ENABLE_PIC OFF)
|
||||||
SET(LLVM_ENABLE_PIE OFF)
|
SET(LLVM_ENABLE_PIE OFF)
|
||||||
elseif(CMAKE_SYSTEM_NAME STREQUAL "Android")
|
|
||||||
SET(ANDROID TRUE)
|
|
||||||
if(ARCHITECTURE STREQUAL "arm")
|
|
||||||
SET(CMAKE_ANDROID_ARCH_ABI "armeabi-v7a")
|
|
||||||
SET(CMAKE_SYSTEM_PROCESSOR "armv7-a")
|
|
||||||
SET(CMAKE_ANDROID_ARM_MODE ON)
|
|
||||||
SET(CMAKE_C_COMPILER_TARGET arm-linux-androideabi)
|
|
||||||
SET(CMAKE_CXX_COMPILER_TARGET arm-linux-androideabi)
|
|
||||||
SET(_CMAKE_TOOLCHAIN_PREFIX arm-linux-androideabi-)
|
|
||||||
elseif(ARCHITECTURE STREQUAL "aarch64")
|
|
||||||
SET(CMAKE_ANDROID_ARCH_ABI "arm64-v8a")
|
|
||||||
SET(CMAKE_SYSTEM_PROCESSOR "aarch64")
|
|
||||||
endif()
|
|
||||||
SET(CMAKE_ANDROID_STANDALONE_TOOLCHAIN @prefix@/native)
|
|
||||||
SET(CMAKE_C_COMPILER "${_CMAKE_TOOLCHAIN_PREFIX}clang")
|
|
||||||
SET(CMAKE_CXX_COMPILER "${_CMAKE_TOOLCHAIN_PREFIX}clang++")
|
|
||||||
else()
|
else()
|
||||||
SET(CMAKE_C_COMPILER @CC@)
|
SET(CMAKE_C_COMPILER @CC@)
|
||||||
SET(CMAKE_CXX_COMPILER @CXX@)
|
SET(CMAKE_CXX_COMPILER @CXX@)
|
||||||
|
|
|
@ -1,21 +1,72 @@
|
||||||
# Bootstrappable Feather Wallet Builds
|
# Bootstrappable Feather Wallet Builds
|
||||||
|
|
||||||
This directory contains the files necessary to perform bootstrappable Feather Wallet
|
This directory contains the files necessary to perform [bootstrappable](https://bootstrappable.org) Feather Wallet builds.
|
||||||
builds.
|
|
||||||
|
|
||||||
[Bootstrappability][b17e] furthers our binary security guarantees by allowing us
|
Bootstrappability allows us to _audit and reproduce_ our toolchain instead of blindly _trusting_ binary downloads.
|
||||||
to _audit and reproduce_ our toolchain instead of blindly _trusting_ binary
|
Our build environment can be built from source, [all the way down](https://guix.gnu.org/en/blog/2023/the-full-source-bootstrap-building-from-source-all-the-way-down/).
|
||||||
downloads.
|
|
||||||
|
|
||||||
We achieve bootstrappability by using Guix as a functional package manager.
|
We achieve bootstrappability by using [Guix](https://guix.gnu.org/) as a functional package manager. Guix runs on any Linux distribution and on
|
||||||
|
most architectures (x86_64, aarch64, riscv64). To produce reproducible release binaries, you only need to install Guix
|
||||||
|
and run the build script.
|
||||||
|
|
||||||
|
Guix allows us to modify any detail about our build environment with ease.
|
||||||
|
Unlike [Gitian](https://github.com/devrandom/gitian-builder), we are not limited to the package set of a particular Ubuntu version.
|
||||||
|
With Guix, we can configure our toolchains to use the latest compilers while still targeting older versions of glibc.
|
||||||
|
We drastically reduce our supply chain attack surface by only including the package we need in our build environment, and nothing else.
|
||||||
|
Packages that are not available in Guix can easily be defined in the [manifest](https://github.com/feather-wallet/feather/blob/master/contrib/guix/manifest.scm) or upstreamed.
|
||||||
|
|
||||||
|
Feather releases are independently reproduced and cryptographically attested to by multiple contributors.
|
||||||
|
You can submit attestations to the [feather-sigs](https://github.com/feather-wallet/feather-sigs) repo.
|
||||||
|
|
||||||
# Requirements
|
# Requirements
|
||||||
|
|
||||||
Conservatively, you will need an x86_64 machine with:
|
- any Linux distribution
|
||||||
|
- 50 GB of free disk space
|
||||||
|
- 4 or more cores recommended
|
||||||
|
- 2 GB RAM per thread
|
||||||
|
|
||||||
- 16GB of free disk space on the partition that /gnu/store will reside in
|
# Quick setup
|
||||||
- 8GB of free disk space **per platform triple** you're planning on building
|
|
||||||
(see the `HOSTS` [environment variable description][env-vars-list])
|
If you're just here to get a build running (e.g. to test your changes) and quickly want to get up and running:
|
||||||
|
|
||||||
|
### Install Guix
|
||||||
|
|
||||||
|
On Ubuntu 22.04, Debian 11, or later:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ apt install guix
|
||||||
|
```
|
||||||
|
|
||||||
|
If Guix is not available in your package manager, use the official [install script](https://guix.gnu.org/manual/en/html_node/Binary-Installation.html).
|
||||||
|
|
||||||
|
### Clone the repo
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ git clone https://github.com/feather-wallet/feather
|
||||||
|
$ cd feather
|
||||||
|
```
|
||||||
|
|
||||||
|
### Run the build
|
||||||
|
|
||||||
|
To build all targets using all available cores:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ ./contrib/guix/guix-build
|
||||||
|
```
|
||||||
|
|
||||||
|
To limit the number of threads to N:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ JOBS=N ./contrib/guix/guix-build
|
||||||
|
```
|
||||||
|
|
||||||
|
To only build the x86_64 linux target:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ HOSTS="x86_64-linux-gnu" ./contrib/guix/guix-build
|
||||||
|
```
|
||||||
|
|
||||||
|
More recognized environment variables can be found further below.
|
||||||
|
|
||||||
# Installation and Setup
|
# Installation and Setup
|
||||||
|
|
||||||
|
@ -362,6 +413,5 @@ used.
|
||||||
If you start `guix-daemon` using an init script, you can edit said script to
|
If you start `guix-daemon` using an init script, you can edit said script to
|
||||||
supply this flag.
|
supply this flag.
|
||||||
|
|
||||||
[b17e]: https://bootstrappable.org/
|
|
||||||
[r12e/source-date-epoch]: https://reproducible-builds.org/docs/source-date-epoch/
|
[r12e/source-date-epoch]: https://reproducible-builds.org/docs/source-date-epoch/
|
||||||
[env-vars-list]: #recognized-environment-variables
|
[env-vars-list]: #recognized-environment-variables
|
||||||
|
|
|
@ -292,6 +292,8 @@ case "$HOST" in
|
||||||
arm-linux-gnueabihf) HOST_CXXFLAGS="${HOST_CXXFLAGS} -Wno-psabi" ;;
|
arm-linux-gnueabihf) HOST_CXXFLAGS="${HOST_CXXFLAGS} -Wno-psabi" ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
|
export USE_DEVICE_TREZOR_MANDATORY=1
|
||||||
|
|
||||||
# Make $HOST-specific native binaries from depends available in $PATH
|
# Make $HOST-specific native binaries from depends available in $PATH
|
||||||
export PATH="${BASEPREFIX}/${HOST}/native/bin:${PATH}"
|
export PATH="${BASEPREFIX}/${HOST}/native/bin:${PATH}"
|
||||||
mkdir -p "$DISTSRC"
|
mkdir -p "$DISTSRC"
|
||||||
|
|
|
@ -51,7 +51,7 @@ fi
|
||||||
time-machine() {
|
time-machine() {
|
||||||
# shellcheck disable=SC2086
|
# shellcheck disable=SC2086
|
||||||
guix time-machine --url=https://github.com/tobtoht/guix.git \
|
guix time-machine --url=https://github.com/tobtoht/guix.git \
|
||||||
--commit=f0bb724211872cd6158fce6162e0b8c73efed126 \
|
--commit=7bf1d7aeaffba15c4f680f93ae88fbef25427252 \
|
||||||
--cores="$JOBS" \
|
--cores="$JOBS" \
|
||||||
--keep-failed \
|
--keep-failed \
|
||||||
--fallback \
|
--fallback \
|
||||||
|
|
|
@ -120,10 +120,17 @@ desirable for building Feather Wallet release binaries."
|
||||||
(search-our-patches "gcc-remap-guix-store.patch"
|
(search-our-patches "gcc-remap-guix-store.patch"
|
||||||
"vmov-alignment.patch")))
|
"vmov-alignment.patch")))
|
||||||
|
|
||||||
|
(define (winpthreads-patches mingw-w64-x86_64-winpthreads)
|
||||||
|
(package-with-extra-patches mingw-w64-x86_64-winpthreads
|
||||||
|
(search-our-patches "winpthreads-remap-guix-store.patch")))
|
||||||
|
|
||||||
(define (make-mingw-pthreads-cross-toolchain target)
|
(define (make-mingw-pthreads-cross-toolchain target)
|
||||||
"Create a cross-compilation toolchain package for TARGET"
|
"Create a cross-compilation toolchain package for TARGET"
|
||||||
(let* ((xbinutils (cross-binutils target))
|
(let* ((xbinutils (cross-binutils target))
|
||||||
(pthreads-xlibc mingw-w64-x86_64-winpthreads)
|
(machine (substring target 0 (string-index target #\-)))
|
||||||
|
(pthreads-xlibc (winpthreads-patches (make-mingw-w64 machine
|
||||||
|
#:xgcc (cross-gcc target #:xgcc (gcc-mingw-patches base-gcc))
|
||||||
|
#:with-winpthreads? #t)))
|
||||||
(pthreads-xgcc (cross-gcc target
|
(pthreads-xgcc (cross-gcc target
|
||||||
#:xgcc (gcc-mingw-patches mingw-w64-base-gcc)
|
#:xgcc (gcc-mingw-patches mingw-w64-base-gcc)
|
||||||
#:xbinutils xbinutils
|
#:xbinutils xbinutils
|
||||||
|
@ -322,8 +329,8 @@ chain for " target " development."))
|
||||||
(make-bitcoin-cross-toolchain target)))
|
(make-bitcoin-cross-toolchain target)))
|
||||||
((string-contains target "darwin")
|
((string-contains target "darwin")
|
||||||
(list
|
(list
|
||||||
gcc-toolchain-10
|
gcc-toolchain-11
|
||||||
(list gcc-toolchain-10 "static")
|
(list gcc-toolchain-11 "static")
|
||||||
binutils
|
binutils
|
||||||
clang-toolchain-10
|
clang-toolchain-10
|
||||||
ldid))
|
ldid))
|
||||||
|
|
17
contrib/guix/patches/winpthreads-remap-guix-store.patch
Normal file
17
contrib/guix/patches/winpthreads-remap-guix-store.patch
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
Without ffile-prefix-map, the debug symbols will contain paths for the
|
||||||
|
guix store which will include the hashes of each package. However, the
|
||||||
|
hash for the same package will differ when on different architectures.
|
||||||
|
In order to be reproducible regardless of the architecture used to build
|
||||||
|
the package, map all guix store prefixes to something fixed, e.g. /usr.
|
||||||
|
|
||||||
|
--- a/mingw-w64-libraries/winpthreads/Makefile.in
|
||||||
|
+++ b/mingw-w64-libraries/winpthreads/Makefile.in
|
||||||
|
@@ -478,7 +478,7 @@ top_build_prefix = @top_build_prefix@
|
||||||
|
top_builddir = @top_builddir@
|
||||||
|
top_srcdir = @top_srcdir@
|
||||||
|
SUBDIRS = . tests
|
||||||
|
-AM_CFLAGS = -Wall -DWIN32_LEAN_AND_MEAN $(am__append_1)
|
||||||
|
+AM_CFLAGS = -Wall -DWIN32_LEAN_AND_MEAN $(am__append_1) $(shell find /gnu/store -maxdepth 1 -mindepth 1 -type d -exec echo -n " -ffile-prefix-map={}=/usr" \;)
|
||||||
|
ACLOCAL_AMFLAGS = -I m4
|
||||||
|
lib_LTLIBRARIES = libwinpthread.la
|
||||||
|
include_HEADERS = include/pthread.h include/sched.h include/semaphore.h include/pthread_unistd.h include/pthread_time.h include/pthread_compat.h include/pthread_signal.h
|
1
external/feather-docs
vendored
1
external/feather-docs
vendored
|
@ -1 +0,0 @@
|
||||||
Subproject commit 1c8e9318b29b18b08e0302c1e34e4f3581e7895c
|
|
0
external/feather-docs
vendored
Normal file
0
external/feather-docs
vendored
Normal file
2
monero
2
monero
|
@ -1 +1 @@
|
||||||
Subproject commit 6a88faa9af20c56363bac563a5c0b803ea2695dd
|
Subproject commit 55a6b0018bb61abb9985a3054837d48f4d1020d8
|
101
src/Application.cpp
Normal file
101
src/Application.cpp
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
// SPDX-FileCopyrightText: 2020-2024 The Monero Project
|
||||||
|
|
||||||
|
#include "Application.h"
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <QLocalSocket>
|
||||||
|
#include <QLockFile>
|
||||||
|
#include <QStandardPaths>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
constexpr int WaitTimeoutMSec = 150;
|
||||||
|
const char BlockSizeProperty[] = "blockSize";
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
Application::Application(int& argc, char** argv)
|
||||||
|
: QApplication(argc, argv)
|
||||||
|
, m_alreadyRunning(false)
|
||||||
|
, m_lockFile(nullptr)
|
||||||
|
{
|
||||||
|
QString userName = qgetenv("USER");
|
||||||
|
if (userName.isEmpty()) {
|
||||||
|
userName = qgetenv("USERNAME");
|
||||||
|
}
|
||||||
|
QString identifier = "feather";
|
||||||
|
if (!userName.isEmpty()) {
|
||||||
|
identifier += "-" + userName;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString lockName = identifier + ".lock";
|
||||||
|
m_socketName = identifier + ".socket";
|
||||||
|
|
||||||
|
// According to documentation we should use RuntimeLocation on *nixes, but even Qt doesn't respect
|
||||||
|
// this and creates sockets in TempLocation, so let's be consistent.
|
||||||
|
m_lockFile = new QLockFile(QStandardPaths::writableLocation(QStandardPaths::TempLocation) + "/" + lockName);
|
||||||
|
m_lockFile->setStaleLockTime(0);
|
||||||
|
m_lockFile->tryLock();
|
||||||
|
|
||||||
|
m_lockServer.setSocketOptions(QLocalServer::UserAccessOption);
|
||||||
|
connect(&m_lockServer, SIGNAL(newConnection()), this, SIGNAL(anotherInstanceStarted()));
|
||||||
|
connect(&m_lockServer, &QLocalServer::newConnection, this, &Application::processIncomingConnection);
|
||||||
|
|
||||||
|
switch (m_lockFile->error()) {
|
||||||
|
case QLockFile::NoError:
|
||||||
|
// No existing lock was found, start listener
|
||||||
|
m_lockServer.listen(m_socketName);
|
||||||
|
break;
|
||||||
|
case QLockFile::LockFailedError: {
|
||||||
|
// Attempt to connect to the existing instance
|
||||||
|
QLocalSocket client;
|
||||||
|
for (int i = 0; i < 3; ++i) {
|
||||||
|
client.connectToServer(m_socketName);
|
||||||
|
if (client.waitForConnected(WaitTimeoutMSec)) {
|
||||||
|
// Connection succeeded, this will raise the existing window if minimized
|
||||||
|
client.abort();
|
||||||
|
m_alreadyRunning = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_alreadyRunning) {
|
||||||
|
// If we get here then the original instance is likely dead
|
||||||
|
qWarning() << "Existing single-instance lock file is invalid. Launching new instance.";
|
||||||
|
|
||||||
|
// forceably reset the lock file
|
||||||
|
m_lockFile->removeStaleLockFile();
|
||||||
|
m_lockFile->tryLock();
|
||||||
|
// start the listen server
|
||||||
|
m_lockServer.listen(m_socketName);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
qWarning() << "The lock file could not be created. Single-instance mode disabled.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Application::~Application()
|
||||||
|
{
|
||||||
|
qDebug() << "~Application";
|
||||||
|
if (m_lockFile) {
|
||||||
|
m_lockFile->unlock();
|
||||||
|
delete m_lockFile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Application::isAlreadyRunning() const
|
||||||
|
{
|
||||||
|
return m_alreadyRunning;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::processIncomingConnection()
|
||||||
|
{
|
||||||
|
qDebug() << "We got an incoming connection";
|
||||||
|
if (m_lockServer.hasPendingConnections()) {
|
||||||
|
QLocalSocket* socket = m_lockServer.nextPendingConnection();
|
||||||
|
socket->setProperty(BlockSizeProperty, 0);
|
||||||
|
}
|
||||||
|
}
|
35
src/Application.h
Normal file
35
src/Application.h
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
// SPDX-FileCopyrightText: 2020-2024 The Monero Project
|
||||||
|
|
||||||
|
#ifndef FEATHER_APPLICATION_H
|
||||||
|
#define FEATHER_APPLICATION_H
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QtNetwork/qlocalserver.h>
|
||||||
|
|
||||||
|
class QLockFile;
|
||||||
|
|
||||||
|
class Application : public QApplication {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
Application(int& argc, char** argv);
|
||||||
|
~Application() override;
|
||||||
|
|
||||||
|
bool isAlreadyRunning() const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void anotherInstanceStarted();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void processIncomingConnection();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool m_alreadyRunning;
|
||||||
|
QLockFile* m_lockFile;
|
||||||
|
QLocalServer m_lockServer;
|
||||||
|
QString m_socketName;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //FEATHER_APPLICATION_H
|
|
@ -20,11 +20,6 @@ endif()
|
||||||
|
|
||||||
find_package(Qt6 REQUIRED COMPONENTS ${QT_COMPONENTS})
|
find_package(Qt6 REQUIRED COMPONENTS ${QT_COMPONENTS})
|
||||||
|
|
||||||
set(QAPPLICATION_CLASS QApplication CACHE STRING "Inheritance class for SingleApplication")
|
|
||||||
add_subdirectory(third-party/singleapplication)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (CHECK_UPDATES)
|
if (CHECK_UPDATES)
|
||||||
add_subdirectory(openpgp)
|
add_subdirectory(openpgp)
|
||||||
endif()
|
endif()
|
||||||
|
@ -227,7 +222,7 @@ if(STATIC)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
|
if (NOT CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||||
target_compile_definitions(feather PRIVATE QT_NO_DEBUG=0)
|
target_compile_definitions(feather PRIVATE QT_NO_DEBUG=1)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_compile_definitions(feather
|
target_compile_definitions(feather
|
||||||
|
@ -254,11 +249,8 @@ if (DEPENDS)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_link_libraries(feather PRIVATE
|
target_link_libraries(feather PRIVATE
|
||||||
wallet_merged
|
wallet_api
|
||||||
${LMDB_LIBRARY}
|
|
||||||
epee
|
epee
|
||||||
${UNBOUND_LIBRARY}
|
|
||||||
${SODIUM_LIBRARY}
|
|
||||||
easylogging
|
easylogging
|
||||||
ringct
|
ringct
|
||||||
${Boost_LIBRARIES}
|
${Boost_LIBRARIES}
|
||||||
|
@ -274,7 +266,6 @@ target_link_libraries(feather PRIVATE
|
||||||
Threads::Threads
|
Threads::Threads
|
||||||
${QRENCODE_LIBRARY}
|
${QRENCODE_LIBRARY}
|
||||||
${POLYSEED_LIBRARY}
|
${POLYSEED_LIBRARY}
|
||||||
SingleApplication::SingleApplication
|
|
||||||
${ICU_LIBRARIES}
|
${ICU_LIBRARIES}
|
||||||
${LIBZIP_LIBRARIES}
|
${LIBZIP_LIBRARIES}
|
||||||
${ZLIB_LIBRARIES}
|
${ZLIB_LIBRARIES}
|
||||||
|
@ -285,11 +276,11 @@ if(CHECK_UPDATES)
|
||||||
target_link_libraries(feather PRIVATE openpgp)
|
target_link_libraries(feather PRIVATE openpgp)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(DEPENDS)
|
|
||||||
target_link_libraries(feather PRIVATE ${ICONV_LIBRARIES})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(DEVICE_TREZOR_READY)
|
if(DEVICE_TREZOR_READY)
|
||||||
|
find_package(Protobuf CONFIG)
|
||||||
|
if (NOT Protobuf_FOUND)
|
||||||
|
find_package(Protobuf REQUIRED)
|
||||||
|
endif()
|
||||||
target_link_libraries(feather PRIVATE ${TREZOR_DEP_LIBS})
|
target_link_libraries(feather PRIVATE ${TREZOR_DEP_LIBS})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
|
@ -324,18 +324,12 @@ QVector<CoinsInfo*> CoinsWidget::currentEntries() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoinsWidget::freezeCoins(QStringList &pubkeys) {
|
void CoinsWidget::freezeCoins(QStringList &pubkeys) {
|
||||||
for (auto &pubkey : pubkeys) {
|
m_wallet->coins()->freeze(pubkeys);
|
||||||
m_wallet->coins()->freeze(pubkey);
|
|
||||||
}
|
|
||||||
m_wallet->coins()->refresh();
|
|
||||||
m_wallet->updateBalance();
|
m_wallet->updateBalance();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CoinsWidget::thawCoins(QStringList &pubkeys) {
|
void CoinsWidget::thawCoins(QStringList &pubkeys) {
|
||||||
for (auto &pubkey : pubkeys) {
|
m_wallet->coins()->thaw(pubkeys);
|
||||||
m_wallet->coins()->thaw(pubkey);
|
|
||||||
}
|
|
||||||
m_wallet->coins()->refresh();
|
|
||||||
m_wallet->updateBalance();
|
m_wallet->updateBalance();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,10 @@
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
|
||||||
#include "dialog/ContactsDialog.h"
|
#include "dialog/ContactsDialog.h"
|
||||||
|
#include "model/AddressBookModel.h"
|
||||||
|
#include "model/AddressBookProxyModel.h"
|
||||||
#include "libwalletqt/AddressBook.h"
|
#include "libwalletqt/AddressBook.h"
|
||||||
|
#include "libwalletqt/Wallet.h"
|
||||||
#include "libwalletqt/WalletManager.h"
|
#include "libwalletqt/WalletManager.h"
|
||||||
#include "utils/Icons.h"
|
#include "utils/Icons.h"
|
||||||
#include "utils/Utils.h"
|
#include "utils/Utils.h"
|
||||||
|
|
|
@ -8,9 +8,9 @@
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
|
|
||||||
#include "model/AddressBookModel.h"
|
class AddressBookModel;
|
||||||
#include "model/AddressBookProxyModel.h"
|
class AddressBookProxyModel;
|
||||||
#include "libwalletqt/Wallet.h"
|
class Wallet;
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class ContactsWidget;
|
class ContactsWidget;
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
|
|
||||||
#include "dialog/TxInfoDialog.h"
|
#include "dialog/TxInfoDialog.h"
|
||||||
#include "dialog/TxProofDialog.h"
|
#include "dialog/TxProofDialog.h"
|
||||||
|
#include "model/TransactionHistoryProxyModel.h"
|
||||||
|
#include "libwalletqt/Wallet.h"
|
||||||
#include "libwalletqt/WalletManager.h"
|
#include "libwalletqt/WalletManager.h"
|
||||||
#include "utils/config.h"
|
#include "utils/config.h"
|
||||||
#include "utils/Icons.h"
|
#include "utils/Icons.h"
|
||||||
|
|
|
@ -7,10 +7,8 @@
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
|
|
||||||
#include "libwalletqt/Coins.h"
|
class TransactionHistoryProxyModel;
|
||||||
#include "libwalletqt/Wallet.h"
|
class Wallet;
|
||||||
#include "model/TransactionHistoryModel.h"
|
|
||||||
#include "model/TransactionHistoryProxyModel.h"
|
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class HistoryWidget;
|
class HistoryWidget;
|
||||||
|
|
|
@ -26,12 +26,13 @@
|
||||||
#include "libwalletqt/AddressBook.h"
|
#include "libwalletqt/AddressBook.h"
|
||||||
#include "libwalletqt/rows/CoinsInfo.h"
|
#include "libwalletqt/rows/CoinsInfo.h"
|
||||||
#include "libwalletqt/Transfer.h"
|
#include "libwalletqt/Transfer.h"
|
||||||
|
#include "libwalletqt/TransactionHistory.h"
|
||||||
|
#include "model/AddressBookModel.h"
|
||||||
#include "plugins/PluginRegistry.h"
|
#include "plugins/PluginRegistry.h"
|
||||||
#include "utils/AppData.h"
|
#include "utils/AppData.h"
|
||||||
#include "utils/AsyncTask.h"
|
#include "utils/AsyncTask.h"
|
||||||
#include "utils/ColorScheme.h"
|
#include "utils/ColorScheme.h"
|
||||||
#include "utils/Icons.h"
|
#include "utils/Icons.h"
|
||||||
#include "utils/SemanticVersion.h"
|
|
||||||
#include "utils/TorManager.h"
|
#include "utils/TorManager.h"
|
||||||
#include "utils/WebsocketNotifier.h"
|
#include "utils/WebsocketNotifier.h"
|
||||||
|
|
||||||
|
@ -116,6 +117,9 @@ MainWindow::MainWindow(WindowManager *windowManager, Wallet *wallet, QWidget *pa
|
||||||
|
|
||||||
this->onWalletOpened();
|
this->onWalletOpened();
|
||||||
|
|
||||||
|
connect(&appData()->prices, &Prices::fiatPricesUpdated, this, &MainWindow::updateBalance);
|
||||||
|
connect(&appData()->prices, &Prices::cryptoPricesUpdated, this, &MainWindow::updateBalance);
|
||||||
|
|
||||||
#ifdef DONATE_BEG
|
#ifdef DONATE_BEG
|
||||||
this->donationNag();
|
this->donationNag();
|
||||||
#endif
|
#endif
|
||||||
|
@ -312,6 +316,7 @@ void MainWindow::initMenu() {
|
||||||
|
|
||||||
// [Wallet] -> [History]
|
// [Wallet] -> [History]
|
||||||
connect(ui->actionExport_CSV, &QAction::triggered, this, &MainWindow::onExportHistoryCSV);
|
connect(ui->actionExport_CSV, &QAction::triggered, this, &MainWindow::onExportHistoryCSV);
|
||||||
|
connect(ui->actionImportHistoryCSV, &QAction::triggered, this, &MainWindow::onImportHistoryDescriptionsCSV);
|
||||||
|
|
||||||
// [Wallet] -> [Contacts]
|
// [Wallet] -> [Contacts]
|
||||||
connect(ui->actionExportContactsCSV, &QAction::triggered, this, &MainWindow::onExportContactsCSV);
|
connect(ui->actionExportContactsCSV, &QAction::triggered, this, &MainWindow::onExportContactsCSV);
|
||||||
|
@ -324,7 +329,7 @@ void MainWindow::initMenu() {
|
||||||
|
|
||||||
// Show/Hide Coins
|
// Show/Hide Coins
|
||||||
connect(ui->actionShow_Coins, &QAction::triggered, m_tabShowHideSignalMapper, QOverload<>::of(&QSignalMapper::map));
|
connect(ui->actionShow_Coins, &QAction::triggered, m_tabShowHideSignalMapper, QOverload<>::of(&QSignalMapper::map));
|
||||||
m_tabShowHideMapper["Coins"] = new ToggleTab(ui->tabCoins, "Coins", "Coins", ui->actionShow_Coins);
|
m_tabShowHideMapper["Coins"] = new ToggleTab(ui->tabCoins, "Coins", "Coins", ui->actionShow_Coins, this);
|
||||||
m_tabShowHideSignalMapper->setMapping(ui->actionShow_Coins, "Coins");
|
m_tabShowHideSignalMapper->setMapping(ui->actionShow_Coins, "Coins");
|
||||||
|
|
||||||
// Show/Hide Plugins..
|
// Show/Hide Plugins..
|
||||||
|
@ -336,7 +341,7 @@ void MainWindow::initMenu() {
|
||||||
auto* pluginAction = new QAction(QString("Show %1").arg(plugin->displayName()), this);
|
auto* pluginAction = new QAction(QString("Show %1").arg(plugin->displayName()), this);
|
||||||
ui->menuView->insertAction(plugin->insertFirst() ? ui->actionPlaceholderBegin : ui->actionPlaceholderEnd, pluginAction);
|
ui->menuView->insertAction(plugin->insertFirst() ? ui->actionPlaceholderBegin : ui->actionPlaceholderEnd, pluginAction);
|
||||||
connect(pluginAction, &QAction::triggered, m_tabShowHideSignalMapper, QOverload<>::of(&QSignalMapper::map));
|
connect(pluginAction, &QAction::triggered, m_tabShowHideSignalMapper, QOverload<>::of(&QSignalMapper::map));
|
||||||
m_tabShowHideMapper[plugin->displayName()] = new ToggleTab(plugin->tab(), plugin->displayName(), plugin->displayName(), pluginAction);
|
m_tabShowHideMapper[plugin->displayName()] = new ToggleTab(plugin->tab(), plugin->displayName(), plugin->displayName(), pluginAction, this);
|
||||||
m_tabShowHideSignalMapper->setMapping(pluginAction, plugin->displayName());
|
m_tabShowHideSignalMapper->setMapping(pluginAction, plugin->displayName());
|
||||||
}
|
}
|
||||||
ui->actionPlaceholderBegin->setVisible(false);
|
ui->actionPlaceholderBegin->setVisible(false);
|
||||||
|
@ -482,6 +487,12 @@ void MainWindow::initWalletContext() {
|
||||||
m_windowManager->notify("Payment received", notify, 5000);
|
m_windowManager->notify("Payment received", notify, 5000);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
connect(m_wallet, &Wallet::moneyReceived, this, [this](const QString &txId, uint64_t amount, bool coinbase){
|
||||||
|
if (m_wallet->isSynchronized() && !m_locked && coinbase) {
|
||||||
|
auto notify = QString("%1 XMR").arg(WalletManager::displayAmount(amount, false));
|
||||||
|
m_windowManager->notify("Mining payment received", notify, 5000);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Device
|
// Device
|
||||||
connect(m_wallet, &Wallet::deviceButtonRequest, this, &MainWindow::onDeviceButtonRequest);
|
connect(m_wallet, &Wallet::deviceButtonRequest, this, &MainWindow::onDeviceButtonRequest);
|
||||||
|
@ -566,7 +577,7 @@ void MainWindow::onWalletOpened() {
|
||||||
m_wallet->history()->refresh();
|
m_wallet->history()->refresh();
|
||||||
});
|
});
|
||||||
// Vice versa
|
// Vice versa
|
||||||
connect(m_wallet->history(), &TransactionHistory::txNoteChanged, [this] {
|
connect(m_wallet->transactionHistoryModel(), &TransactionHistoryModel::transactionDescriptionChanged, [this] {
|
||||||
m_wallet->coins()->refresh();
|
m_wallet->coins()->refresh();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -581,6 +592,10 @@ void MainWindow::onWalletOpened() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::updateBalance() {
|
||||||
|
this->onBalanceUpdated(m_wallet->balance(), m_wallet->unlockedBalance());
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::onBalanceUpdated(quint64 balance, quint64 spendable) {
|
void MainWindow::onBalanceUpdated(quint64 balance, quint64 spendable) {
|
||||||
bool hide = conf()->get(Config::hideBalance).toBool();
|
bool hide = conf()->get(Config::hideBalance).toBool();
|
||||||
int displaySetting = conf()->get(Config::balanceDisplay).toInt();
|
int displaySetting = conf()->get(Config::balanceDisplay).toInt();
|
||||||
|
@ -601,6 +616,12 @@ void MainWindow::onBalanceUpdated(quint64 balance, quint64 spendable) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (conf()->get(Config::balanceShowFiat).toBool() && !hide) {
|
||||||
|
QString fiatCurrency = conf()->get(Config::preferredFiatCurrency).toString();
|
||||||
|
double balanceFiatAmount = appData()->prices.convert("XMR", fiatCurrency, balance / constants::cdiv);
|
||||||
|
balance_str += QString(" (%1)").arg(Utils::amountToCurrencyString(balanceFiatAmount, fiatCurrency));
|
||||||
|
}
|
||||||
|
|
||||||
m_statusLabelBalance->setToolTip("Click for details");
|
m_statusLabelBalance->setToolTip("Click for details");
|
||||||
m_statusLabelBalance->setText(balance_str);
|
m_statusLabelBalance->setText(balance_str);
|
||||||
}
|
}
|
||||||
|
@ -911,7 +932,7 @@ void MainWindow::onTransactionCreated(PendingTransaction *tx, const QVector<QStr
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (tx->txCount() > 1) {
|
else if (tx->txCount() > 1) {
|
||||||
Utils::showError(this, "Failed to construct transaction", "Split transactions are not supported", {"Try sending a smaller amount."});
|
Utils::showError(this, "Failed to construct transaction", "Transaction tries to spend too many inputs", {"Send a smaller amount of XMR to yourself first."});
|
||||||
m_wallet->disposeTransaction(tx);
|
m_wallet->disposeTransaction(tx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1208,6 +1229,7 @@ void MainWindow::closeEvent(QCloseEvent *event) {
|
||||||
qDebug() << Q_FUNC_INFO;
|
qDebug() << Q_FUNC_INFO;
|
||||||
|
|
||||||
if (!this->cleanedUp) {
|
if (!this->cleanedUp) {
|
||||||
|
qDebug() << "MainWindow: cleaning up";
|
||||||
this->cleanedUp = true;
|
this->cleanedUp = true;
|
||||||
|
|
||||||
emit aboutToQuit();
|
emit aboutToQuit();
|
||||||
|
@ -1693,6 +1715,21 @@ void MainWindow::onExportHistoryCSV() {
|
||||||
Utils::showInfo(this, "CSV export", QString("Transaction history exported to %1").arg(fn));
|
Utils::showInfo(this, "CSV export", QString("Transaction history exported to %1").arg(fn));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::onImportHistoryDescriptionsCSV() {
|
||||||
|
const QString fileName = QFileDialog::getOpenFileName(this, "Import CSV file", QDir::homePath(), "CSV Files (*.csv)");
|
||||||
|
if (fileName.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString error = m_wallet->history()->importLabelsFromCSV(fileName);
|
||||||
|
if (!error.isEmpty()) {
|
||||||
|
Utils::showError(this, "Unable to import transaction descriptions from CSV", error);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Utils::showInfo(this, "Successfully imported transaction descriptions from CSV");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::onExportContactsCSV() {
|
void MainWindow::onExportContactsCSV() {
|
||||||
auto *model = m_wallet->addressBookModel();
|
auto *model = m_wallet->addressBookModel();
|
||||||
if (model->rowCount() <= 0){
|
if (model->rowCount() <= 0){
|
||||||
|
@ -1762,8 +1799,8 @@ void MainWindow::donationNag() {
|
||||||
|
|
||||||
donationCounter++;
|
donationCounter++;
|
||||||
if (donationCounter % constants::donationBoundary == 0) {
|
if (donationCounter % constants::donationBoundary == 0) {
|
||||||
auto msg = "Feather is a 100% community-sponsored endeavor. Please consider supporting "
|
auto msg = "Feather development is funded entirely through donations.\n\nPlease consider supporting "
|
||||||
"the project financially. Get rid of this message by donating any amount.";
|
"the project. Donate any amount to remove this reminder.";
|
||||||
int ret = QMessageBox::information(this, "Donate to Feather", msg, QMessageBox::Yes, QMessageBox::No);
|
int ret = QMessageBox::information(this, "Donate to Feather", msg, QMessageBox::Yes, QMessageBox::No);
|
||||||
if (ret == QMessageBox::Yes) {
|
if (ret == QMessageBox::Yes) {
|
||||||
this->donateButtonClicked();
|
this->donateButtonClicked();
|
||||||
|
@ -1935,5 +1972,5 @@ int MainWindow::findTab(const QString &title) {
|
||||||
}
|
}
|
||||||
|
|
||||||
MainWindow::~MainWindow() {
|
MainWindow::~MainWindow() {
|
||||||
qDebug() << "~MainWindow";
|
qDebug() << "~MainWindow" << QThread::currentThreadId();
|
||||||
}
|
}
|
|
@ -51,9 +51,12 @@ namespace Ui {
|
||||||
class MainWindow;
|
class MainWindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ToggleTab {
|
class ToggleTab : QObject {
|
||||||
ToggleTab(QWidget *tab, QString name, QString description, QAction *menuAction) :
|
Q_OBJECT
|
||||||
tab(tab), key(std::move(name)), name(std::move(description)), menuAction(menuAction) {}
|
|
||||||
|
public:
|
||||||
|
ToggleTab(QWidget *tab, QString name, QString description, QAction *menuAction, QObject *parent = nullptr) :
|
||||||
|
QObject(parent), tab(tab), key(std::move(name)), name(std::move(description)), menuAction(menuAction) {}
|
||||||
QWidget *tab;
|
QWidget *tab;
|
||||||
QString key;
|
QString key;
|
||||||
QString name;
|
QString name;
|
||||||
|
@ -110,6 +113,7 @@ private slots:
|
||||||
void menuToggleTabVisible(const QString &key);
|
void menuToggleTabVisible(const QString &key);
|
||||||
void menuClearHistoryClicked();
|
void menuClearHistoryClicked();
|
||||||
void onExportHistoryCSV();
|
void onExportHistoryCSV();
|
||||||
|
void onImportHistoryDescriptionsCSV();
|
||||||
void onExportContactsCSV();
|
void onExportContactsCSV();
|
||||||
void onCreateDesktopEntry();
|
void onCreateDesktopEntry();
|
||||||
void onShowDocumentation();
|
void onShowDocumentation();
|
||||||
|
@ -128,6 +132,7 @@ private slots:
|
||||||
void onTxPoolBacklog(const QVector<quint64> &backlog, quint64 originalFeeLevel, quint64 automaticFeeLevel);
|
void onTxPoolBacklog(const QVector<quint64> &backlog, quint64 originalFeeLevel, quint64 automaticFeeLevel);
|
||||||
|
|
||||||
// libwalletqt
|
// libwalletqt
|
||||||
|
void updateBalance();
|
||||||
void onBalanceUpdated(quint64 balance, quint64 spendable);
|
void onBalanceUpdated(quint64 balance, quint64 spendable);
|
||||||
void onSyncStatus(quint64 height, quint64 target, bool daemonSync);
|
void onSyncStatus(quint64 height, quint64 target, bool daemonSync);
|
||||||
void onWalletOpened();
|
void onWalletOpened();
|
||||||
|
|
|
@ -499,6 +499,7 @@
|
||||||
<string>History</string>
|
<string>History</string>
|
||||||
</property>
|
</property>
|
||||||
<addaction name="actionExport_CSV"/>
|
<addaction name="actionExport_CSV"/>
|
||||||
|
<addaction name="actionImportHistoryCSV"/>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QMenu" name="menuContacts">
|
<widget class="QMenu" name="menuContacts">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
|
@ -939,6 +940,11 @@
|
||||||
<string>Tx pool viewer</string>
|
<string>Tx pool viewer</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="actionImportHistoryCSV">
|
||||||
|
<property name="text">
|
||||||
|
<string>Import descriptions from CSV</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<layoutdefault spacing="6" margin="11"/>
|
<layoutdefault spacing="6" margin="11"/>
|
||||||
<customwidgets>
|
<customwidgets>
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
#include "ui_ReceiveWidget.h"
|
#include "ui_ReceiveWidget.h"
|
||||||
|
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
#include <QMessageBox>
|
|
||||||
|
|
||||||
#include "dialog/PaymentRequestDialog.h"
|
#include "dialog/PaymentRequestDialog.h"
|
||||||
#include "dialog/QrCodeDialog.h"
|
#include "dialog/QrCodeDialog.h"
|
||||||
|
@ -71,7 +70,7 @@ ReceiveWidget::ReceiveWidget(Wallet *wallet, QWidget *parent)
|
||||||
|
|
||||||
// context menu
|
// context menu
|
||||||
ui->addresses->setContextMenuPolicy(Qt::CustomContextMenu);
|
ui->addresses->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||||
m_showTransactionsAction = new QAction("Show transactions");
|
m_showTransactionsAction = new QAction("Show transactions", this);
|
||||||
connect(m_showTransactionsAction, &QAction::triggered, this, &ReceiveWidget::onShowTransactions);
|
connect(m_showTransactionsAction, &QAction::triggered, this, &ReceiveWidget::onShowTransactions);
|
||||||
connect(ui->addresses, &QTreeView::customContextMenuRequested, this, &ReceiveWidget::showContextMenu);
|
connect(ui->addresses, &QTreeView::customContextMenuRequested, this, &ReceiveWidget::showContextMenu);
|
||||||
connect(ui->addresses, &SubaddressView::copyAddress, this, &ReceiveWidget::copyAddress);
|
connect(ui->addresses, &SubaddressView::copyAddress, this, &ReceiveWidget::copyAddress);
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
|
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
#include <QSvgWidget>
|
|
||||||
|
|
||||||
#include "libwalletqt/Subaddress.h"
|
#include "libwalletqt/Subaddress.h"
|
||||||
#include "libwalletqt/Wallet.h"
|
#include "libwalletqt/Wallet.h"
|
||||||
|
|
|
@ -4,13 +4,12 @@
|
||||||
#include "SendWidget.h"
|
#include "SendWidget.h"
|
||||||
#include "ui_SendWidget.h"
|
#include "ui_SendWidget.h"
|
||||||
|
|
||||||
#include <QMessageBox>
|
|
||||||
|
|
||||||
#include "ColorScheme.h"
|
#include "ColorScheme.h"
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
#include "utils/AppData.h"
|
#include "utils/AppData.h"
|
||||||
#include "utils/config.h"
|
#include "utils/config.h"
|
||||||
#include "Icons.h"
|
#include "Icons.h"
|
||||||
|
#include "libwalletqt/Wallet.h"
|
||||||
#include "libwalletqt/WalletManager.h"
|
#include "libwalletqt/WalletManager.h"
|
||||||
|
|
||||||
#if defined(WITH_SCANNER)
|
#if defined(WITH_SCANNER)
|
||||||
|
@ -29,8 +28,7 @@ SendWidget::SendWidget(Wallet *wallet, QWidget *parent)
|
||||||
QString amount_rx = R"(^\d{0,8}[\.,]\d{0,12}|(all)$)";
|
QString amount_rx = R"(^\d{0,8}[\.,]\d{0,12}|(all)$)";
|
||||||
QRegularExpression rx;
|
QRegularExpression rx;
|
||||||
rx.setPattern(amount_rx);
|
rx.setPattern(amount_rx);
|
||||||
QValidator *validator = new QRegularExpressionValidator(rx, this);
|
ui->lineAmount->setValidator(new QRegularExpressionValidator(rx, this));
|
||||||
ui->lineAmount->setValidator(validator);
|
|
||||||
|
|
||||||
connect(m_wallet, &Wallet::initiateTransaction, this, &SendWidget::disableSendButton);
|
connect(m_wallet, &Wallet::initiateTransaction, this, &SendWidget::disableSendButton);
|
||||||
connect(m_wallet, &Wallet::transactionCreated, this, &SendWidget::enableSendButton);
|
connect(m_wallet, &Wallet::transactionCreated, this, &SendWidget::enableSendButton);
|
||||||
|
@ -47,7 +45,7 @@ SendWidget::SendWidget(Wallet *wallet, QWidget *parent)
|
||||||
connect(ui->lineAmount, &QLineEdit::textChanged, this, &SendWidget::amountEdited);
|
connect(ui->lineAmount, &QLineEdit::textChanged, this, &SendWidget::amountEdited);
|
||||||
connect(ui->lineAddress, &QPlainTextEdit::textChanged, this, &SendWidget::addressEdited);
|
connect(ui->lineAddress, &QPlainTextEdit::textChanged, this, &SendWidget::addressEdited);
|
||||||
connect(ui->btn_openAlias, &QPushButton::clicked, this, &SendWidget::aliasClicked);
|
connect(ui->btn_openAlias, &QPushButton::clicked, this, &SendWidget::aliasClicked);
|
||||||
connect(ui->lineAddress, &PayToEdit::dataPasted, this, &SendWidget::onDataPasted);
|
connect(ui->lineAddress, &PayToEdit::dataPasted, this, &SendWidget::onDataFromQR);
|
||||||
ui->label_conversionAmount->setText("");
|
ui->label_conversionAmount->setText("");
|
||||||
ui->label_conversionAmount->hide();
|
ui->label_conversionAmount->hide();
|
||||||
ui->btn_openAlias->hide();
|
ui->btn_openAlias->hide();
|
||||||
|
@ -142,7 +140,7 @@ void SendWidget::scanClicked() {
|
||||||
|
|
||||||
auto dialog = new QrCodeScanDialog(this, false);
|
auto dialog = new QrCodeScanDialog(this, false);
|
||||||
dialog->exec();
|
dialog->exec();
|
||||||
ui->lineAddress->setText(dialog->decodedString());
|
this->onDataFromQR(dialog->decodedString());
|
||||||
dialog->deleteLater();
|
dialog->deleteLater();
|
||||||
#else
|
#else
|
||||||
Utils::showError(this, "Can't open QR scanner", "Feather was built without webcam QR scanner support");
|
Utils::showError(this, "Can't open QR scanner", "Feather was built without webcam QR scanner support");
|
||||||
|
@ -404,13 +402,17 @@ void SendWidget::setSubtractFeeFromAmountEnabled(bool enabled) {
|
||||||
ui->check_subtractFeeFromAmount->setVisible(enabled);
|
ui->check_subtractFeeFromAmount->setVisible(enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SendWidget::onDataPasted(const QString &data) {
|
void SendWidget::onDataFromQR(const QString &data) {
|
||||||
if (!data.isEmpty()) {
|
if (!data.isEmpty()) {
|
||||||
QVariantMap uriData = m_wallet->parse_uri_to_object(data);
|
QVariantMap uriData = m_wallet->parse_uri_to_object(data);
|
||||||
if (!uriData.contains("error")) {
|
if (!uriData.contains("error")) {
|
||||||
ui->lineAddress->setText(uriData.value("address").toString());
|
ui->lineAddress->setText(uriData.value("address").toString());
|
||||||
ui->lineDescription->setText(uriData.value("tx_description").toString());
|
ui->lineDescription->setText(uriData.value("tx_description").toString());
|
||||||
ui->lineAmount->setText(uriData.value("amount").toString());
|
|
||||||
|
// Strip trailing zeroes
|
||||||
|
auto amountStr = uriData.value("amount").toString();
|
||||||
|
auto amount = WalletManager::amountFromString(amountStr);
|
||||||
|
ui->lineAmount->setText(WalletManager::displayAmount(amount, false));
|
||||||
} else {
|
} else {
|
||||||
ui->lineAddress->setText(data);
|
ui->lineAddress->setText(data);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
#include "libwalletqt/Wallet.h"
|
class Wallet;
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class SendWidget;
|
class SendWidget;
|
||||||
|
@ -49,7 +49,7 @@ public slots:
|
||||||
void disallowSending();
|
void disallowSending();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void onDataPasted(const QString &data);
|
void onDataFromQR(const QString &data);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setupComboBox();
|
void setupComboBox();
|
||||||
|
|
|
@ -12,10 +12,9 @@
|
||||||
#include "libwalletqt/WalletManager.h"
|
#include "libwalletqt/WalletManager.h"
|
||||||
#include "utils/AppData.h"
|
#include "utils/AppData.h"
|
||||||
#include "utils/Icons.h"
|
#include "utils/Icons.h"
|
||||||
|
#include "utils/nodes.h"
|
||||||
#include "utils/WebsocketNotifier.h"
|
#include "utils/WebsocketNotifier.h"
|
||||||
#include "widgets/NetworkProxyWidget.h"
|
#include "widgets/NetworkProxyWidget.h"
|
||||||
#include "WindowManager.h"
|
|
||||||
#include "plugins/PluginRegistry.h"
|
|
||||||
#include "utils/ColorScheme.h"
|
#include "utils/ColorScheme.h"
|
||||||
|
|
||||||
Settings::Settings(Nodes *nodes, QWidget *parent)
|
Settings::Settings(Nodes *nodes, QWidget *parent)
|
||||||
|
@ -132,10 +131,18 @@ void Settings::setupAppearanceTab() {
|
||||||
emit updateBalance();
|
emit updateBalance();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// [Balance show fiat]
|
||||||
|
ui->checkBox_balanceShowFiat->setChecked(conf()->get(Config::balanceShowFiat).toBool());
|
||||||
|
connect(ui->checkBox_balanceShowFiat, &QCheckBox::toggled, [this](bool toggled){
|
||||||
|
conf()->set(Config::balanceShowFiat, toggled);
|
||||||
|
emit updateBalance();
|
||||||
|
});
|
||||||
|
|
||||||
// [Preferred fiat currency]
|
// [Preferred fiat currency]
|
||||||
QStringList availableFiatCurrencies = appData()->prices.rates.keys();
|
QStringList availableFiatCurrencies = appData()->prices.rates.keys();
|
||||||
for (const auto ¤cy : availableFiatCurrencies) {
|
for (const auto ¤cy : availableFiatCurrencies) {
|
||||||
ui->comboBox_fiatCurrency->addItem(currency);
|
ui->comboBox_fiatCurrency->addItem(currency);
|
||||||
|
emit updateBalance();
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList fiatCurrencies;
|
QStringList fiatCurrencies;
|
||||||
|
@ -152,6 +159,7 @@ void Settings::setupAppearanceTab() {
|
||||||
QString selection = ui->comboBox_fiatCurrency->itemText(index);
|
QString selection = ui->comboBox_fiatCurrency->itemText(index);
|
||||||
conf()->set(Config::preferredFiatCurrency, selection);
|
conf()->set(Config::preferredFiatCurrency, selection);
|
||||||
emit preferredFiatCurrencyChanged(selection);
|
emit preferredFiatCurrencyChanged(selection);
|
||||||
|
emit updateBalance();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,17 +4,13 @@
|
||||||
#ifndef FEATHER_SettingsDIALOG_H
|
#ifndef FEATHER_SettingsDIALOG_H
|
||||||
#define FEATHER_SettingsDIALOG_H
|
#define FEATHER_SettingsDIALOG_H
|
||||||
|
|
||||||
|
|
||||||
#include <QAbstractButton>
|
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
#include <QSettings>
|
|
||||||
|
|
||||||
#include "widgets/NodeWidget.h"
|
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class Settings;
|
class Settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Nodes;
|
||||||
class Settings : public QDialog
|
class Settings : public QDialog
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
|
@ -129,17 +129,17 @@
|
||||||
</item>
|
</item>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="0">
|
<item row="6" column="0">
|
||||||
<widget class="QLabel" name="label_17">
|
<widget class="QLabel" name="label_17">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Fiat currency:</string>
|
<string>Fiat currency:</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="1">
|
<item row="6" column="1">
|
||||||
<widget class="QComboBox" name="comboBox_fiatCurrency"/>
|
<widget class="QComboBox" name="comboBox_fiatCurrency"/>
|
||||||
</item>
|
</item>
|
||||||
<item row="6" column="0">
|
<item row="7" column="0">
|
||||||
<spacer name="verticalSpacer_3">
|
<spacer name="verticalSpacer_3">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Vertical</enum>
|
<enum>Qt::Vertical</enum>
|
||||||
|
@ -152,6 +152,13 @@
|
||||||
</property>
|
</property>
|
||||||
</spacer>
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="5" column="1">
|
||||||
|
<widget class="QCheckBox" name="checkBox_balanceShowFiat">
|
||||||
|
<property name="text">
|
||||||
|
<string>Show fiat balance in statusbar</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
|
|
@ -3,21 +3,27 @@
|
||||||
|
|
||||||
#include "WindowManager.h"
|
#include "WindowManager.h"
|
||||||
|
|
||||||
#include <QApplication>
|
|
||||||
#include <QDialogButtonBox>
|
#include <QDialogButtonBox>
|
||||||
#include <QInputDialog>
|
#include <QInputDialog>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QWindow>
|
#include <QWindow>
|
||||||
|
|
||||||
|
#include "Application.h"
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
|
#include "MainWindow.h"
|
||||||
|
#include "dialog/DocsDialog.h"
|
||||||
#include "dialog/PasswordDialog.h"
|
#include "dialog/PasswordDialog.h"
|
||||||
#include "dialog/SplashDialog.h"
|
#include "dialog/SplashDialog.h"
|
||||||
|
#include "dialog/TorInfoDialog.h"
|
||||||
|
#include "libwalletqt/WalletManager.h"
|
||||||
|
#include "libwalletqt/Wallet.h"
|
||||||
#include "utils/Icons.h"
|
#include "utils/Icons.h"
|
||||||
#include "utils/NetworkManager.h"
|
#include "utils/NetworkManager.h"
|
||||||
#include "utils/os/tails.h"
|
#include "utils/os/tails.h"
|
||||||
#include "utils/os/whonix.h"
|
#include "utils/os/whonix.h"
|
||||||
#include "utils/TorManager.h"
|
#include "utils/TorManager.h"
|
||||||
#include "utils/WebsocketNotifier.h"
|
#include "utils/WebsocketNotifier.h"
|
||||||
|
#include "utils/AppData.h"
|
||||||
|
|
||||||
WindowManager::WindowManager(QObject *parent)
|
WindowManager::WindowManager(QObject *parent)
|
||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
|
@ -33,6 +39,7 @@ WindowManager::WindowManager(QObject *parent)
|
||||||
connect(m_walletManager, &WalletManager::deviceError, this, &WindowManager::onDeviceError);
|
connect(m_walletManager, &WalletManager::deviceError, this, &WindowManager::onDeviceError);
|
||||||
connect(m_walletManager, &WalletManager::walletPassphraseNeeded, this, &WindowManager::onWalletPassphraseNeeded);
|
connect(m_walletManager, &WalletManager::walletPassphraseNeeded, this, &WindowManager::onWalletPassphraseNeeded);
|
||||||
|
|
||||||
|
connect(qApp, SIGNAL(anotherInstanceStarted()), this, SLOT(raise()));
|
||||||
connect(qApp, &QGuiApplication::lastWindowClosed, this, &WindowManager::quitAfterLastWindow);
|
connect(qApp, &QGuiApplication::lastWindowClosed, this, &WindowManager::quitAfterLastWindow);
|
||||||
|
|
||||||
m_tray = new QSystemTrayIcon(icons()->icon("appicons/64x64.png"));
|
m_tray = new QSystemTrayIcon(icons()->icon("appicons/64x64.png"));
|
||||||
|
@ -66,6 +73,7 @@ WindowManager::~WindowManager() {
|
||||||
qDebug() << "~WindowManager";
|
qDebug() << "~WindowManager";
|
||||||
m_cleanupThread->quit();
|
m_cleanupThread->quit();
|
||||||
m_cleanupThread->wait();
|
m_cleanupThread->wait();
|
||||||
|
qDebug() << "WindowManager: cleanup thread done" << QThread::currentThreadId();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ######################## APPLICATION LIFECYCLE ########################
|
// ######################## APPLICATION LIFECYCLE ########################
|
||||||
|
@ -80,7 +88,7 @@ void WindowManager::quitAfterLastWindow() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowManager::close() {
|
void WindowManager::close() {
|
||||||
qDebug() << Q_FUNC_INFO;
|
qDebug() << Q_FUNC_INFO << QThread::currentThreadId();
|
||||||
for (const auto &window: m_windows) {
|
for (const auto &window: m_windows) {
|
||||||
window->close();
|
window->close();
|
||||||
}
|
}
|
||||||
|
@ -100,11 +108,14 @@ void WindowManager::close() {
|
||||||
|
|
||||||
torManager()->stop();
|
torManager()->stop();
|
||||||
|
|
||||||
|
deleteLater();
|
||||||
|
|
||||||
|
qDebug() << "Calling QApplication::quit()";
|
||||||
QApplication::quit();
|
QApplication::quit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowManager::closeWindow(MainWindow *window) {
|
void WindowManager::closeWindow(MainWindow *window) {
|
||||||
qDebug() << "closing Window";
|
qDebug() << "WindowManager: closing Window";
|
||||||
m_windows.removeOne(window);
|
m_windows.removeOne(window);
|
||||||
|
|
||||||
// Move Wallet to a different thread for cleanup, so it doesn't block GUI thread
|
// Move Wallet to a different thread for cleanup, so it doesn't block GUI thread
|
||||||
|
@ -273,17 +284,29 @@ void WindowManager::onWalletOpened(Wallet *wallet) {
|
||||||
bool showIncorrectPassword = m_openWalletTriedOnce;
|
bool showIncorrectPassword = m_openWalletTriedOnce;
|
||||||
m_openWalletTriedOnce = true;
|
m_openWalletTriedOnce = true;
|
||||||
this->onWalletOpenPasswordRequired(showIncorrectPassword, wallet->keysPath());
|
this->onWalletOpenPasswordRequired(showIncorrectPassword, wallet->keysPath());
|
||||||
|
return; // Do not remove this
|
||||||
}
|
}
|
||||||
else if (errMsg == QString("basic_string::_M_replace_aux") || errMsg == QString("std::bad_alloc") || errMsg == "invalid signature") {
|
else if (errMsg == QString("basic_string::_M_replace_aux") || errMsg == QString("std::bad_alloc") || errMsg == "invalid signature") {
|
||||||
qCritical() << errMsg;
|
qCritical() << errMsg;
|
||||||
WalletManager::clearWalletCache(wallet->cachePath());
|
WalletManager::clearWalletCache(wallet->cachePath());
|
||||||
errMsg = QString("%1\n\nWallet cache is unusable, moving it.").arg(errMsg);
|
errMsg = QString("%1\n\nWallet cache is unusable, moving it.").arg(errMsg);
|
||||||
this->handleWalletError({nullptr, Utils::ERROR, "Unable to open wallet", errMsg, {"Try opening this wallet again.", "If this keeps happening, please file a bug report."}, "report_an_issue"});
|
this->handleWalletError({nullptr, Utils::ERROR, "Unable to open wallet", errMsg, {"Try opening this wallet again.", "If this keeps happening, please file a bug report."}, "report_an_issue"});
|
||||||
} else {
|
}
|
||||||
|
else if (errMsg.startsWith("failed to read file")) {
|
||||||
|
#if defined(Q_OS_MACOS)
|
||||||
|
Utils::Message message{nullptr, Utils::ERROR, "Unable to open wallet", errMsg, {"You may need to give Feather permission to access the folder", "In the System Settings app, go to 'Privacy & Security' -> 'Files & Folders'"}};
|
||||||
|
#else
|
||||||
|
Utils::Message message{nullptr, Utils::ERROR, "Unable to open wallet", errMsg, {"You may need to change the permissions on the wallet directory."}};
|
||||||
|
#endif
|
||||||
|
this->handleWalletError(message);
|
||||||
|
}
|
||||||
|
else {
|
||||||
Utils::Message message{nullptr, Utils::ERROR, "Unable to open wallet"};
|
Utils::Message message{nullptr, Utils::ERROR, "Unable to open wallet"};
|
||||||
this->handleDeviceError(errMsg, message);
|
this->handleDeviceError(errMsg, message);
|
||||||
this->handleWalletError(message);
|
this->handleWalletError(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_openingWallet = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,17 +5,20 @@
|
||||||
#define FEATHER_WINDOWMANAGER_H
|
#define FEATHER_WINDOWMANAGER_H
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <QSystemTrayIcon>
|
||||||
|
|
||||||
#include "dialog/DocsDialog.h"
|
#include "utils/EventFilter.h"
|
||||||
#include "dialog/TorInfoDialog.h"
|
|
||||||
#include "libwalletqt/WalletManager.h"
|
|
||||||
#include "libwalletqt/Wallet.h"
|
|
||||||
#include "MainWindow.h"
|
|
||||||
#include "utils/nodes.h"
|
#include "utils/nodes.h"
|
||||||
#include "wizard/WalletWizard.h"
|
#include "wizard/WalletWizard.h"
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
|
|
||||||
class MainWindow;
|
class MainWindow;
|
||||||
|
class DocsDialog;
|
||||||
|
class TorInfoDialog;
|
||||||
|
class WalletManager;
|
||||||
|
class Wallet;
|
||||||
|
class SplashDialog;
|
||||||
|
|
||||||
class WindowManager : public QObject {
|
class WindowManager : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
@ -30,7 +33,6 @@ public:
|
||||||
void closeWindow(MainWindow *window);
|
void closeWindow(MainWindow *window);
|
||||||
void showWizard(WalletWizard::Page startPage);
|
void showWizard(WalletWizard::Page startPage);
|
||||||
void restartApplication(const QString &binaryFilename);
|
void restartApplication(const QString &binaryFilename);
|
||||||
void raise();
|
|
||||||
|
|
||||||
void showSettings(Nodes *nodes, QWidget *parent, bool showProxyTab = false);
|
void showSettings(Nodes *nodes, QWidget *parent, bool showProxyTab = false);
|
||||||
|
|
||||||
|
@ -59,6 +61,7 @@ public slots:
|
||||||
void tryOpenWallet(const QString &path, const QString &password);
|
void tryOpenWallet(const QString &path, const QString &password);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
void raise();
|
||||||
void onWalletOpened(Wallet *wallet);
|
void onWalletOpened(Wallet *wallet);
|
||||||
void onWalletCreated(Wallet *wallet);
|
void onWalletCreated(Wallet *wallet);
|
||||||
void onWalletOpenPasswordRequired(bool invalidPassword, const QString &path);
|
void onWalletOpenPasswordRequired(bool invalidPassword, const QString &path);
|
||||||
|
|
|
@ -3,8 +3,6 @@
|
||||||
"tor": [
|
"tor": [
|
||||||
"sfprpc2fws6ltnq4hyr7lvpul3nank5layd7q7tyc5h4gy4h77gtabad.onion:18089",
|
"sfprpc2fws6ltnq4hyr7lvpul3nank5layd7q7tyc5h4gy4h77gtabad.onion:18089",
|
||||||
"moneroxmrxw44lku6qniyarpwgznpcwml4drq7vb24ppatlcg4kmxpqd.onion:18089",
|
"moneroxmrxw44lku6qniyarpwgznpcwml4drq7vb24ppatlcg4kmxpqd.onion:18089",
|
||||||
"6dsdenp6vjkvqzy4wzsnzn6wixkdzihx3khiumyzieauxuxslmcaeiad.onion:18081",
|
|
||||||
"56wl7y2ebhamkkiza4b7il4mrzwtyvpdym7bm2bkg3jrei2je646k3qd.onion:18089",
|
|
||||||
"ip4zpbps7unk6xhlanqtw24f75akfbl3upeckfjqjks7ftfnk4i73oid.onion:18081",
|
"ip4zpbps7unk6xhlanqtw24f75akfbl3upeckfjqjks7ftfnk4i73oid.onion:18081",
|
||||||
"mhfsxznn5pi4xuxohj5k7unqp73sa6d44mbeewbpxnm25z3wzfogcfyd.onion:18081",
|
"mhfsxznn5pi4xuxohj5k7unqp73sa6d44mbeewbpxnm25z3wzfogcfyd.onion:18081",
|
||||||
"7inib34hqn2ocmlaaxjshdavbdn5w5rfdff735lbz33765j2pz3tn4ad.onion:18081",
|
"7inib34hqn2ocmlaaxjshdavbdn5w5rfdff735lbz33765j2pz3tn4ad.onion:18081",
|
||||||
|
@ -21,10 +19,10 @@
|
||||||
"rucknium757bokwv3ss35ftgc3gzb7hgbvvglbg3hisp7tsj2fkd2nyd.onion:18081"
|
"rucknium757bokwv3ss35ftgc3gzb7hgbvvglbg3hisp7tsj2fkd2nyd.onion:18081"
|
||||||
],
|
],
|
||||||
"i2p": [
|
"i2p": [
|
||||||
"ynk3hrwte23asonojqeskoulek2g2cd6tqg4neghnenfyljrvhga.b32.i2p:18081",
|
"ofrnxmr5ltaazarexs3damrcsldc5p6qlcos3vk25cwdgyjvrueq.b32.i2p:18089",
|
||||||
"t7lce3j7mwxt32h755u3njjp3k6og3defgueo3iecgsexxnkoezouobc.b32.i2p:18089",
|
"vdmnehdjkpkg57nthgnjfuaqgku673r5bpbqg56ix6fyqoywgqrq.b32.i2p:18089",
|
||||||
"ecnfc7oyzzw3jmwc2omxzccbik33wyyaofxsfow7342z6kjanq6a.b32.i2p:18089",
|
"uqj3aphckqtjsitz7kxx5flqpwjlq5ppr3chazfued7xucv3nheq.b32.i2p:18089",
|
||||||
"xmp3afekvuhbmzxl2bgj6ju23d6feqpumxuzdqzq4aysbijohdxa.b32.i2p:18089"
|
"ugnlcdciyhghh2zert7c3kl4biwkirc43ke33jiy5slnd3mv2trq.b32.i2p:18089"
|
||||||
],
|
],
|
||||||
"clearnet": [
|
"clearnet": [
|
||||||
"node.community.rino.io:18081",
|
"node.community.rino.io:18081",
|
||||||
|
|
|
@ -2141,4 +2141,30 @@
|
||||||
1723042527:3210000
|
1723042527:3210000
|
||||||
1723220196:3211500
|
1723220196:3211500
|
||||||
1723401886:3213000
|
1723401886:3213000
|
||||||
1723577283:3214500
|
1723577283:3214500
|
||||||
|
1723758523:3216000
|
||||||
|
1723943045:3217500
|
||||||
|
1724123516:3219000
|
||||||
|
1724300973:3220500
|
||||||
|
1724484278:3222000
|
||||||
|
1724666887:3223500
|
||||||
|
1724849987:3225000
|
||||||
|
1725015093:3226500
|
||||||
|
1725197019:3228000
|
||||||
|
1725383293:3229500
|
||||||
|
1725558474:3231000
|
||||||
|
1725742245:3232500
|
||||||
|
1725924657:3234000
|
||||||
|
1726105045:3235500
|
||||||
|
1726283197:3237000
|
||||||
|
1726463211:3238500
|
||||||
|
1726636517:3240000
|
||||||
|
1726818897:3241500
|
||||||
|
1727000277:3243000
|
||||||
|
1727180466:3244500
|
||||||
|
1727359618:3246000
|
||||||
|
1727542507:3247500
|
||||||
|
1727723723:3249000
|
||||||
|
1727906604:3250500
|
||||||
|
1728083420:3252000
|
||||||
|
1728259944:3253500
|
|
@ -1108,4 +1108,30 @@
|
||||||
1722983267:1660500
|
1722983267:1660500
|
||||||
1723166957:1662000
|
1723166957:1662000
|
||||||
1723347339:1663500
|
1723347339:1663500
|
||||||
1723524898:1665000
|
1723524898:1665000
|
||||||
|
1723704308:1666500
|
||||||
|
1723860608:1668000
|
||||||
|
1724036267:1669500
|
||||||
|
1724260269:1671000
|
||||||
|
1724443530:1672500
|
||||||
|
1724620063:1674000
|
||||||
|
1724802245:1675500
|
||||||
|
1724981057:1677000
|
||||||
|
1725166685:1678500
|
||||||
|
1725344930:1680000
|
||||||
|
1725518960:1681500
|
||||||
|
1725706849:1683000
|
||||||
|
1725884468:1684500
|
||||||
|
1726020096:1686000
|
||||||
|
1726227873:1687500
|
||||||
|
1726405463:1689000
|
||||||
|
1726586949:1690500
|
||||||
|
1726765988:1692000
|
||||||
|
1726945486:1693500
|
||||||
|
1727125243:1695000
|
||||||
|
1727307226:1696500
|
||||||
|
1727549352:1698000
|
||||||
|
1727727177:1699500
|
||||||
|
1727908581:1701000
|
||||||
|
1728092922:1702500
|
||||||
|
1728273508:1704000
|
|
@ -4,8 +4,7 @@
|
||||||
#ifndef FEATHER_CONSTANTS_H
|
#ifndef FEATHER_CONSTANTS_H
|
||||||
#define FEATHER_CONSTANTS_H
|
#define FEATHER_CONSTANTS_H
|
||||||
|
|
||||||
#include <QtGlobal>
|
#include <QString>
|
||||||
#include <QUrl>
|
|
||||||
|
|
||||||
#include "networktype.h"
|
#include "networktype.h"
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "ui_AboutDialog.h"
|
#include "ui_AboutDialog.h"
|
||||||
|
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
#include <QDate>
|
||||||
|
|
||||||
#include "config-feather.h"
|
#include "config-feather.h"
|
||||||
#include "utils/Utils.h"
|
#include "utils/Utils.h"
|
||||||
|
|
|
@ -4,9 +4,6 @@
|
||||||
#ifndef FEATHER_ABOUT_H
|
#ifndef FEATHER_ABOUT_H
|
||||||
#define FEATHER_ABOUT_H
|
#define FEATHER_ABOUT_H
|
||||||
|
|
||||||
#include <QDialog>
|
|
||||||
#include <QStringListModel>
|
|
||||||
|
|
||||||
#include "components.h"
|
#include "components.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
#include "libwalletqt/SubaddressAccount.h"
|
#include "libwalletqt/SubaddressAccount.h"
|
||||||
#include "libwalletqt/WalletManager.h"
|
#include "libwalletqt/WalletManager.h"
|
||||||
|
#include "model/SubaddressAccountModel.h"
|
||||||
#include "utils/Icons.h"
|
#include "utils/Icons.h"
|
||||||
#include "utils/Utils.h"
|
#include "utils/Utils.h"
|
||||||
|
|
||||||
|
|
|
@ -4,10 +4,8 @@
|
||||||
#ifndef FEATHER_ACCOUNTSWITCHERDIALOG_H
|
#ifndef FEATHER_ACCOUNTSWITCHERDIALOG_H
|
||||||
#define FEATHER_ACCOUNTSWITCHERDIALOG_H
|
#define FEATHER_ACCOUNTSWITCHERDIALOG_H
|
||||||
|
|
||||||
#include <QDialog>
|
|
||||||
|
|
||||||
#include "libwalletqt/Wallet.h"
|
|
||||||
#include "components.h"
|
#include "components.h"
|
||||||
|
#include "libwalletqt/Wallet.h"
|
||||||
#include "model/SubaddressAccountModel.h"
|
#include "model/SubaddressAccountModel.h"
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "utils/Utils.h"
|
#include "utils/Utils.h"
|
||||||
#include "components.h"
|
#include "components.h"
|
||||||
#include "dialog/QrCodeDialog.h"
|
#include "dialog/QrCodeDialog.h"
|
||||||
|
#include "libwalletqt/Wallet.h"
|
||||||
|
|
||||||
AddressCheckerIndexDialog::AddressCheckerIndexDialog(Wallet *wallet, QWidget *parent)
|
AddressCheckerIndexDialog::AddressCheckerIndexDialog(Wallet *wallet, QWidget *parent)
|
||||||
: WindowModalDialog(parent)
|
: WindowModalDialog(parent)
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
#define ADDRESSCHECKERINDEXDIALOG_H
|
#define ADDRESSCHECKERINDEXDIALOG_H
|
||||||
|
|
||||||
#include "components.h"
|
#include "components.h"
|
||||||
#include "Wallet.h"
|
|
||||||
|
class Wallet;
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class AddressCheckerIndexDialog;
|
class AddressCheckerIndexDialog;
|
||||||
|
|
|
@ -4,8 +4,6 @@
|
||||||
#ifndef FEATHER_BALANCEDIALOG_H
|
#ifndef FEATHER_BALANCEDIALOG_H
|
||||||
#define FEATHER_BALANCEDIALOG_H
|
#define FEATHER_BALANCEDIALOG_H
|
||||||
|
|
||||||
#include <QDialog>
|
|
||||||
|
|
||||||
#include "components.h"
|
#include "components.h"
|
||||||
#include "libwalletqt/Wallet.h"
|
#include "libwalletqt/Wallet.h"
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "ui_DocsDialog.h"
|
#include "ui_DocsDialog.h"
|
||||||
|
|
||||||
#include <QScrollBar>
|
#include <QScrollBar>
|
||||||
|
#include <QDirIterator>
|
||||||
|
|
||||||
#include "utils/Utils.h"
|
#include "utils/Utils.h"
|
||||||
#include "ColorScheme.h"
|
#include "ColorScheme.h"
|
||||||
|
@ -133,6 +134,12 @@ DocsDialog::DocsDialog(QWidget *parent)
|
||||||
this->updateHighlights(ui->search->text());
|
this->updateHighlights(ui->search->text());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Pressing 'enter' in the search box shouldn't close the dialog
|
||||||
|
QPushButton *closeButton = ui->buttonBox->button(QDialogButtonBox::Close);
|
||||||
|
if (closeButton) {
|
||||||
|
closeButton->setAutoDefault(false);
|
||||||
|
}
|
||||||
|
|
||||||
this->showDoc("report_an_issue");
|
this->showDoc("report_an_issue");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,10 +8,8 @@
|
||||||
#include "ColorScheme.h"
|
#include "ColorScheme.h"
|
||||||
#include "utils/Utils.h"
|
#include "utils/Utils.h"
|
||||||
#include "polyseed/polyseed.h"
|
#include "polyseed/polyseed.h"
|
||||||
#include "utils/AsyncTask.h"
|
|
||||||
#include "device/device_default.hpp"
|
#include "device/device_default.hpp"
|
||||||
#include "cryptonote_basic/account.h"
|
#include "cryptonote_basic/account.h"
|
||||||
#include "cryptonote_basic/cryptonote_basic_impl.h"
|
|
||||||
#include "cryptonote_basic/blobdatatype.h"
|
#include "cryptonote_basic/blobdatatype.h"
|
||||||
#include "common/base58.h"
|
#include "common/base58.h"
|
||||||
#include "serialization/binary_utils.h"
|
#include "serialization/binary_utils.h"
|
||||||
|
|
|
@ -70,10 +70,14 @@ TxInfoDialog::TxInfoDialog(Wallet *wallet, TransactionRow *txInfo, QWidget *pare
|
||||||
ui->frameInputs->hide();
|
ui->frameInputs->hide();
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
ui->frame_destinationsWarning->hide();
|
||||||
|
|
||||||
QTextCursor cursor = ui->outputs->textCursor();
|
QTextCursor cursor = ui->outputs->textCursor();
|
||||||
|
|
||||||
auto transfers = txInfo->transfers();
|
auto transfers = txInfo->transfers();
|
||||||
if (!transfers.isEmpty()) {
|
if (!transfers.isEmpty()) {
|
||||||
|
bool hasIntegrated = false;
|
||||||
|
|
||||||
for (const auto& transfer : transfers) {
|
for (const auto& transfer : transfers) {
|
||||||
auto address = transfer->address();
|
auto address = transfer->address();
|
||||||
auto amount = WalletManager::displayAmount(transfer->amount());
|
auto amount = WalletManager::displayAmount(transfer->amount());
|
||||||
|
@ -81,9 +85,21 @@ TxInfoDialog::TxInfoDialog(Wallet *wallet, TransactionRow *txInfo, QWidget *pare
|
||||||
cursor.insertText(address, Utils::addressTextFormat(index, transfer->amount()));
|
cursor.insertText(address, Utils::addressTextFormat(index, transfer->amount()));
|
||||||
cursor.insertText(QString(" %1").arg(amount), QTextCharFormat());
|
cursor.insertText(QString(" %1").arg(amount), QTextCharFormat());
|
||||||
cursor.insertBlock();
|
cursor.insertBlock();
|
||||||
|
|
||||||
|
if (WalletManager::baseAddressFromIntegratedAddress(transfer->address(), constants::networkType) != transfer->address()) {
|
||||||
|
hasIntegrated = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ui->label_outputs->setText(QString("Destinations (%2)").arg(QString::number(transfers.size())));
|
ui->label_outputs->setText(QString("Destinations (%2)").arg(QString::number(transfers.size())));
|
||||||
this->adjustHeight(ui->outputs, transfers.size());
|
this->adjustHeight(ui->outputs, transfers.size());
|
||||||
|
|
||||||
|
// Trezor saves a mangled payment ID.
|
||||||
|
if (m_wallet->isTrezor() && !hasIntegrated && txInfo->hasPaymentId()) {
|
||||||
|
ui->frame_destinationsWarning->setInfo(icons()->icon("warning"), "The address displayed here does not contain a payment ID. "
|
||||||
|
"If you are making a repeat payment to a service, "
|
||||||
|
"do not copy the address from here to prevent a loss of funds.");
|
||||||
|
ui->frame_destinationsWarning->show();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ui->frameOutputs->hide();
|
ui->frameOutputs->hide();
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>929</width>
|
<width>929</width>
|
||||||
<height>715</height>
|
<height>723</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
|
@ -184,6 +184,16 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="InfoFrame" name="frame_destinationsWarning">
|
||||||
|
<property name="frameShape">
|
||||||
|
<enum>QFrame::StyledPanel</enum>
|
||||||
|
</property>
|
||||||
|
<property name="frameShadow">
|
||||||
|
<enum>QFrame::Raised</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QTextEdit" name="outputs">
|
<widget class="QTextEdit" name="outputs">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
|
@ -287,6 +297,14 @@
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
|
<customwidgets>
|
||||||
|
<customwidget>
|
||||||
|
<class>InfoFrame</class>
|
||||||
|
<extends>QFrame</extends>
|
||||||
|
<header>components.h</header>
|
||||||
|
<container>1</container>
|
||||||
|
</customwidget>
|
||||||
|
</customwidgets>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections/>
|
<connections/>
|
||||||
</ui>
|
</ui>
|
||||||
|
|
|
@ -4,8 +4,6 @@
|
||||||
#include "URSettingsDialog.h"
|
#include "URSettingsDialog.h"
|
||||||
#include "ui_URSettingsDialog.h"
|
#include "ui_URSettingsDialog.h"
|
||||||
|
|
||||||
#include <QFileDialog>
|
|
||||||
|
|
||||||
#include "utils/config.h"
|
#include "utils/config.h"
|
||||||
#include "utils/Utils.h"
|
#include "utils/Utils.h"
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,8 @@ CoinsInfo* Coins::coin(int index)
|
||||||
|
|
||||||
void Coins::refresh()
|
void Coins::refresh()
|
||||||
{
|
{
|
||||||
|
qDebug() << Q_FUNC_INFO;
|
||||||
|
|
||||||
emit refreshStarted();
|
emit refreshStarted();
|
||||||
|
|
||||||
boost::shared_lock<boost::shared_mutex> transfers_lock(m_wallet2->m_transfers_mutex);
|
boost::shared_lock<boost::shared_mutex> transfers_lock(m_wallet2->m_transfers_mutex);
|
||||||
|
@ -103,48 +105,52 @@ quint64 Coins::count() const
|
||||||
return m_rows.length();
|
return m_rows.length();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Coins::freeze(QString &publicKey)
|
void Coins::freeze(QStringList &publicKeys)
|
||||||
{
|
{
|
||||||
crypto::public_key pk;
|
crypto::public_key pk;
|
||||||
if (!epee::string_tools::hex_to_pod(publicKey.toStdString(), pk))
|
|
||||||
{
|
for (const auto& publicKey : publicKeys) {
|
||||||
qWarning() << "Invalid public key: " << publicKey;
|
if (!epee::string_tools::hex_to_pod(publicKey.toStdString(), pk))
|
||||||
return;
|
{
|
||||||
|
qWarning() << "Invalid public key: " << publicKey;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_wallet2->freeze(pk);
|
||||||
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
qWarning() << "freeze: " << e.what();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
refresh();
|
||||||
{
|
|
||||||
m_wallet2->freeze(pk);
|
|
||||||
refresh();
|
|
||||||
}
|
|
||||||
catch (const std::exception& e)
|
|
||||||
{
|
|
||||||
qWarning() << "freeze: " << e.what();
|
|
||||||
}
|
|
||||||
|
|
||||||
emit coinFrozen();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Coins::thaw(QString &publicKey)
|
void Coins::thaw(QStringList &publicKeys)
|
||||||
{
|
{
|
||||||
crypto::public_key pk;
|
crypto::public_key pk;
|
||||||
if (!epee::string_tools::hex_to_pod(publicKey.toStdString(), pk))
|
|
||||||
{
|
for (const auto& publicKey : publicKeys) {
|
||||||
qWarning() << "Invalid public key: " << publicKey;
|
if (!epee::string_tools::hex_to_pod(publicKey.toStdString(), pk))
|
||||||
return;
|
{
|
||||||
|
qWarning() << "Invalid public key: " << publicKey;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
m_wallet2->thaw(pk);
|
||||||
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
qWarning() << "thaw: " << e.what();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
refresh();
|
||||||
{
|
|
||||||
m_wallet2->thaw(pk);
|
|
||||||
refresh();
|
|
||||||
}
|
|
||||||
catch (const std::exception& e)
|
|
||||||
{
|
|
||||||
qWarning() << "thaw: " << e.what();
|
|
||||||
}
|
|
||||||
|
|
||||||
emit coinThawed();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QVector<CoinsInfo*> Coins::coins_from_txid(const QString &txid)
|
QVector<CoinsInfo*> Coins::coins_from_txid(const QString &txid)
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QReadWriteLock>
|
#include <QReadWriteLock>
|
||||||
#include <QDateTime>
|
|
||||||
|
|
||||||
#include "Wallet.h"
|
#include "Wallet.h"
|
||||||
|
|
||||||
|
@ -32,8 +31,10 @@ public:
|
||||||
CoinsInfo * coin(int index);
|
CoinsInfo * coin(int index);
|
||||||
void refresh();
|
void refresh();
|
||||||
void refreshUnlocked();
|
void refreshUnlocked();
|
||||||
void freeze(QString &publicKey);
|
|
||||||
void thaw(QString &publicKey);
|
void freeze(QStringList &publicKeys);
|
||||||
|
void thaw(QStringList &publicKeys);
|
||||||
|
|
||||||
QVector<CoinsInfo*> coins_from_txid(const QString &txid);
|
QVector<CoinsInfo*> coins_from_txid(const QString &txid);
|
||||||
QVector<CoinsInfo*> coinsFromKeyImage(const QStringList &keyimages);
|
QVector<CoinsInfo*> coinsFromKeyImage(const QStringList &keyimages);
|
||||||
void setDescription(const QString &publicKey, quint32 accountIndex, const QString &description);
|
void setDescription(const QString &publicKey, quint32 accountIndex, const QString &description);
|
||||||
|
@ -44,8 +45,6 @@ public:
|
||||||
signals:
|
signals:
|
||||||
void refreshStarted() const;
|
void refreshStarted() const;
|
||||||
void refreshFinished() const;
|
void refreshFinished() const;
|
||||||
void coinFrozen() const;
|
|
||||||
void coinThawed() const;
|
|
||||||
void descriptionChanged() const;
|
void descriptionChanged() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
#include "Input.h"
|
#include "Input.h"
|
||||||
#include "Transfer.h"
|
#include "Transfer.h"
|
||||||
|
#include <wallet/api/wallet2_api.h>
|
||||||
|
|
||||||
quint64 ConstructionInfo::unlockTime() const {
|
quint64 ConstructionInfo::unlockTime() const {
|
||||||
return m_unlockTime;
|
return m_unlockTime;
|
||||||
|
|
|
@ -4,13 +4,16 @@
|
||||||
#ifndef FEATHER_CONSTRUCTIONINFO_H
|
#ifndef FEATHER_CONSTRUCTIONINFO_H
|
||||||
#define FEATHER_CONSTRUCTIONINFO_H
|
#define FEATHER_CONSTRUCTIONINFO_H
|
||||||
|
|
||||||
#include <wallet/api/wallet2_api.h>
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QSet>
|
#include <QSet>
|
||||||
|
|
||||||
class Input;
|
class Input;
|
||||||
class Transfer;
|
class Transfer;
|
||||||
|
|
||||||
|
namespace Monero {
|
||||||
|
class TransactionConstructionInfo;
|
||||||
|
}
|
||||||
|
|
||||||
class ConstructionInfo : public QObject
|
class ConstructionInfo : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
|
@ -4,15 +4,11 @@
|
||||||
#ifndef FEATHER_INPUT_H
|
#ifndef FEATHER_INPUT_H
|
||||||
#define FEATHER_INPUT_H
|
#define FEATHER_INPUT_H
|
||||||
|
|
||||||
#include <wallet/api/wallet2_api.h>
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
class Input : public QObject
|
class Input : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(quint64 amount READ amount)
|
|
||||||
Q_PROPERTY(QString pubKey READ pubKey)
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit Input(uint64_t _amount, QString _address, QObject *parent = nullptr): QObject(parent), m_amount(_amount), m_pubkey(std::move(_address)) {};
|
explicit Input(uint64_t _amount, QString _address, QObject *parent = nullptr): QObject(parent), m_amount(_amount), m_pubkey(std::move(_address)) {};
|
||||||
|
@ -20,10 +16,10 @@ private:
|
||||||
friend class ConstructionInfo;
|
friend class ConstructionInfo;
|
||||||
quint64 m_amount;
|
quint64 m_amount;
|
||||||
QString m_pubkey;
|
QString m_pubkey;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
quint64 amount() const { return m_amount; }
|
quint64 amount() const { return m_amount; }
|
||||||
QString pubKey() const { return m_pubkey; }
|
QString pubKey() const { return m_pubkey; }
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //FEATHER_INPUT_H
|
#endif //FEATHER_INPUT_H
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
#include "PassphraseHelper.h"
|
#include "PassphraseHelper.h"
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
Monero::optional<std::string> PassphraseHelper::onDevicePassphraseRequest(bool & on_device)
|
std::optional<std::string> PassphraseHelper::onDevicePassphraseRequest(bool & on_device)
|
||||||
{
|
{
|
||||||
qDebug() << __FUNCTION__;
|
qDebug() << __FUNCTION__;
|
||||||
QMutexLocker locker(&m_mutex_pass);
|
QMutexLocker locker(&m_mutex_pass);
|
||||||
|
@ -26,9 +26,9 @@ Monero::optional<std::string> PassphraseHelper::onDevicePassphraseRequest(bool &
|
||||||
if (!on_device) {
|
if (!on_device) {
|
||||||
auto tmpPass = m_passphrase.toStdString();
|
auto tmpPass = m_passphrase.toStdString();
|
||||||
m_passphrase = QString();
|
m_passphrase = QString();
|
||||||
return Monero::optional<std::string>(tmpPass);
|
return std::optional<std::string>(tmpPass);
|
||||||
} else {
|
} else {
|
||||||
return Monero::optional<std::string>();
|
return std::optional<std::string>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,11 +4,9 @@
|
||||||
#ifndef MONERO_GUI_PASSPHRASEHELPER_H
|
#ifndef MONERO_GUI_PASSPHRASEHELPER_H
|
||||||
#define MONERO_GUI_PASSPHRASEHELPER_H
|
#define MONERO_GUI_PASSPHRASEHELPER_H
|
||||||
|
|
||||||
#include <wallet/api/wallet2_api.h>
|
|
||||||
#include <QMutex>
|
#include <QMutex>
|
||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
#include <QWaitCondition>
|
#include <QWaitCondition>
|
||||||
#include <QMutex>
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements component responsible for showing entry prompt to the user,
|
* Implements component responsible for showing entry prompt to the user,
|
||||||
|
@ -32,7 +30,7 @@ class PassphraseHelper {
|
||||||
public:
|
public:
|
||||||
PassphraseHelper(PassphrasePrompter * prompter=nullptr): m_prompter(prompter) {};
|
PassphraseHelper(PassphrasePrompter * prompter=nullptr): m_prompter(prompter) {};
|
||||||
PassphraseHelper(const PassphraseHelper & h): PassphraseHelper(h.m_prompter) {};
|
PassphraseHelper(const PassphraseHelper & h): PassphraseHelper(h.m_prompter) {};
|
||||||
Monero::optional<std::string> onDevicePassphraseRequest(bool & on_device);
|
std::optional<std::string> onDevicePassphraseRequest(bool & on_device);
|
||||||
void onPassphraseEntered(const QString &passphrase, bool enter_on_device, bool entry_abort);
|
void onPassphraseEntered(const QString &passphrase, bool enter_on_device, bool entry_abort);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
|
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
|
|
||||||
|
#include <wallet/api/wallet2_api.h>
|
||||||
|
|
||||||
PendingTransaction::Status PendingTransaction::status() const
|
PendingTransaction::Status PendingTransaction::status() const
|
||||||
{
|
{
|
||||||
return static_cast<Status>(m_pimpl->status());
|
return static_cast<Status>(m_pimpl->status());
|
||||||
|
|
|
@ -7,18 +7,21 @@
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QList>
|
#include <QList>
|
||||||
|
|
||||||
#include <wallet/api/wallet2_api.h>
|
|
||||||
#include "PendingTransactionInfo.h"
|
#include "PendingTransactionInfo.h"
|
||||||
|
|
||||||
|
namespace Monero {
|
||||||
|
class PendingTransaction;
|
||||||
|
}
|
||||||
|
|
||||||
class PendingTransaction : public QObject
|
class PendingTransaction : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum Status {
|
enum Status {
|
||||||
Status_Ok = Monero::PendingTransaction::Status_Ok,
|
Status_Ok = 0,
|
||||||
Status_Error = Monero::PendingTransaction::Status_Error,
|
Status_Error = 1,
|
||||||
Status_Critical = Monero::PendingTransaction::Status_Critical
|
Status_Critical = 2
|
||||||
};
|
};
|
||||||
Q_ENUM(Status)
|
Q_ENUM(Status)
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
// SPDX-FileCopyrightText: 2020-2024 The Monero Project
|
// SPDX-FileCopyrightText: 2020-2024 The Monero Project
|
||||||
|
|
||||||
#include "PendingTransactionInfo.h"
|
#include "PendingTransactionInfo.h"
|
||||||
|
#include <wallet/api/wallet2_api.h>
|
||||||
|
|
||||||
quint64 PendingTransactionInfo::fee() const {
|
quint64 PendingTransactionInfo::fee() const {
|
||||||
return m_fee;
|
return m_fee;
|
||||||
|
|
|
@ -11,6 +11,10 @@
|
||||||
class Input;
|
class Input;
|
||||||
class Transfer;
|
class Transfer;
|
||||||
|
|
||||||
|
namespace Monero {
|
||||||
|
class PendingTransactionInfo;
|
||||||
|
}
|
||||||
|
|
||||||
class PendingTransactionInfo : public ConstructionInfo
|
class PendingTransactionInfo : public ConstructionInfo
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
|
@ -4,10 +4,7 @@
|
||||||
#ifndef FEATHER_RINGS_H
|
#ifndef FEATHER_RINGS_H
|
||||||
#define FEATHER_RINGS_H
|
#define FEATHER_RINGS_H
|
||||||
|
|
||||||
#include <wallet/api/wallet2_api.h>
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QList>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
class Ring : public QObject
|
class Ring : public QObject
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,10 +4,8 @@
|
||||||
#ifndef SUBADDRESS_H
|
#ifndef SUBADDRESS_H
|
||||||
#define SUBADDRESS_H
|
#define SUBADDRESS_H
|
||||||
|
|
||||||
#include <functional>
|
|
||||||
|
|
||||||
#include <QReadWriteLock>
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <QReadWriteLock>
|
||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
|
|
||||||
|
|
|
@ -64,6 +64,8 @@ TransactionRow* TransactionHistory::transaction(int index)
|
||||||
|
|
||||||
void TransactionHistory::refresh()
|
void TransactionHistory::refresh()
|
||||||
{
|
{
|
||||||
|
qDebug() << Q_FUNC_INFO;
|
||||||
|
|
||||||
QDateTime firstDateTime = QDate(2014, 4, 18).startOfDay();
|
QDateTime firstDateTime = QDate(2014, 4, 18).startOfDay();
|
||||||
QDateTime lastDateTime = QDateTime::currentDateTime().addDays(1); // tomorrow (guard against jitter and timezones)
|
QDateTime lastDateTime = QDateTime::currentDateTime().addDays(1); // tomorrow (guard against jitter and timezones)
|
||||||
|
|
||||||
|
@ -75,10 +77,10 @@ void TransactionHistory::refresh()
|
||||||
clearRows();
|
clearRows();
|
||||||
|
|
||||||
quint64 lastTxHeight = 0;
|
quint64 lastTxHeight = 0;
|
||||||
|
bool hasFakePaymentId = m_wallet->isTrezor();
|
||||||
m_locked = false;
|
m_locked = false;
|
||||||
m_minutesToUnlock = 0;
|
m_minutesToUnlock = 0;
|
||||||
|
|
||||||
|
|
||||||
uint64_t min_height = 0;
|
uint64_t min_height = 0;
|
||||||
uint64_t max_height = (uint64_t)-1;
|
uint64_t max_height = (uint64_t)-1;
|
||||||
uint64_t wallet_height = m_wallet->blockChainHeight();
|
uint64_t wallet_height = m_wallet->blockChainHeight();
|
||||||
|
@ -105,7 +107,7 @@ void TransactionHistory::refresh()
|
||||||
if (payment_id.substr(16).find_first_not_of('0') == std::string::npos)
|
if (payment_id.substr(16).find_first_not_of('0') == std::string::npos)
|
||||||
payment_id = payment_id.substr(0,16);
|
payment_id = payment_id.substr(0,16);
|
||||||
|
|
||||||
auto* t = new TransactionRow();
|
auto* t = new TransactionRow(this);
|
||||||
t->m_paymentId = QString::fromStdString(payment_id);
|
t->m_paymentId = QString::fromStdString(payment_id);
|
||||||
t->m_coinbase = pd.m_coinbase;
|
t->m_coinbase = pd.m_coinbase;
|
||||||
t->m_amount = pd.m_amount;
|
t->m_amount = pd.m_amount;
|
||||||
|
@ -152,7 +154,7 @@ void TransactionHistory::refresh()
|
||||||
if (payment_id.substr(16).find_first_not_of('0') == std::string::npos)
|
if (payment_id.substr(16).find_first_not_of('0') == std::string::npos)
|
||||||
payment_id = payment_id.substr(0,16);
|
payment_id = payment_id.substr(0,16);
|
||||||
|
|
||||||
auto* t = new TransactionRow();
|
auto* t = new TransactionRow(this);
|
||||||
t->m_paymentId = QString::fromStdString(payment_id);
|
t->m_paymentId = QString::fromStdString(payment_id);
|
||||||
|
|
||||||
t->m_amount = pd.m_amount_out - change;
|
t->m_amount = pd.m_amount_out - change;
|
||||||
|
@ -176,7 +178,7 @@ void TransactionHistory::refresh()
|
||||||
// single output transaction might contain multiple transfers
|
// single output transaction might contain multiple transfers
|
||||||
for (auto const &d: pd.m_dests)
|
for (auto const &d: pd.m_dests)
|
||||||
{
|
{
|
||||||
Transfer *transfer = new Transfer(d.amount, QString::fromStdString(d.address(m_wallet2->nettype(), pd.m_payment_id)), this);
|
Transfer *transfer = new Transfer(d.amount, QString::fromStdString(d.address(m_wallet2->nettype(), pd.m_payment_id, !hasFakePaymentId)), this);
|
||||||
t->m_transfers.append(transfer);
|
t->m_transfers.append(transfer);
|
||||||
}
|
}
|
||||||
for (auto const &r: pd.m_rings)
|
for (auto const &r: pd.m_rings)
|
||||||
|
@ -206,7 +208,7 @@ void TransactionHistory::refresh()
|
||||||
payment_id = payment_id.substr(0,16);
|
payment_id = payment_id.substr(0,16);
|
||||||
bool is_failed = pd.m_state == tools::wallet2::unconfirmed_transfer_details::failed;
|
bool is_failed = pd.m_state == tools::wallet2::unconfirmed_transfer_details::failed;
|
||||||
|
|
||||||
auto *t = new TransactionRow();
|
auto *t = new TransactionRow(this);
|
||||||
t->m_paymentId = QString::fromStdString(payment_id);
|
t->m_paymentId = QString::fromStdString(payment_id);
|
||||||
|
|
||||||
t->m_amount = pd.m_amount_out - change;
|
t->m_amount = pd.m_amount_out - change;
|
||||||
|
@ -229,7 +231,7 @@ void TransactionHistory::refresh()
|
||||||
|
|
||||||
for (auto const &d: pd.m_dests)
|
for (auto const &d: pd.m_dests)
|
||||||
{
|
{
|
||||||
Transfer *transfer = new Transfer(d.amount, QString::fromStdString(d.address(m_wallet2->nettype(), pd.m_payment_id)), this);
|
Transfer *transfer = new Transfer(d.amount, QString::fromStdString(d.address(m_wallet2->nettype(), pd.m_payment_id, !hasFakePaymentId)), this);
|
||||||
t->m_transfers.append(transfer);
|
t->m_transfers.append(transfer);
|
||||||
}
|
}
|
||||||
for (auto const &r: pd.m_rings)
|
for (auto const &r: pd.m_rings)
|
||||||
|
@ -254,7 +256,7 @@ void TransactionHistory::refresh()
|
||||||
std::string payment_id = epee::string_tools::pod_to_hex(i->first);
|
std::string payment_id = epee::string_tools::pod_to_hex(i->first);
|
||||||
if (payment_id.substr(16).find_first_not_of('0') == std::string::npos)
|
if (payment_id.substr(16).find_first_not_of('0') == std::string::npos)
|
||||||
payment_id = payment_id.substr(0,16);
|
payment_id = payment_id.substr(0,16);
|
||||||
auto *t = new TransactionRow();
|
auto *t = new TransactionRow(this);
|
||||||
t->m_paymentId = QString::fromStdString(payment_id);
|
t->m_paymentId = QString::fromStdString(payment_id);
|
||||||
t->m_amount = pd.m_amount;
|
t->m_amount = pd.m_amount;
|
||||||
t->m_balanceDelta = pd.m_amount;
|
t->m_balanceDelta = pd.m_amount;
|
||||||
|
@ -281,12 +283,14 @@ void TransactionHistory::refresh()
|
||||||
void TransactionHistory::setTxNote(const QString &txid, const QString ¬e)
|
void TransactionHistory::setTxNote(const QString &txid, const QString ¬e)
|
||||||
{
|
{
|
||||||
cryptonote::blobdata txid_data;
|
cryptonote::blobdata txid_data;
|
||||||
if(!epee::string_tools::parse_hexstr_to_binbuff(txid.toStdString(), txid_data) || txid_data.size() != sizeof(crypto::hash))
|
if (!epee::string_tools::parse_hexstr_to_binbuff(txid.toStdString(), txid_data) || txid_data.size() != sizeof(crypto::hash)) {
|
||||||
|
qDebug() << Q_FUNC_INFO << "invalid txid";
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const crypto::hash htxid = *reinterpret_cast<const crypto::hash*>(txid_data.data());
|
const crypto::hash htxid = *reinterpret_cast<const crypto::hash*>(txid_data.data());
|
||||||
|
|
||||||
m_wallet2->set_tx_note(htxid, note.toStdString());
|
m_wallet2->set_tx_note(htxid, note.toStdString());
|
||||||
refresh();
|
|
||||||
emit txNoteChanged();
|
emit txNoteChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -401,4 +405,102 @@ bool TransactionHistory::writeCSV(const QString &path) {
|
||||||
|
|
||||||
data = QString("blockHeight,timestamp,date,accountIndex,direction,balanceDelta,amount,fee,txid,description,paymentId,fiatAmount,fiatCurrency%1").arg(data);
|
data = QString("blockHeight,timestamp,date,accountIndex,direction,balanceDelta,amount,fee,txid,description,paymentId,fiatAmount,fiatCurrency%1").arg(data);
|
||||||
return Utils::fileWrite(path, data);
|
return Utils::fileWrite(path, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QStringList parseCSVLine(const QString &line) {
|
||||||
|
QStringList result;
|
||||||
|
QString currentField;
|
||||||
|
bool inQuotes = false;
|
||||||
|
|
||||||
|
for (int i = 0; i < line.length(); ++i) {
|
||||||
|
QChar currentChar = line[i];
|
||||||
|
|
||||||
|
if (currentChar == '"') {
|
||||||
|
if (inQuotes && i + 1 < line.length() && line[i + 1] == '"') {
|
||||||
|
currentField.append('"');
|
||||||
|
++i;
|
||||||
|
} else {
|
||||||
|
inQuotes = !inQuotes;
|
||||||
|
}
|
||||||
|
} else if (currentChar == ',' && !inQuotes) {
|
||||||
|
result.append(currentField.trimmed());
|
||||||
|
currentField.clear();
|
||||||
|
} else {
|
||||||
|
currentField.append(currentChar);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result.append(currentField.trimmed());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString TransactionHistory::importLabelsFromCSV(const QString &fileName) {
|
||||||
|
QFile file(fileName);
|
||||||
|
|
||||||
|
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||||
|
return QString("Could not open file: %1").arg(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
QTextStream in(&file);
|
||||||
|
|
||||||
|
QList<QStringList> fields;
|
||||||
|
while (!in.atEnd()) {
|
||||||
|
QString line = in.readLine();
|
||||||
|
fields.append(parseCSVLine(line));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fields.empty()) {
|
||||||
|
return "CSV file appears to be empty";
|
||||||
|
}
|
||||||
|
|
||||||
|
qint64 txidField = -1;
|
||||||
|
qint64 descriptionField = -1;
|
||||||
|
|
||||||
|
QStringList header = fields[0];
|
||||||
|
for (int i = 0; i < header.length(); i++) {
|
||||||
|
if (header[i] == "txid") {
|
||||||
|
txidField = i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (header[i] == "description") {
|
||||||
|
descriptionField = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (txidField < 0) {
|
||||||
|
return "'txid' field not found in CSV header";
|
||||||
|
}
|
||||||
|
if (descriptionField < 0) {
|
||||||
|
return "'description' field not found in CSV header";
|
||||||
|
}
|
||||||
|
qint64 maxIndex = std::max(txidField, descriptionField);
|
||||||
|
|
||||||
|
QList<QPair<QString, QString>> descriptions;
|
||||||
|
|
||||||
|
for (int i = 1; i < fields.length(); i++) {
|
||||||
|
const auto& row = fields[i];
|
||||||
|
if (maxIndex >= row.length()) {
|
||||||
|
qDebug() << "Row with invalid length in CSV";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (row[txidField].isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (row[descriptionField].isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
descriptions.push_back({row[txidField], row[descriptionField]});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& description : descriptions) {
|
||||||
|
qDebug() << "Setting note for tx:" << description.first << "description:" << description.second;
|
||||||
|
this->setTxNote(description.first, description.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->refresh();
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
|
@ -34,7 +34,6 @@ public:
|
||||||
TransactionRow* transaction(int index);
|
TransactionRow* transaction(int index);
|
||||||
void refresh();
|
void refresh();
|
||||||
void setTxNote(const QString &txid, const QString ¬e);
|
void setTxNote(const QString &txid, const QString ¬e);
|
||||||
bool writeCSV(const QString &path);
|
|
||||||
quint64 count() const;
|
quint64 count() const;
|
||||||
QDateTime firstDateTime() const;
|
QDateTime firstDateTime() const;
|
||||||
QDateTime lastDateTime() const;
|
QDateTime lastDateTime() const;
|
||||||
|
@ -42,6 +41,9 @@ public:
|
||||||
bool locked() const;
|
bool locked() const;
|
||||||
void clearRows();
|
void clearRows();
|
||||||
|
|
||||||
|
bool writeCSV(const QString &path);
|
||||||
|
QString importLabelsFromCSV(const QString &fileName);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void refreshStarted() const;
|
void refreshStarted() const;
|
||||||
void refreshFinished() const;
|
void refreshFinished() const;
|
||||||
|
|
|
@ -2,7 +2,9 @@
|
||||||
// SPDX-FileCopyrightText: 2020-2024 The Monero Project
|
// SPDX-FileCopyrightText: 2020-2024 The Monero Project
|
||||||
|
|
||||||
#include "UnsignedTransaction.h"
|
#include "UnsignedTransaction.h"
|
||||||
#include <QDebug>
|
|
||||||
|
#include "ConstructionInfo.h"
|
||||||
|
#include <wallet/api/wallet2_api.h>
|
||||||
|
|
||||||
UnsignedTransaction::Status UnsignedTransaction::status() const
|
UnsignedTransaction::Status UnsignedTransaction::status() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,7 +6,12 @@
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
#include "libwalletqt/PendingTransactionInfo.h"
|
namespace Monero {
|
||||||
|
class UnsignedTransaction;
|
||||||
|
class Wallet;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ConstructionInfo;
|
||||||
|
|
||||||
class UnsignedTransaction : public QObject
|
class UnsignedTransaction : public QObject
|
||||||
{
|
{
|
||||||
|
@ -14,9 +19,9 @@ class UnsignedTransaction : public QObject
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum Status {
|
enum Status {
|
||||||
Status_Ok = Monero::UnsignedTransaction::Status_Ok,
|
Status_Ok = 0,
|
||||||
Status_Error = Monero::UnsignedTransaction::Status_Error,
|
Status_Error = 1,
|
||||||
Status_Critical = Monero::UnsignedTransaction::Status_Critical
|
Status_Critical = 2
|
||||||
};
|
};
|
||||||
Q_ENUM(Status)
|
Q_ENUM(Status)
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include "SubaddressAccount.h"
|
#include "SubaddressAccount.h"
|
||||||
#include "TransactionHistory.h"
|
#include "TransactionHistory.h"
|
||||||
#include "WalletManager.h"
|
#include "WalletManager.h"
|
||||||
|
#include "WalletListenerImpl.h"
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
|
@ -73,10 +74,6 @@ Wallet::Wallet(Monero::Wallet *wallet, QObject *parent)
|
||||||
this->updateBalance();
|
this->updateBalance();
|
||||||
}
|
}
|
||||||
|
|
||||||
connect(this->history(), &TransactionHistory::txNoteChanged, [this]{
|
|
||||||
this->history()->refresh();
|
|
||||||
});
|
|
||||||
|
|
||||||
connect(this, &Wallet::refreshed, this, &Wallet::onRefreshed);
|
connect(this, &Wallet::refreshed, this, &Wallet::onRefreshed);
|
||||||
connect(this, &Wallet::newBlock, this, &Wallet::onNewBlock);
|
connect(this, &Wallet::newBlock, this, &Wallet::onNewBlock);
|
||||||
connect(this, &Wallet::updated, this, &Wallet::onUpdated);
|
connect(this, &Wallet::updated, this, &Wallet::onUpdated);
|
||||||
|
@ -357,6 +354,22 @@ void Wallet::setSeedLanguage(const QString &lang)
|
||||||
m_wallet2->set_seed_language(lang.toStdString());
|
m_wallet2->set_seed_language(lang.toStdString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString Wallet::getSecretViewKey() const {
|
||||||
|
return QString::fromStdString(m_walletImpl->secretViewKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Wallet::getPublicViewKey() const {
|
||||||
|
return QString::fromStdString(m_walletImpl->publicViewKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Wallet::getSecretSpendKey() const {
|
||||||
|
return QString::fromStdString(m_walletImpl->secretSpendKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Wallet::getPublicSpendKey() const {
|
||||||
|
return QString::fromStdString(m_walletImpl->publicSpendKey());
|
||||||
|
}
|
||||||
|
|
||||||
// #################### Node connection ####################
|
// #################### Node connection ####################
|
||||||
|
|
||||||
void Wallet::setOffline(bool offline) {
|
void Wallet::setOffline(bool offline) {
|
||||||
|
@ -866,7 +879,7 @@ void Wallet::createTransaction(const QString &address, quint64 amount, const QSt
|
||||||
m_scheduler.run([this, all, address, amount, feeLevel, subtractFeeFromAmount] {
|
m_scheduler.run([this, all, address, amount, feeLevel, subtractFeeFromAmount] {
|
||||||
std::set<uint32_t> subaddr_indices;
|
std::set<uint32_t> subaddr_indices;
|
||||||
|
|
||||||
Monero::PendingTransaction *ptImpl = m_walletImpl->createTransaction(address.toStdString(), "", all ? Monero::optional<uint64_t>() : Monero::optional<uint64_t>(amount), constants::mixin,
|
Monero::PendingTransaction *ptImpl = m_walletImpl->createTransaction(address.toStdString(), "", all ? std::optional<uint64_t>() : std::optional<uint64_t>(amount), constants::mixin,
|
||||||
static_cast<Monero::PendingTransaction::Priority>(feeLevel),
|
static_cast<Monero::PendingTransaction::Priority>(feeLevel),
|
||||||
currentSubaddressAccount(), subaddr_indices, m_selectedInputs, subtractFeeFromAmount);
|
currentSubaddressAccount(), subaddr_indices, m_selectedInputs, subtractFeeFromAmount);
|
||||||
|
|
||||||
|
@ -1331,6 +1344,10 @@ bool Wallet::setRingDatabase(const QString &path) {
|
||||||
return m_walletImpl->setRingDatabase(path.toStdString());
|
return m_walletImpl->setRingDatabase(path.toStdString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
quint64 Wallet::getWalletCreationHeight() const {
|
||||||
|
return m_walletImpl->getRefreshFromBlockHeight();
|
||||||
|
}
|
||||||
|
|
||||||
void Wallet::setWalletCreationHeight(quint64 height) {
|
void Wallet::setWalletCreationHeight(quint64 height) {
|
||||||
m_wallet2->set_refresh_from_block_height(height);
|
m_wallet2->set_refresh_from_block_height(height);
|
||||||
}
|
}
|
||||||
|
@ -1431,7 +1448,7 @@ void Wallet::getTxPoolStatsAsync() {
|
||||||
|
|
||||||
Wallet::~Wallet()
|
Wallet::~Wallet()
|
||||||
{
|
{
|
||||||
qDebug("~Wallet: Closing wallet");
|
qDebug() << "~Wallet: Closing wallet" << QThread::currentThreadId();
|
||||||
|
|
||||||
pauseRefresh();
|
pauseRefresh();
|
||||||
m_walletImpl->stop();
|
m_walletImpl->stop();
|
||||||
|
@ -1448,5 +1465,5 @@ Wallet::~Wallet()
|
||||||
|
|
||||||
delete m_walletImpl;
|
delete m_walletImpl;
|
||||||
m_walletImpl = nullptr;
|
m_walletImpl = nullptr;
|
||||||
qDebug("m_walletImpl deleted");
|
qDebug() << "m_walletImpl deleted" << QThread::currentThreadId();
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,24 +4,28 @@
|
||||||
#ifndef WALLET_H
|
#ifndef WALLET_H
|
||||||
#define WALLET_H
|
#define WALLET_H
|
||||||
|
|
||||||
#include <QElapsedTimer>
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QMutex>
|
#include <QMutex>
|
||||||
#include <QList>
|
|
||||||
#include <QtConcurrent/QtConcurrent>
|
|
||||||
|
|
||||||
#include "utils/scheduler.h"
|
#include "utils/scheduler.h"
|
||||||
#include "PendingTransaction.h"
|
#include "PendingTransaction.h"
|
||||||
#include "UnsignedTransaction.h"
|
#include "UnsignedTransaction.h"
|
||||||
#include "utils/networktype.h"
|
#include "utils/networktype.h"
|
||||||
#include "PassphraseHelper.h"
|
#include "PassphraseHelper.h"
|
||||||
#include "WalletListenerImpl.h"
|
|
||||||
#include "rows/TxBacklogEntry.h"
|
#include "rows/TxBacklogEntry.h"
|
||||||
|
|
||||||
|
#include <set>
|
||||||
|
|
||||||
|
class WalletListenerImpl;
|
||||||
|
|
||||||
namespace Monero {
|
namespace Monero {
|
||||||
struct Wallet; // forward declaration
|
struct Wallet; // forward declaration
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace tools {
|
||||||
|
struct wallet2;
|
||||||
|
}
|
||||||
|
|
||||||
struct TxProof {
|
struct TxProof {
|
||||||
TxProof(QString proof, QString error = "")
|
TxProof(QString proof, QString error = "")
|
||||||
: proof(std::move(proof)), error(std::move(error)){}
|
: proof(std::move(proof)), error(std::move(error)){}
|
||||||
|
@ -94,17 +98,17 @@ public:
|
||||||
~Wallet() override;
|
~Wallet() override;
|
||||||
|
|
||||||
enum Status {
|
enum Status {
|
||||||
Status_Ok = Monero::Wallet::Status_Ok,
|
Status_Ok = 0,
|
||||||
Status_Error = Monero::Wallet::Status_Error,
|
Status_Error = 1,
|
||||||
Status_Critical = Monero::Wallet::Status_Critical,
|
Status_Critical = 2,
|
||||||
Status_BadPassword = Monero::Wallet::Status_BadPassword
|
Status_BadPassword = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_ENUM(Status)
|
Q_ENUM(Status)
|
||||||
|
|
||||||
enum ConnectionStatus {
|
enum ConnectionStatus {
|
||||||
ConnectionStatus_Disconnected = Monero::Wallet::ConnectionStatus_Disconnected,
|
ConnectionStatus_Disconnected = 0,
|
||||||
ConnectionStatus_WrongVersion = Monero::Wallet::ConnectionStatus_WrongVersion,
|
ConnectionStatus_WrongVersion = 2,
|
||||||
ConnectionStatus_Connecting = 9,
|
ConnectionStatus_Connecting = 9,
|
||||||
ConnectionStatus_Synchronizing = 10,
|
ConnectionStatus_Synchronizing = 10,
|
||||||
ConnectionStatus_Synchronized = 11
|
ConnectionStatus_Synchronized = 11
|
||||||
|
@ -186,10 +190,10 @@ public:
|
||||||
void setSeedLanguage(const QString &lang);
|
void setSeedLanguage(const QString &lang);
|
||||||
|
|
||||||
//! Get wallet keys
|
//! Get wallet keys
|
||||||
QString getSecretViewKey() const {return QString::fromStdString(m_walletImpl->secretViewKey());}
|
QString getSecretViewKey() const;
|
||||||
QString getPublicViewKey() const {return QString::fromStdString(m_walletImpl->publicViewKey());}
|
QString getPublicViewKey() const;
|
||||||
QString getSecretSpendKey() const {return QString::fromStdString(m_walletImpl->secretSpendKey());}
|
QString getSecretSpendKey() const;
|
||||||
QString getPublicSpendKey() const {return QString::fromStdString(m_walletImpl->publicSpendKey());}
|
QString getPublicSpendKey() const;
|
||||||
|
|
||||||
// ##### Node connection #####
|
// ##### Node connection #####
|
||||||
|
|
||||||
|
@ -399,7 +403,7 @@ public:
|
||||||
|
|
||||||
bool setRingDatabase(const QString &path);
|
bool setRingDatabase(const QString &path);
|
||||||
|
|
||||||
quint64 getWalletCreationHeight() const {return m_walletImpl->getRefreshFromBlockHeight();}
|
quint64 getWalletCreationHeight() const;
|
||||||
void setWalletCreationHeight(quint64 height);
|
void setWalletCreationHeight(quint64 height);
|
||||||
|
|
||||||
//! Rescan spent outputs
|
//! Rescan spent outputs
|
||||||
|
@ -431,7 +435,7 @@ signals:
|
||||||
void refreshed(bool success, const QString &message);
|
void refreshed(bool success, const QString &message);
|
||||||
|
|
||||||
void moneySpent(const QString &txId, quint64 amount);
|
void moneySpent(const QString &txId, quint64 amount);
|
||||||
void moneyReceived(const QString &txId, quint64 amount);
|
void moneyReceived(const QString &txId, quint64 amount, bool coinbase);
|
||||||
void unconfirmedMoneyReceived(const QString &txId, quint64 amount);
|
void unconfirmedMoneyReceived(const QString &txId, quint64 amount);
|
||||||
void newBlock(quint64 height, quint64 targetHeight);
|
void newBlock(quint64 height, quint64 targetHeight);
|
||||||
void walletCreationHeightChanged();
|
void walletCreationHeightChanged();
|
||||||
|
@ -529,6 +533,4 @@ private:
|
||||||
std::set<std::string> m_selectedInputs;
|
std::set<std::string> m_selectedInputs;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif // WALLET_H
|
#endif // WALLET_H
|
||||||
|
|
|
@ -25,13 +25,13 @@ void WalletListenerImpl::moneySpent(const std::string &txId, uint64_t amount)
|
||||||
emit m_wallet->moneySpent(qTxId, amount);
|
emit m_wallet->moneySpent(qTxId, amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WalletListenerImpl::moneyReceived(const std::string &txId, uint64_t amount)
|
void WalletListenerImpl::moneyReceived(const std::string &txId, uint64_t amount, bool coinbase)
|
||||||
{
|
{
|
||||||
// Incoming tx included in a block.
|
// Incoming tx included in a block.
|
||||||
QString qTxId = QString::fromStdString(txId);
|
QString qTxId = QString::fromStdString(txId);
|
||||||
qDebug() << Q_FUNC_INFO << qTxId << " " << WalletManager::displayAmount(amount);
|
qDebug() << Q_FUNC_INFO << qTxId << " " << WalletManager::displayAmount(amount);
|
||||||
|
|
||||||
emit m_wallet->moneyReceived(qTxId, amount);
|
emit m_wallet->moneyReceived(qTxId, amount, coinbase);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WalletListenerImpl::unconfirmedMoneyReceived(const std::string &txId, uint64_t amount)
|
void WalletListenerImpl::unconfirmedMoneyReceived(const std::string &txId, uint64_t amount)
|
||||||
|
@ -85,7 +85,7 @@ void WalletListenerImpl::onPassphraseEntered(const QString &passphrase, bool ent
|
||||||
m_phelper.onPassphraseEntered(passphrase, enter_on_device, entry_abort);
|
m_phelper.onPassphraseEntered(passphrase, enter_on_device, entry_abort);
|
||||||
}
|
}
|
||||||
|
|
||||||
Monero::optional<std::string> WalletListenerImpl::onDevicePassphraseRequest(bool & on_device)
|
std::optional<std::string> WalletListenerImpl::onDevicePassphraseRequest(bool & on_device)
|
||||||
{
|
{
|
||||||
qDebug() << __FUNCTION__;
|
qDebug() << __FUNCTION__;
|
||||||
return m_phelper.onDevicePassphraseRequest(on_device);
|
return m_phelper.onDevicePassphraseRequest(on_device);
|
||||||
|
|
|
@ -16,7 +16,7 @@ public:
|
||||||
|
|
||||||
virtual void moneySpent(const std::string &txId, uint64_t amount) override;
|
virtual void moneySpent(const std::string &txId, uint64_t amount) override;
|
||||||
|
|
||||||
virtual void moneyReceived(const std::string &txId, uint64_t amount) override;
|
virtual void moneyReceived(const std::string &txId, uint64_t amount, bool coinbase) override;
|
||||||
|
|
||||||
virtual void unconfirmedMoneyReceived(const std::string &txId, uint64_t amount) override;
|
virtual void unconfirmedMoneyReceived(const std::string &txId, uint64_t amount) override;
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ public:
|
||||||
|
|
||||||
virtual void onPassphraseEntered(const QString &passphrase, bool enter_on_device, bool entry_abort) override;
|
virtual void onPassphraseEntered(const QString &passphrase, bool enter_on_device, bool entry_abort) override;
|
||||||
|
|
||||||
virtual Monero::optional<std::string> onDevicePassphraseRequest(bool & on_device) override;
|
virtual std::optional<std::string> onDevicePassphraseRequest(bool & on_device) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Wallet * m_wallet;
|
Wallet * m_wallet;
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "Wallet.h"
|
#include "Wallet.h"
|
||||||
|
|
||||||
#include "utils/ScopeGuard.h"
|
#include "utils/ScopeGuard.h"
|
||||||
|
#include <wallet/api/wallet2_api.h>
|
||||||
|
|
||||||
class WalletPassphraseListenerImpl : public Monero::WalletListener, public PassphraseReceiver
|
class WalletPassphraseListenerImpl : public Monero::WalletListener, public PassphraseReceiver
|
||||||
{
|
{
|
||||||
|
@ -12,7 +13,7 @@ public:
|
||||||
explicit WalletPassphraseListenerImpl(WalletManager * mgr): m_mgr(mgr), m_phelper(mgr) {}
|
explicit WalletPassphraseListenerImpl(WalletManager * mgr): m_mgr(mgr), m_phelper(mgr) {}
|
||||||
|
|
||||||
void moneySpent(const std::string &txId, uint64_t amount) override { (void)txId; (void)amount; };
|
void moneySpent(const std::string &txId, uint64_t amount) override { (void)txId; (void)amount; };
|
||||||
void moneyReceived(const std::string &txId, uint64_t amount) override { (void)txId; (void)amount; };
|
void moneyReceived(const std::string &txId, uint64_t amount, bool coinbase) override { (void)txId; (void)amount; (void)coinbase;};
|
||||||
void unconfirmedMoneyReceived(const std::string &txId, uint64_t amount) override { (void)txId; (void)amount; };
|
void unconfirmedMoneyReceived(const std::string &txId, uint64_t amount) override { (void)txId; (void)amount; };
|
||||||
void newBlock(uint64_t height) override { (void) height; };
|
void newBlock(uint64_t height) override { (void) height; };
|
||||||
void updated() override {};
|
void updated() override {};
|
||||||
|
@ -24,7 +25,7 @@ public:
|
||||||
m_phelper.onPassphraseEntered(passphrase, enter_on_device, entry_abort);
|
m_phelper.onPassphraseEntered(passphrase, enter_on_device, entry_abort);
|
||||||
}
|
}
|
||||||
|
|
||||||
Monero::optional<std::string> onDevicePassphraseRequest(bool & on_device) override
|
std::optional<std::string> onDevicePassphraseRequest(bool & on_device) override
|
||||||
{
|
{
|
||||||
qDebug() << __FUNCTION__;
|
qDebug() << __FUNCTION__;
|
||||||
return m_phelper.onDevicePassphraseRequest(on_device);
|
return m_phelper.onDevicePassphraseRequest(on_device);
|
||||||
|
@ -312,6 +313,7 @@ WalletManager::WalletManager(QObject *parent)
|
||||||
|
|
||||||
WalletManager::~WalletManager()
|
WalletManager::~WalletManager()
|
||||||
{
|
{
|
||||||
|
qDebug() << "~WalletManager" << QThread::currentThreadId();
|
||||||
m_scheduler.shutdownWaitForFinished();
|
m_scheduler.shutdownWaitForFinished();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue