Compare commits
496 Commits
v0.4.4-beta2
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 1998d79c3e | |||
| ea4d5a9132 | |||
| 585f7b9d05 | |||
| b7c707bd4e | |||
| b57d2c338c | |||
| 28069fc84b | |||
| d7ec62cdbe | |||
| 244fc7acaa | |||
| 3716330ac7 | |||
| c4e7f6e0f0 | |||
| c0862ea66e | |||
| 67b41240d2 | |||
| 16110603a1 | |||
| 83934efaad | |||
| 6fb167308c | |||
| d6f95156bc | |||
| 35804afc90 | |||
| bc59547714 | |||
| f2b6068d8b | |||
| c820967cba | |||
| eadaa21e83 | |||
| 465b384195 | |||
| 768ca26a8d | |||
| 6fb131a52b | |||
| 3f18c388f6 | |||
| 2f646cdc10 | |||
| a5523be459 | |||
| 81d322b2ce | |||
| 3b1a939417 | |||
| a4e7ebc591 | |||
| 25dccd5423 | |||
| d05ac7f44e | |||
| 35b1a03b3d | |||
| 7acf8068ea | |||
| 383f3d36e6 | |||
| 7d06436d08 | |||
| 3bee380b18 | |||
| 58c70115f2 | |||
| 6be4081332 | |||
| 538e4a5d1f | |||
| 3e49572539 | |||
| 05c7152ad5 | |||
| 8d31fa2842 | |||
| 2abe39f178 | |||
| a6f47a9f92 | |||
| ac13287c78 | |||
| 305b92909e | |||
| 248667016a | |||
| 10b58aac73 | |||
| 0221fe8a34 | |||
| 1ff480e64d | |||
| fd121aae19 | |||
| 0deb19c53c | |||
| 7f3e389d92 | |||
| 87da2d4661 | |||
| f6075ae9ec | |||
| c424e84f4b | |||
| 3b4efe9636 | |||
| dfa27e78c6 | |||
| 9b57fe3eae | |||
| 8f60758a3c | |||
| 3a7ec4db32 | |||
| 679bc9f0d7 | |||
| 362eb38ff8 | |||
| 6243e992cf | |||
| e872414d57 | |||
| fcaf640bcb | |||
| f5237ceaf5 | |||
| 1503ec6629 | |||
| 0f744520ad | |||
| caf52cca20 | |||
| 1c4309c400 | |||
| 9725b921a5 | |||
| 38d2515dc5 | |||
| 13efd79f88 | |||
| 0c273d3571 | |||
| d22389b37a | |||
| f9b060e552 | |||
| 7d13f90e4a | |||
| f7a75a4fdc | |||
| b9fa97daad | |||
| 6f0f5b5e83 | |||
| 6fbd3184b1 | |||
| d5fee31ec6 | |||
| 2a93e04180 | |||
| b902ec9406 | |||
| e3ba570fb1 | |||
| fac65e5093 | |||
| eebc1f1d26 | |||
| 502ece5ba3 | |||
| 62967db201 | |||
| 4b7f863c71 | |||
| 55a6f17c91 | |||
| 8a32d7f73b | |||
| dfb6a705ea | |||
| 5246138398 | |||
| cc3e6a0822 | |||
| 8e68f58eff | |||
| 0a79a4d9fd | |||
| 48fb95bdc1 | |||
| bb4d3768b2 | |||
| cea3f0f341 | |||
| 35fc88c0ec | |||
| 312413aeb0 | |||
| 6ba060e116 | |||
| 88d5e1f50e | |||
| 644a8d3b4d | |||
| e80d135c15 | |||
| a40026f941 | |||
| fb25a36bf2 | |||
| 6f3f7c8e9a | |||
| c6c35d5639 | |||
| 63433cc58f | |||
| 940c0e03f7 | |||
| 445e498fbf | |||
| 09ad75f0cc | |||
| f8d9f9335e | |||
| cd31dafa97 | |||
| 6aa32701b8 | |||
| f84a622bfa | |||
| f60b7209f8 | |||
| 3b00a41fff | |||
| 119a7fab57 | |||
| 6d0a4a4d7b | |||
| 45404ecc71 | |||
| e5bfc2f6ad | |||
| c5be51053a | |||
| 4bfb5f51bf | |||
| d7a9facee9 | |||
| 260bc3721b | |||
| 3e0457de09 | |||
| ce6f6e0593 | |||
| f1efb700d2 | |||
| dd246296b9 | |||
| 22334d7c6c | |||
| c07698fcc8 | |||
| ce69272638 | |||
| 2b95d100b3 | |||
| b7706d4def | |||
| 845d46d7b3 | |||
| e4f8929f2c | |||
| c03402d525 | |||
| d8b18b17f6 | |||
| 5347266ed9 | |||
| 419c26adbf | |||
| 7727bdb51e | |||
| 37a58646fd | |||
| 0e747e3f15 | |||
| caf8a0a962 | |||
| 1b60c08dce | |||
| 1667514896 | |||
| 041cd03098 | |||
| 0c4998b091 | |||
| 7f25459169 | |||
| 91814ebfd9 | |||
| 7b3e8007c8 | |||
| 141761957d | |||
| b2ab2f606c | |||
| 40f0420e02 | |||
| 44e54ad555 | |||
| 69407ed8a5 | |||
| 13ee838f3c | |||
| ec33664734 | |||
| bfe8c4606d | |||
| a159bed3ba | |||
| 52f2065db4 | |||
| 0fd570a2c4 | |||
| 7df7f2740d | |||
| 458af34c67 | |||
| 21a3f5ca6f | |||
| bc7a797b71 | |||
| 9e888834e7 | |||
| 9709fad4d6 | |||
| 906e55f87b | |||
| 92812621be | |||
| 82b14a776f | |||
| 54a33225a2 | |||
| d7584de579 | |||
| a4c0d85bbb | |||
| 609615779c | |||
| b9364b5749 | |||
| 7cd7bef3ca | |||
| 80bd2d1ff0 | |||
| cbe84499fb | |||
| a8ee0a90e0 | |||
| c9de861216 | |||
| 0239202f09 | |||
| 2dd6208a80 | |||
| 37594fe8fa | |||
| e5c9b05ed6 | |||
| 9ba621b3ae | |||
| 9e20133ed9 | |||
| 9c11200666 | |||
| 3e0649a8d2 | |||
| b87bfe002a | |||
| f2e69594a7 | |||
| 7b39504050 | |||
| eff99e9287 | |||
| 6f8fcdab03 | |||
| c7a739d885 | |||
| 608962068a | |||
| e7615b4c08 | |||
| 5fa5ff8585 | |||
| 28a9338ab7 | |||
| 1d3747e9cd | |||
| c1c70ddace | |||
| 7ea690614e | |||
| 2909fd2505 | |||
| 7dd5450419 | |||
| e3a03e9d98 | |||
| dd39f94ca6 | |||
| 78232ff3a8 | |||
| aa02928620 | |||
| 52736ea0a3 | |||
| b7cc8e8100 | |||
| 520d4b4eab | |||
| 11a296acde | |||
| 8b1796147a | |||
| bf9d0e837e | |||
| a9301f5573 | |||
| e6e644e600 | |||
| 130975cebd | |||
| 5306d4b94a | |||
| 14a6c6b8ef | |||
| 2b31c8ad69 | |||
| ae02dcbe9a | |||
| e235199ff3 | |||
| 87ceee6c2d | |||
| 41e3e85159 | |||
| b570a4938c | |||
| cbde471d91 | |||
| 1e81092e59 | |||
| 65db5c3782 | |||
| a289de023a | |||
| cad1618bbd | |||
| d53a0669c9 | |||
| adcb66d268 | |||
| ec2015e5a4 | |||
| d163d6892c | |||
| 8eac4bce5f | |||
| ea19899914 | |||
| 7fe9ee0990 | |||
| c8314f7b56 | |||
| b07d2ce901 | |||
| 474bca538b | |||
| a958bdb0e0 | |||
| 1adc1b0f8d | |||
| f7be7b843b | |||
| 3878e389fe | |||
| a3a05a24e4 | |||
| 1bf4f40b79 | |||
| 4a909bda2d | |||
| 6f6a17d923 | |||
| d1b7abfc69 | |||
| 33535531ec | |||
| bd34433be2 | |||
| daffdd764b | |||
| 4942f848f8 | |||
| fa3ecd03df | |||
| 9c08143015 | |||
| 9c2fa466a0 | |||
| 4ee14df3c6 | |||
| c4ca673074 | |||
| 724e2739d4 | |||
| d483b9872b | |||
| f2f21a49b1 | |||
| 5f6122d045 | |||
| 53db771c35 | |||
| 59b167f0f3 | |||
| 60b3f22376 | |||
| e3e35f6dde | |||
| c145285dcf | |||
| 2550591cf1 | |||
| 18ec1c331b | |||
| 0520fc4fe6 | |||
| f5729a6109 | |||
| da99d88bce | |||
| 87be655738 | |||
| 7a05f26810 | |||
| 96fff8abc3 | |||
| f1e48c9094 | |||
| 02e8fea2fe | |||
| 266c41aeab | |||
| 410a9313dc | |||
| 870203e6fe | |||
| 8f699871d3 | |||
| 650b6b8bd4 | |||
| 19593db002 | |||
| d89d20ab0e | |||
| b982d4c5a6 | |||
| c4dbc4ea7b | |||
| 29f9a4d679 | |||
| 8ad1727ea7 | |||
| 79429b6870 | |||
| 1057317147 | |||
| c79e9d0e71 | |||
| d4a61dbb66 | |||
| 4989c4cece | |||
| 818aac3c73 | |||
| 04208fdcd3 | |||
| 673661bdb9 | |||
| b7ea8d0b22 | |||
| 70bde9353b | |||
| 0bfa68beda | |||
| 4a0242d905 | |||
| 1ee4d3d66e | |||
| c72543bb63 | |||
| ec46d14fe5 | |||
| fa0a05a01c | |||
| 3cc4bb2b9a | |||
| 89c60d57ec | |||
| 606cdd43f2 | |||
| 1f3255e1e8 | |||
| 8f4ceba0cc | |||
| 88e104423f | |||
| 09b886b324 | |||
| 4d891d61c1 | |||
| c4dc67cfc5 | |||
| b7488f7735 | |||
| 871a687b52 | |||
| 149a22bee1 | |||
| 9ca8361824 | |||
| 29f9451b27 | |||
| f7c2cc6550 | |||
| 3b671cb0bf | |||
| e1d3086a24 | |||
| b259bc45e8 | |||
| 638034c35f | |||
| 66552f14ca | |||
| 7d4122151e | |||
| 4659b6b6f1 | |||
| b529887e88 | |||
| c607f23a60 | |||
| 3a21213153 | |||
| 2194b853d5 | |||
| 24f9916287 | |||
| ce9c845d26 | |||
| fec249d598 | |||
| ff85622450 | |||
| a204844b8e | |||
| 154806402b | |||
| ee263314ef | |||
| cc83158ccc | |||
| ad1eb77d50 | |||
| 316aacbc62 | |||
| d9846bba74 | |||
| c69c3e35fd | |||
| 13793610af | |||
| 4eecccee04 | |||
| 939fd068c5 | |||
| 4f33613628 | |||
| 33aa5607a4 | |||
| 4eb13de957 | |||
| ada1fa0e5e | |||
| 164985ce16 | |||
| a6733fcf2b | |||
| 44e70b4765 | |||
| 22cc08c107 | |||
| ed030081b7 | |||
| 9292f88a57 | |||
| 4095e9f80f | |||
| 02fd790788 | |||
| 6d2960612f | |||
| 2d9b302137 | |||
| a7753897b2 | |||
| fe3297271f | |||
| 9d9471d314 | |||
| 5da798a7c5 | |||
| 0f97ec9ea7 | |||
| 0418bfee30 | |||
| cd22e55296 | |||
| 488d5f1e9b | |||
| 771b8ea606 | |||
| 28262a30fe | |||
| aa4276c39e | |||
| 1f49c178ee | |||
| f087b3807b | |||
| cb6cdac603 | |||
| 082976a3f0 | |||
| 420824005e | |||
| 98ded9b9c4 | |||
| 9baeb750ac | |||
| 1cf81058b6 | |||
| 9570c7a910 | |||
| 23756691b7 | |||
| d5f6cdc0cd | |||
| 378ec75a6e | |||
| 3eb986fc51 | |||
| b713a08a81 | |||
| 5bd079af4a | |||
| cd2c7c939c | |||
| 2f707e30c6 | |||
| f9726354b8 | |||
| fcd78eea7e | |||
| db740fa037 | |||
| 5971f39e7a | |||
| 02f2eb5ee9 | |||
| 02ef77bbcc | |||
| aa64124c28 | |||
| bc7db51f03 | |||
| 6889321361 | |||
| 3cb473132e | |||
| b298f542a6 | |||
| eb9f799b8b | |||
| 8bf35db67e | |||
| aeef1a6677 | |||
| ee586a3fca | |||
| 19be3a6146 | |||
| 64a69268fe | |||
| 7312652540 | |||
| 8cd587ec54 | |||
| 62c43a4ed2 | |||
| 0180051a8c | |||
| a7c1ba652b | |||
| 2a4d08b67f | |||
| 3fc5ea3543 | |||
| 3b72dc0555 | |||
| b48c86afe0 | |||
| 0f88d91fa0 | |||
| f4612357b2 | |||
| e9a2b6fbb7 | |||
| ca2069facc | |||
| 114297d784 | |||
| 6368aee05f | |||
| 8599cdf95b | |||
| d39f2f180e | |||
| c763febe98 | |||
| cef01372b1 | |||
| e15dbb5db2 | |||
| 82d706aacb | |||
| f3522764a1 | |||
| 0448a6bf9a | |||
| 2ce22c2508 | |||
| 1334bac45a | |||
| e909e3eef1 | |||
| 4b594142ca | |||
| 29e435bd39 | |||
| 4abde92c1a | |||
| dd23331df9 | |||
| 7d2025bc19 | |||
| a01422a5e0 | |||
| e68f7f46ed | |||
| b87c243da1 | |||
| 49fd907073 | |||
| 8c999520d1 | |||
| 945bdc72e7 | |||
| c6d843b6f5 | |||
| 8f5111aeda | |||
| b285ec550d | |||
| afc2518ef7 | |||
| a9406b158d | |||
| e45643e157 | |||
| 1df18ca6a4 | |||
| 91b2ec275a | |||
| e45fdb863c | |||
| cb2f9d3f75 | |||
| 59025bb27b | |||
| 204c6fc778 | |||
| 78c2b4b1fb | |||
| fcac456902 | |||
| 1824a34a68 | |||
| 1786c628bf | |||
| 6b8df3cee5 | |||
| 884db2b499 | |||
| ce7a1bdd96 | |||
| 57cbb146db | |||
| 85c856411e | |||
| 6fefb49da0 | |||
| c5c828516b | |||
| 218911d9fc | |||
| da3ef2511d | |||
| 8b2b039036 | |||
| 4d1c84fcaf | |||
| bb91b01cf7 | |||
| 7f0eda828a | |||
| d3f15211d7 | |||
| b828703bbd | |||
| 2fa8ef97ef | |||
| acb3af43f0 | |||
| d1eed6e9ff | |||
| 30a2931067 | |||
| 1c73dd0c9f | |||
| 1c84c00fe6 | |||
| 7abf28d87c | |||
| ea919eb6ea | |||
| 42aee311cd | |||
| d51ca28d7b | |||
| 77683cafa1 | |||
| e193d141bf | |||
| c248b78831 | |||
| 6b75cb1fb5 | |||
| a926092d9a | |||
| 6d8e925fdb | |||
| 0ee3c669d6 | |||
| addd26cd47 | |||
| 9e96fcfe3a |
@@ -0,0 +1,127 @@
|
||||
name: ci/gh-actions/depends
|
||||
|
||||
on:
|
||||
push:
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
- '**/README.md'
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- 'docs/**'
|
||||
- '**/README.md'
|
||||
|
||||
env:
|
||||
APT_SET_CONF: |
|
||||
echo "Acquire::Retries \"3\";" | sudo tee -a /etc/apt/apt.conf.d/80-custom
|
||||
echo "Acquire::http::Timeout \"120\";" | sudo tee -a /etc/apt/apt.conf.d/80-custom
|
||||
echo "Acquire::ftp::Timeout \"120\";" | sudo tee -a /etc/apt/apt.conf.d/80-custom
|
||||
CCACHE_SETTINGS: |
|
||||
ccache --max-size=150M
|
||||
ccache --set-config=compression=true
|
||||
USE_DEVICE_TREZOR_MANDATORY: ON
|
||||
|
||||
jobs:
|
||||
build-cross:
|
||||
runs-on: ubuntu-22.04
|
||||
env:
|
||||
CCACHE_TEMPDIR: /tmp/.ccache-temp
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
toolchain:
|
||||
- name: "RISCV 64bit"
|
||||
host: "riscv64-linux-gnu"
|
||||
packages: "python3 gperf g++-riscv64-linux-gnu"
|
||||
- name: "ARM v7"
|
||||
host: "arm-linux-gnueabihf"
|
||||
packages: "python3 gperf g++-arm-linux-gnueabihf"
|
||||
- name: "ARM v8"
|
||||
host: "aarch64-linux-gnu"
|
||||
packages: "python3 gperf g++-aarch64-linux-gnu"
|
||||
- name: "i686 Win"
|
||||
host: "i686-w64-mingw32"
|
||||
packages: "python3 g++-mingw-w64-i686"
|
||||
- name: "i686 Linux"
|
||||
host: "i686-pc-linux-gnu"
|
||||
packages: "gperf cmake g++-multilib python3-zmq"
|
||||
- name: "Win64"
|
||||
host: "x86_64-w64-mingw32"
|
||||
packages: "cmake python3 g++-mingw-w64-x86-64"
|
||||
- name: "x86_64 Linux"
|
||||
host: "x86_64-unknown-linux-gnu"
|
||||
packages: "gperf cmake python3-zmq libdbus-1-dev libharfbuzz-dev"
|
||||
- name: "Cross-Mac x86_64"
|
||||
host: "x86_64-apple-darwin"
|
||||
packages: "cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools python3-dev python3-setuptools-git"
|
||||
- name: "Cross-Mac aarch64"
|
||||
host: "aarch64-apple-darwin"
|
||||
packages: "cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools python3-dev python3-setuptools-git"
|
||||
- name: "x86_64 Freebsd"
|
||||
host: "x86_64-unknown-freebsd"
|
||||
packages: "clang-8 gperf cmake python3-zmq libdbus-1-dev libharfbuzz-dev"
|
||||
# - name: "ARMv8 Android"
|
||||
# host: "aarch64-linux-android"
|
||||
# packages: "gperf cmake python3"
|
||||
name: ${{ matrix.toolchain.name }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: recursive
|
||||
# Most volatile cache
|
||||
- name: ccache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ccache-${{ matrix.toolchain.host }}-${{ github.sha }}
|
||||
restore-keys: ccache-${{ matrix.toolchain.host }}-
|
||||
# Less volatile cache
|
||||
- name: depends cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: contrib/depends/built
|
||||
key: depends-${{ matrix.toolchain.host }}-${{ hashFiles('contrib/depends/packages/*') }}
|
||||
restore-keys: |
|
||||
depends-${{ matrix.toolchain.host }}-${{ hashFiles('contrib/depends/packages/*') }}
|
||||
depends-${{ matrix.toolchain.host }}-
|
||||
# Static cache
|
||||
- name: OSX SDK cache
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: contrib/depends/sdk-sources
|
||||
key: sdk-${{ matrix.toolchain.host }}-${{ matrix.toolchain.osx_sdk }}
|
||||
restore-keys: sdk-${{ matrix.toolchain.host }}-${{ matrix.toolchain.osx_sdk }}
|
||||
- name: set apt conf
|
||||
run: ${{env.APT_SET_CONF}}
|
||||
- name: install dependencies
|
||||
run: sudo apt update; sudo apt -y install build-essential libtool libssl-dev cmake autotools-dev automake pkg-config bsdmainutils curl git ca-certificates ccache ${{ matrix.toolchain.packages }}
|
||||
- name: prepare w64-mingw32
|
||||
if: ${{ matrix.toolchain.host == 'x86_64-w64-mingw32' || matrix.toolchain.host == 'i686-w64-mingw32' }}
|
||||
run: |
|
||||
sudo update-alternatives --set ${{ matrix.toolchain.host }}-g++ $(which ${{ matrix.toolchain.host }}-g++-posix)
|
||||
sudo update-alternatives --set ${{ matrix.toolchain.host }}-gcc $(which ${{ matrix.toolchain.host }}-gcc-posix)
|
||||
- name: build
|
||||
run: |
|
||||
${{env.CCACHE_SETTINGS}}
|
||||
make depends target=${{ matrix.toolchain.host }} -j2
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: ${{ matrix.toolchain.host == 'x86_64-w64-mingw32' || matrix.toolchain.host == 'x86_64-apple-darwin' || matrix.toolchain.host == 'aarch64-apple-darwin' || matrix.toolchain.host == 'x86_64-unknown-linux-gnu' || matrix.toolchain.host == 'aarch64-linux-gnu' }}
|
||||
with:
|
||||
name: ${{ matrix.toolchain.name }}
|
||||
path: |
|
||||
/home/runner/work/${{ github.event.repository.name }}/${{ github.event.repository.name }}/build/${{ matrix.toolchain.host }}/release/bin/salvium-wallet-*
|
||||
/home/runner/work/${{ github.event.repository.name }}/${{ github.event.repository.name }}/build/${{ matrix.toolchain.host }}/release/bin/salviumd*
|
||||
- name: zip daemon & cli
|
||||
run: |
|
||||
zip salvium-${GITHUB_REF_NAME}-${{ matrix.toolchain.host }}.zip /home/runner/work/${{ github.event.repository.name }}/${{ github.event.repository.name }}/build/${{ matrix.toolchain.host }}/release/bin/salvium-wallet-rpc* /home/runner/work/${{ github.event.repository.name }}/${{ github.event.repository.name }}/build/${{ matrix.toolchain.host }}/release/bin/salvium-wallet-cli* /home/runner/work/${{ github.event.repository.name }}/${{ github.event.repository.name }}/build/${{ matrix.toolchain.host }}/release/bin/salviumd*
|
||||
ls -l
|
||||
- name: "Deploy"
|
||||
uses: keithweaver/aws-s3-github-action@v1.0.0
|
||||
with:
|
||||
command: cp
|
||||
source: ./salvium-${{ github.ref_name }}-${{ matrix.toolchain.host }}.zip
|
||||
destination: s3://${{ vars.S3_BUCKET }}/salvium-${{ github.ref_name }}-${{ matrix.toolchain.host }}.zip
|
||||
aws_access_key_id: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
||||
aws_secret_access_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws_region: eu-west-1
|
||||
flags: --acl public-read
|
||||
@@ -30,6 +30,9 @@ contrib/gitian/builder/
|
||||
contrib/gitian/docker/
|
||||
contrib/gitian/sigs/
|
||||
|
||||
# Audit tool
|
||||
src/blockchain_utilities/blockchain_audit.cpp
|
||||
|
||||
# Created by https://www.gitignore.io
|
||||
|
||||
### C++ ###
|
||||
|
||||
@@ -14,3 +14,6 @@
|
||||
[submodule "external/miniupnp"]
|
||||
path = external/miniupnp
|
||||
url = https://github.com/miniupnp/miniupnp
|
||||
[submodule "external/mx25519"]
|
||||
path = external/mx25519
|
||||
url = https://github.com/tevador/mx25519
|
||||
|
||||
+22
-6
@@ -372,6 +372,7 @@ if(NOT MANUAL_SUBMODULES)
|
||||
check_submodule(external/trezor-common)
|
||||
check_submodule(external/randomx)
|
||||
check_submodule(external/supercop)
|
||||
check_submodule(external/mx25519)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -458,7 +459,7 @@ elseif(CMAKE_SYSTEM_NAME MATCHES ".*BSDI.*")
|
||||
set(BSDI TRUE)
|
||||
endif()
|
||||
|
||||
include_directories(external/rapidjson/include external/easylogging++ src contrib/epee/include external external/supercop/include)
|
||||
include_directories(external/rapidjson/include external/easylogging++ src contrib/epee/include external external/supercop/include external/mx25519/include)
|
||||
|
||||
if(APPLE)
|
||||
cmake_policy(SET CMP0042 NEW)
|
||||
@@ -506,6 +507,7 @@ if(STATIC)
|
||||
set(CMAKE_FIND_LIBRARY_SUFFIXES .a ${CMAKE_FIND_LIBRARY_SUFFIXES})
|
||||
endif()
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DZMQ_STATIC")
|
||||
add_definitions("-DMX25519_STATIC")
|
||||
endif()
|
||||
|
||||
option(SANITIZE "Use ASAN memory sanitizer" OFF)
|
||||
@@ -531,7 +533,7 @@ add_definitions("-DBLOCKCHAIN_DB=${BLOCKCHAIN_DB}")
|
||||
# Can't install hook in static build on OSX, because OSX linker does not support --wrap
|
||||
# On ARM, having libunwind package (with .so's only) installed breaks static link.
|
||||
# When possible, avoid stack tracing using libunwind in favor of using easylogging++.
|
||||
if (APPLE OR NETBSD)
|
||||
if (APPLE)
|
||||
set(DEFAULT_STACK_TRACE OFF)
|
||||
set(LIBUNWIND_LIBRARIES "")
|
||||
elseif (DEPENDS AND NOT LINUX)
|
||||
@@ -1084,6 +1086,10 @@ endif()
|
||||
find_package(Boost 1.58 QUIET REQUIRED COMPONENTS ${BOOST_COMPONENTS})
|
||||
add_definitions(-DBOOST_ASIO_ENABLE_SEQUENTIAL_STRAND_ALLOCATION)
|
||||
add_definitions(-DBOOST_NO_AUTO_PTR)
|
||||
add_definitions(-DBOOST_UUID_DISABLE_ALIGNMENT) # This restores UUID's std::has_unique_object_representations property
|
||||
# Boost has two conflicting save/load impls for `std::variant`, one in serialization/variant.hpp,
|
||||
# and one in serialization/std_variant.hpp. This macro disables the one in variant.hpp.
|
||||
add_definitions(-DBOOST_NO_CXX17_HDR_VARIANT)
|
||||
|
||||
set(CMAKE_FIND_LIBRARY_SUFFIXES ${OLD_LIB_SUFFIXES})
|
||||
if(NOT Boost_FOUND)
|
||||
@@ -1107,7 +1113,9 @@ include_directories(SYSTEM ${Boost_INCLUDE_DIRS})
|
||||
if(MINGW)
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wa,-mbig-obj")
|
||||
set(EXTRA_LIBRARIES mswsock;ws2_32;iphlpapi;crypt32;bcrypt)
|
||||
if(NOT DEPENDS)
|
||||
if(DEPENDS)
|
||||
set(ICU_LIBRARIES icuio icui18n icuuc icudata icutu iconv)
|
||||
else()
|
||||
set(ICU_LIBRARIES icuio icuin icuuc icudt icutu iconv)
|
||||
endif()
|
||||
elseif(APPLE OR OPENBSD OR ANDROID)
|
||||
@@ -1182,7 +1190,6 @@ endif()
|
||||
if(STATIC)
|
||||
set(sodium_USE_STATIC_LIBS ON)
|
||||
endif()
|
||||
find_package(Sodium REQUIRED)
|
||||
|
||||
find_path(ZMQ_INCLUDE_PATH zmq.h)
|
||||
find_library(ZMQ_LIB zmq)
|
||||
@@ -1190,6 +1197,7 @@ find_library(PGM_LIBRARY pgm)
|
||||
find_library(NORM_LIBRARY norm)
|
||||
find_library(GSSAPI_LIBRARY gssapi_krb5)
|
||||
find_library(PROTOLIB_LIBRARY protolib)
|
||||
find_library(SODIUM_LIBRARY sodium)
|
||||
find_library(BSD_LIBRARY bsd)
|
||||
find_library(MD_LIBRARY md)
|
||||
find_library(PROTOKIT_LIBRARY protokit)
|
||||
@@ -1212,8 +1220,16 @@ endif()
|
||||
if(PROTOLIB_LIBRARY)
|
||||
set(ZMQ_LIB "${ZMQ_LIB};${PROTOLIB_LIBRARY}")
|
||||
endif()
|
||||
if(Sodium_FOUND)
|
||||
set(ZMQ_LIB "${ZMQ_LIB};${sodium_LIBRARIES}")
|
||||
if(SODIUM_LIBRARY)
|
||||
message(STATUS "ZMQ_LIB: ${ZMQ_LIB};${SODIUM_LIBRARY}")
|
||||
set(ZMQ_LIB "${ZMQ_LIB};${SODIUM_LIBRARY}")
|
||||
find_path(SODIUM_INCLUDE_PATH sodium/crypto_verify_32.h)
|
||||
if (SODIUM_INCLUDE_PATH)
|
||||
message(STATUS "SODIUM_INCLUDE_PATH: ${SODIUM_INCLUDE_PATH}")
|
||||
include_directories(${SODIUM_INCLUDE_PATH})
|
||||
else()
|
||||
message(FATAL_ERROR "Could not find required sodium/crypto_verify_32.h")
|
||||
endif()
|
||||
endif()
|
||||
if(BSD_LIBRARY)
|
||||
set(ZMQ_LIB "${ZMQ_LIB};${BSD_LIBRARY}")
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
# Use Ubuntu 24.04 as base
|
||||
FROM ubuntu:24.04 AS builder
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
# Install build dependencies including cross-compilers
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
build-essential cmake pkg-config git imagemagick libcap-dev librsvg2-bin libz-dev \
|
||||
g++-mingw-w64-x86-64 clang gcc-arm-none-eabi binutils-x86-64-linux-gnu libtiff-tools \
|
||||
g++-x86-64-linux-gnu gcc-x86-64-linux-gnu binutils-aarch64-linux-gnu \
|
||||
g++-aarch64-linux-gnu gcc-aarch64-linux-gnu crossbuild-essential-amd64 \
|
||||
libssl-dev libzmq3-dev libunbound-dev libsodium-dev libunwind8-dev liblzma-dev \
|
||||
libreadline-dev libexpat1-dev libpgm-dev qttools5-dev-tools libhidapi-dev libusb-1.0-0-dev \
|
||||
libprotobuf-dev protobuf-compiler libudev-dev libboost-all-dev python3 ccache doxygen graphviz \
|
||||
ca-certificates curl zip libtool gperf automake autoconf \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Clone the develop branch
|
||||
WORKDIR /opt
|
||||
RUN git clone --recursive -b develop https://github.com/salvium/salvium.git
|
||||
WORKDIR /opt/salvium
|
||||
|
||||
# make the script runnable
|
||||
RUN chmod +x make_releases.sh
|
||||
|
||||
# Make sure the output folder exists
|
||||
RUN mkdir ~/releases
|
||||
|
||||
# Expose the releases directory for copying zip files to the host
|
||||
VOLUME ["~/releases"]
|
||||
|
||||
ENTRYPOINT ["/opt/salvium/make_releases.sh"]
|
||||
|
||||
|
||||
# To access the generated zip files on your host, run the container with:
|
||||
# docker run -v ~/releases:/root/releases <image>
|
||||
# This will copy the zip files to your host's ~/salvium-releases directory.
|
||||
@@ -1,6 +1,6 @@
|
||||
# Salvium Zero v0.4.1
|
||||
# Salvium One v1.1.1
|
||||
|
||||
Copyright (c) 2023-2024, Salvium
|
||||
Copyright (c) 2023-2025, Salvium
|
||||
Portions Copyright (c) 2014-2023, The Monero Project
|
||||
Portions Copyright (c) 2012-2013 The Cryptonote developers.
|
||||
|
||||
@@ -47,7 +47,7 @@ As with many development projects, the repository on GitHub is considered to be
|
||||
|
||||
## Supporting the project
|
||||
|
||||
Salvium is a 100% community-sponsored endeavor. If you want to join our efforts, the easiest thing you can do is support the project financially. Go to [https://salvium.io/donate/](https://salvium.io/donate/) for more information.
|
||||
Salvium is a 100% community-sponsored endeavor. If you want to join our efforts, the easiest thing you can do is support the project financially. Go to [https://salvium.io/donate](https://salvium.io/donate) for more information.
|
||||
|
||||
## License
|
||||
|
||||
@@ -172,7 +172,7 @@ invokes cmake commands as needed.
|
||||
|
||||
```bash
|
||||
cd salvium
|
||||
git checkout release-v0.18
|
||||
git checkout v1.1.1
|
||||
make
|
||||
```
|
||||
|
||||
@@ -251,7 +251,7 @@ Tested on a Raspberry Pi Zero with a clean install of minimal Raspbian Stretch (
|
||||
```bash
|
||||
git clone https://github.com/salvium/salvium
|
||||
cd salvium
|
||||
git checkout v0.4.1
|
||||
git checkout v1.1.1
|
||||
```
|
||||
|
||||
* Build:
|
||||
@@ -370,10 +370,10 @@ application.
|
||||
cd salvium
|
||||
```
|
||||
|
||||
* If you would like a specific [version/tag](https://github.com/salvium/salvium/tags), do a git checkout for that version. eg. 'v0.4.1'. If you don't care about the version and just want binaries from master, skip this step:
|
||||
* If you would like a specific [version/tag](https://github.com/salvium/salvium/tags), do a git checkout for that version. eg. 'v1.1.1'. If you don't care about the version and just want binaries from master, skip this step:
|
||||
|
||||
```bash
|
||||
git checkout v0.4.1
|
||||
git checkout v1.1.1
|
||||
```
|
||||
|
||||
* If you are on a 64-bit system, run:
|
||||
|
||||
@@ -6,7 +6,7 @@ macro(CHECK_LINKER_FLAG flag VARIABLE)
|
||||
message(STATUS "Looking for ${flag} linker flag")
|
||||
endif()
|
||||
|
||||
set(_cle_source ${CMAKE_SOURCE_DIR}/cmake/CheckLinkerFlag.c)
|
||||
set(_cle_source ${CMAKE_CURRENT_SOURCE_DIR}/cmake/CheckLinkerFlag.c)
|
||||
|
||||
set(saved_CMAKE_C_FLAGS ${CMAKE_C_FLAGS})
|
||||
set(CMAKE_C_FLAGS "${flag}")
|
||||
|
||||
@@ -6,10 +6,10 @@ function(_trezor_default_val val_name val_default)
|
||||
endfunction()
|
||||
|
||||
# Define default options via env vars
|
||||
_trezor_default_val(USE_DEVICE_TREZOR ON)
|
||||
_trezor_default_val(USE_DEVICE_TREZOR OFF)
|
||||
_trezor_default_val(USE_DEVICE_TREZOR_MANDATORY OFF)
|
||||
_trezor_default_val(USE_DEVICE_TREZOR_PROTOBUF_TEST ON)
|
||||
_trezor_default_val(USE_DEVICE_TREZOR_LIBUSB ON)
|
||||
_trezor_default_val(USE_DEVICE_TREZOR_PROTOBUF_TEST OFF)
|
||||
_trezor_default_val(USE_DEVICE_TREZOR_LIBUSB OFF)
|
||||
_trezor_default_val(USE_DEVICE_TREZOR_UDP_RELEASE OFF)
|
||||
_trezor_default_val(USE_DEVICE_TREZOR_DEBUG OFF)
|
||||
_trezor_default_val(TREZOR_DEBUG OFF)
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
depends_prefix="`dirname ${ac_site_file}`/.."
|
||||
|
||||
cross_compiling=maybe
|
||||
host_alias=@HOST@
|
||||
ac_tool_prefix=${host_alias}-
|
||||
|
||||
if test -z $with_boost; then
|
||||
with_boost=$depends_prefix
|
||||
fi
|
||||
|
||||
if test x@host_os@ = xdarwin; then
|
||||
BREW=no
|
||||
PORT=no
|
||||
fi
|
||||
|
||||
PATH=$depends_prefix/native/bin:$PATH
|
||||
PKG_CONFIG="`which pkg-config` --static"
|
||||
|
||||
# These two need to remain exported because pkg-config does not see them
|
||||
# otherwise. That means they must be unexported at the end of configure.ac to
|
||||
# avoid ruining the cache. Sigh.
|
||||
export PKG_CONFIG_PATH=$depends_prefix/share/pkgconfig:$depends_prefix/lib/pkgconfig
|
||||
if test -z "@allow_host_packages@"; then
|
||||
export PKGCONFIG_LIBDIR=
|
||||
fi
|
||||
|
||||
CPPFLAGS="-I$depends_prefix/include/ $CPPFLAGS"
|
||||
LDFLAGS="-L$depends_prefix/lib $LDFLAGS"
|
||||
|
||||
CC="@CC@"
|
||||
CXX="@CXX@"
|
||||
OBJC="${CC}"
|
||||
CCACHE=$depends_prefix/native/bin/ccache
|
||||
PYTHONPATH=$depends_prefix/native/lib/python/dist-packages:$PYTHONPATH
|
||||
|
||||
if test -n "@AR@"; then
|
||||
AR=@AR@
|
||||
ac_cv_path_ac_pt_AR=${AR}
|
||||
fi
|
||||
|
||||
if test -n "@RANLIB@"; then
|
||||
RANLIB=@RANLIB@
|
||||
ac_cv_path_ac_pt_RANLIB=${RANLIB}
|
||||
fi
|
||||
|
||||
if test -n "@NM@"; then
|
||||
NM=@NM@
|
||||
ac_cv_path_ac_pt_NM=${NM}
|
||||
fi
|
||||
|
||||
if test -n "@debug@"; then
|
||||
enable_reduce_exports=no
|
||||
fi
|
||||
|
||||
if test -n "@CFLAGS@"; then
|
||||
CFLAGS="@CFLAGS@ $CFLAGS"
|
||||
fi
|
||||
if test -n "@CXXFLAGS@"; then
|
||||
CXXFLAGS="@CXXFLAGS@ $CXXFLAGS"
|
||||
fi
|
||||
if test -n "@CPPFLAGS@"; then
|
||||
CPPFLAGS="@CPPFLAGS@ $CPPFLAGS"
|
||||
fi
|
||||
if test -n "@LDFLAGS@"; then
|
||||
LDFLAGS="@LDFLAGS@ $LDFLAGS"
|
||||
fi
|
||||
@@ -1,4 +1,4 @@
|
||||
OSX_MIN_VERSION=10.13
|
||||
OSX_MIN_VERSION=11.0
|
||||
LD64_VERSION=609
|
||||
ifeq (aarch64, $(host_arch))
|
||||
CC_target=arm64-apple-$(host_os)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
mingw32_CFLAGS=-pipe -pthread
|
||||
mingw32_CFLAGS=-pipe
|
||||
mingw32_CXXFLAGS=$(mingw32_CFLAGS)
|
||||
mingw32_ARFLAGS=cr
|
||||
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
package=boost
|
||||
$(package)_version=1_64_0
|
||||
$(package)_download_path=https://downloads.sourceforge.net/project/boost/boost/1.64.0/
|
||||
$(package)_file_name=$(package)_$($(package)_version).tar.bz2
|
||||
$(package)_sha256_hash=7bcc5caace97baa948931d712ea5f37038dbb1c5d89b43ad4def4ed7cb683332
|
||||
$(package)_patches=fix_aroptions.patch fix_arm_arch.patch
|
||||
package=boost
|
||||
$(package)_version=1.84.0
|
||||
$(package)_download_path=https://archives.boost.io/release/$($(package)_version)/source/
|
||||
$(package)_file_name=$(package)_$(subst .,_,$($(package)_version)).tar.bz2
|
||||
$(package)_sha256_hash=cc4b893acf645c9d4b698e9a0f08ca8846aa5d6c68275c14c3e7949c24109454
|
||||
|
||||
define $(package)_set_vars
|
||||
$(package)_config_opts_release=variant=release
|
||||
$(package)_config_opts_debug=variant=debug
|
||||
$(package)_config_opts=--layout=tagged --build-type=complete --user-config=user-config.jam
|
||||
$(package)_config_opts+=--layout=system --user-config=user-config.jam variant=release
|
||||
$(package)_config_opts+=threading=multi link=static -sNO_BZIP2=1 -sNO_ZLIB=1
|
||||
$(package)_config_opts_linux=threadapi=pthread runtime-link=shared
|
||||
$(package)_config_opts_android=threadapi=pthread runtime-link=static target-os=android
|
||||
$(package)_config_opts_darwin=--toolset=darwin runtime-link=shared
|
||||
$(package)_config_opts_darwin=--toolset=darwin runtime-link=shared target-os=darwin
|
||||
$(package)_config_opts_mingw32=binary-format=pe target-os=windows threadapi=win32 runtime-link=static
|
||||
$(package)_config_opts_x86_64_mingw32=address-model=64
|
||||
$(package)_config_opts_i686_mingw32=address-model=32
|
||||
@@ -23,14 +22,13 @@ $(package)_toolset_darwin=darwin
|
||||
$(package)_archiver_darwin=$($(package)_libtool)
|
||||
$(package)_config_libraries_$(host_os)="chrono,filesystem,program_options,system,thread,test,date_time,regex,serialization"
|
||||
$(package)_config_libraries_mingw32="chrono,filesystem,program_options,system,thread,test,date_time,regex,serialization,locale"
|
||||
$(package)_cxxflags=-std=c++11
|
||||
$(package)_cxxflags_linux=-fPIC
|
||||
$(package)_cxxflags_freebsd=-fPIC
|
||||
$(package)_cxxflags=-std=c++17
|
||||
$(package)_cxxflags_linux+=-fPIC
|
||||
$(package)_cxxflags_freebsd+=-fPIC
|
||||
$(package)_cxxflags_darwin+=-ffile-prefix-map=$($(package)_extract_dir)=/usr
|
||||
endef
|
||||
|
||||
define $(package)_preprocess_cmds
|
||||
patch -p1 < $($(package)_patch_dir)/fix_aroptions.patch &&\
|
||||
patch -p1 < $($(package)_patch_dir)/fix_arm_arch.patch &&\
|
||||
echo "using $(boost_toolset_$(host_os)) : : $($(package)_cxx) : <cxxflags>\"$($(package)_cxxflags) $($(package)_cppflags)\" <linkflags>\"$($(package)_ldflags)\" <archiver>\"$(boost_archiver_$(host_os))\" <arflags>\"$($(package)_arflags)\" <striper>\"$(host_STRIP)\" <ranlib>\"$(host_RANLIB)\" <rc>\"$(host_WINDRES)\" : ;" > user-config.jam
|
||||
endef
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package=icu4c
|
||||
$(package)_version=55.2
|
||||
$(package)_download_path=https://github.com/unicode-org/icu/releases/download/release-55-2/
|
||||
$(package)_file_name=$(package)-55_2-src.tgz
|
||||
$(package)_sha256_hash=eda2aa9f9c787748a2e2d310590720ca8bcc6252adf6b4cfb03b65bef9d66759
|
||||
$(package)_patches=icu-001-dont-build-static-dynamic-twice.patch
|
||||
|
||||
define $(package)_set_vars
|
||||
$(package)_build_opts=CFLAGS="$($(package)_cflags) $($(package)_cppflags) -DU_USING_ICU_NAMESPACE=0 -DU_STATIC_IMPLEMENTATION -DU_COMBINED_IMPLEMENTATION -fPIC -DENABLE_STATIC=YES -DPGKDATA_MODE=static"
|
||||
endef
|
||||
|
||||
define $(package)_config_cmds
|
||||
patch -p1 < $($(package)_patch_dir)/icu-001-dont-build-static-dynamic-twice.patch &&\
|
||||
mkdir builda &&\
|
||||
mkdir buildb &&\
|
||||
cd builda &&\
|
||||
sh ../source/runConfigureICU Linux &&\
|
||||
make &&\
|
||||
cd ../buildb &&\
|
||||
sh ../source/runConfigureICU MinGW --enable-static=yes --disable-shared --disable-layout --disable-layoutex --disable-tests --disable-samples --prefix=$(host_prefix) --with-cross-build=`pwd`/../builda &&\
|
||||
$(MAKE) $($(package)_build_opts)
|
||||
endef
|
||||
|
||||
define $(package)_stage_cmds
|
||||
cd buildb &&\
|
||||
$(MAKE) $($(package)_build_opts) DESTDIR=$($(package)_staging_dir) install lib/*
|
||||
endef
|
||||
@@ -0,0 +1,35 @@
|
||||
package=libiconv
|
||||
$(package)_version=1.15
|
||||
$(package)_download_path=https://ftp.gnu.org/gnu/libiconv
|
||||
$(package)_file_name=libiconv-$($(package)_version).tar.gz
|
||||
$(package)_sha256_hash=ccf536620a45458d26ba83887a983b96827001e92a13847b45e4925cc8913178
|
||||
$(package)_patches=fix-whitespace.patch
|
||||
|
||||
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)_preprocess_cmds
|
||||
cp -f $(BASEDIR)/config.guess $(BASEDIR)/config.sub build-aux/ &&\
|
||||
patch -p1 < $($(package)_patch_dir)/fix-whitespace.patch
|
||||
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
|
||||
@@ -0,0 +1,25 @@
|
||||
package=native_ccache
|
||||
$(package)_version=3.3.4
|
||||
$(package)_download_path=https://samba.org/ftp/ccache
|
||||
$(package)_file_name=ccache-$($(package)_version).tar.bz2
|
||||
$(package)_sha256_hash=fa9d7f38367431bc86b19ad107d709ca7ecf1574fdacca01698bdf0a47cd8567
|
||||
|
||||
define $(package)_set_vars
|
||||
$(package)_config_opts=
|
||||
endef
|
||||
|
||||
define $(package)_config_cmds
|
||||
$($(package)_autoconf)
|
||||
endef
|
||||
|
||||
define $(package)_build_cmds
|
||||
$(MAKE)
|
||||
endef
|
||||
|
||||
define $(package)_stage_cmds
|
||||
$(MAKE) DESTDIR=$($(package)_staging_dir) install
|
||||
endef
|
||||
|
||||
define $(package)_postprocess_cmds
|
||||
rm -rf lib include
|
||||
endef
|
||||
@@ -5,17 +5,18 @@ $(package)_download_file=$($(package)_version).tar.gz
|
||||
$(package)_file_name=$(package)-$($(package)_version).tar.gz
|
||||
$(package)_sha256_hash=70a7189418c2086d20c299c5d59250cf5940782c778892ccc899c66516ed240e
|
||||
$(package)_build_subdir=cctools
|
||||
$(package)_dependencies=native_clang native_libtapi
|
||||
$(package)_patches=no-build-date.patch
|
||||
$(package)_dependencies=native_libtapi
|
||||
|
||||
define $(package)_set_vars
|
||||
$(package)_config_opts=--target=$(host) --disable-lto-support --with-libtapi=$(host_prefix)
|
||||
$(package)_ldflags+=-Wl,-rpath=\\$$$$$$$$\$$$$$$$$ORIGIN/../lib
|
||||
$(package)_cc=$(host_prefix)/native/bin/clang
|
||||
$(package)_cxx=$(host_prefix)/native/bin/clang++
|
||||
$(package)_cc=$(clang_prog)
|
||||
$(package)_cxx=$(clangxx_prog)
|
||||
endef
|
||||
|
||||
define $(package)_preprocess_cmds
|
||||
cp -f $(BASEDIR)/config.guess $(BASEDIR)/config.sub cctools && \
|
||||
patch -p1 < $($(package)_patch_dir)/no-build-date.patch
|
||||
endef
|
||||
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
package=native_clang
|
||||
$(package)_version=9.0.0
|
||||
$(package)_download_path=https://releases.llvm.org/$($(package)_version)
|
||||
$(package)_download_file=clang+llvm-$($(package)_version)-x86_64-linux-gnu-ubuntu-18.04.tar.xz
|
||||
$(package)_file_name=clang-llvm-$($(package)_version)-x86_64-linux-gnu-ubuntu-18.04.tar.xz
|
||||
$(package)_sha256_hash=a23b082b30c128c9831dbdd96edad26b43f56624d0ad0ea9edec506f5385038d
|
||||
#$(package)_version=9.0.0
|
||||
#$(package)_download_path=https://releases.llvm.org/$($(package)_version)
|
||||
#$(package)_download_file=clang+llvm-$($(package)_version)-x86_64-linux-gnu-ubuntu-18.04.tar.xz
|
||||
#$(package)_file_name=clang-llvm-$($(package)_version)-x86_64-linux-gnu-ubuntu-18.04.tar.xz
|
||||
#$(package)_sha256_hash=a23b082b30c128c9831dbdd96edad26b43f56624d0ad0ea9edec506f5385038d
|
||||
|
||||
$(package)_version=12.0.0
|
||||
$(package)_download_path=https://github.com/llvm/llvm-project/releases/download/llvmorg-$($(package)_version)
|
||||
$(package)_download_file=clang+llvm-$($(package)_version)-x86_64-linux-gnu-ubuntu-20.04.tar.xz
|
||||
$(package)_file_name=clang-llvm-$($(package)_version)-x86_64-linux-gnu-ubuntu-20.04.tar.xz
|
||||
$(package)_sha256_hash=a9ff205eb0b73ca7c86afc6432eed1c2d49133bd0d49e47b15be59bbf0dd292e
|
||||
|
||||
define $(package)_extract_cmds
|
||||
echo $($(package)_sha256_hash) $($(package)_source) | sha256sum -c &&\
|
||||
|
||||
@@ -4,30 +4,16 @@ $(package)_download_path=https://github.com/tpoechtrager/apple-libtapi/archive
|
||||
$(package)_download_file=$($(package)_version).tar.gz
|
||||
$(package)_file_name=$(package)-$($(package)_version).tar.gz
|
||||
$(package)_sha256_hash=62e419c12d1c9fad67cc1cd523132bc00db050998337c734c15bc8d73cc02b61
|
||||
$(package)_build_subdir=build
|
||||
$(package)_dependencies=native_clang
|
||||
$(package)_patches=no_embed_git_rev.patch
|
||||
|
||||
define $(package)_preprocess_cmds
|
||||
patch -p1 -i $($(package)_patch_dir)/no_embed_git_rev.patch
|
||||
endef
|
||||
|
||||
define $(package)_config_cmds
|
||||
echo -n $(build_prefix) > INSTALLPREFIX; \
|
||||
CC=$(host_prefix)/native/bin/clang CXX=$(host_prefix)/native/bin/clang++ \
|
||||
cmake -DCMAKE_INSTALL_PREFIX=$(build_prefix) \
|
||||
-DLLVM_INCLUDE_TESTS=OFF \
|
||||
-DCMAKE_BUILD_TYPE=RELEASE \
|
||||
-DTAPI_REPOSITORY_STRING="1100.0.11" \
|
||||
-DTAPI_FULL_VERSION="11.0.0" \
|
||||
-DCMAKE_CXX_FLAGS="-I $($(package)_extract_dir)/src/llvm/projects/clang/include -I $($(package)_build_dir)/projects/clang/include" \
|
||||
$($(package)_extract_dir)/src/llvm
|
||||
endef
|
||||
|
||||
define $(package)_build_cmds
|
||||
$(MAKE) clangBasic && $(MAKE) libtapi
|
||||
CC=$(clang_prog) CXX=$(clangxx_prog) INSTALLPREFIX=$($(package)_staging_prefix_dir) ./build.sh
|
||||
endef
|
||||
|
||||
define $(package)_stage_cmds
|
||||
$(MAKE) DESTDIR=$($(package)_staging_dir) install-libtapi install-tapi-headers
|
||||
./install.sh
|
||||
endef
|
||||
|
||||
@@ -46,6 +46,7 @@ define $(package)_set_vars
|
||||
endef
|
||||
|
||||
define $(package)_preprocess_cmds
|
||||
cp -f $(BASEDIR)/config.guess $(BASEDIR)/config.sub . && \
|
||||
cp $($(package)_patch_dir)/fallback.c ncurses
|
||||
endef
|
||||
|
||||
|
||||
@@ -1,28 +1,34 @@
|
||||
packages:=boost openssl zeromq expat unbound sodium
|
||||
native_packages := native_protobuf
|
||||
packages := boost openssl zeromq unbound sodium protobuf
|
||||
|
||||
hardware_packages := hidapi protobuf libusb
|
||||
hardware_native_packages := native_protobuf
|
||||
|
||||
android_native_packages = android_ndk $(hardware_native_packages)
|
||||
android_packages = ncurses readline protobuf
|
||||
|
||||
darwin_native_packages = $(hardware_native_packages)
|
||||
darwin_packages = ncurses readline $(hardware_packages)
|
||||
|
||||
# not really native...
|
||||
freebsd_native_packages = freebsd_base $(hardware_native_packages)
|
||||
freebsd_packages = ncurses readline protobuf libusb
|
||||
|
||||
linux_packages = eudev ncurses readline $(hardware_packages)
|
||||
linux_native_packages = $(hardware_native_packages)
|
||||
|
||||
ifeq ($(build_tests),ON)
|
||||
packages += gtest
|
||||
ifneq ($(host_os),android)
|
||||
packages += libusb
|
||||
endif
|
||||
|
||||
mingw32_packages = $(hardware_packages)
|
||||
mingw32_native_packages = $(hardware_native_packages)
|
||||
ifneq ($(host_os),freebsd)
|
||||
ifneq ($(host_os),android)
|
||||
packages += hidapi
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq ($(host_os),mingw32)
|
||||
packages += ncurses readline
|
||||
endif
|
||||
|
||||
mingw32_native_packages :=
|
||||
mingw32_packages = icu4c libiconv
|
||||
|
||||
linux_native_packages :=
|
||||
linux_packages := eudev
|
||||
|
||||
freebsd_native_packages := freebsd_base
|
||||
freebsd_packages :=
|
||||
|
||||
ifneq ($(build_os),darwin)
|
||||
darwin_native_packages += darwin_sdk native_clang native_cctools native_libtapi
|
||||
darwin_native_packages := darwin_sdk native_clang native_cctools native_libtapi
|
||||
endif
|
||||
darwin_packages :=
|
||||
|
||||
android_native_packages := android_ndk
|
||||
android_packages :=
|
||||
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
package=unbound
|
||||
$(package)_version=1.19.1
|
||||
$(package)_version=1.22.0
|
||||
$(package)_download_path=https://www.nlnetlabs.nl/downloads/$(package)/
|
||||
$(package)_file_name=$(package)-$($(package)_version).tar.gz
|
||||
$(package)_sha256_hash=bc1d576f3dd846a0739adc41ffaa702404c6767d2b6082deb9f2f97cbb24a3a9
|
||||
$(package)_dependencies=openssl expat
|
||||
$(package)_patches=disable-glibc-reallocarray.patch
|
||||
|
||||
$(package)_sha256_hash=c5dd1bdef5d5685b2cedb749158dd152c52d44f65529a34ac15cd88d4b1b3d43
|
||||
$(package)_dependencies=openssl
|
||||
$(package)_patches=no-expat.patch
|
||||
|
||||
define $(package)_set_vars
|
||||
$(package)_config_opts=--disable-shared --enable-static --without-pyunbound --prefix=$(host_prefix)
|
||||
$(package)_config_opts+=--with-libexpat=$(host_prefix) --with-ssl=$(host_prefix) --with-libevent=no
|
||||
$(package)_config_opts+=--with-libexpat=no --with-ssl=$(host_prefix) --with-libevent=no
|
||||
$(package)_config_opts+=--without-pythonmodule --disable-flto --with-pthreads --with-libunbound-only
|
||||
$(package)_config_opts_linux=--with-pic
|
||||
$(package)_config_opts_w64=--enable-static-exe --sysconfdir=/etc --prefix=$(host_prefix) --target=$(host_prefix)
|
||||
$(package)_config_opts_x86_64_darwin=ac_cv_func_SHA384_Init=yes
|
||||
$(package)_build_opts_mingw32=LDFLAGS="$($(package)_ldflags) -lpthread"
|
||||
$(package)_cflags_mingw32+="-D_WIN32_WINNT=0x600"
|
||||
endef
|
||||
|
||||
# Remove blobs
|
||||
define $(package)_preprocess_cmds
|
||||
patch -p1 < $($(package)_patch_dir)/disable-glibc-reallocarray.patch &&\
|
||||
autoconf
|
||||
patch -p1 < $($(package)_patch_dir)/no-expat.patch &&\
|
||||
rm configure~ doc/*.odp doc/*.pdf contrib/*.tar.gz contrib/*.tar.bz2 &&\
|
||||
rm -rf testdata dnscrypt/testdata
|
||||
endef
|
||||
|
||||
define $(package)_config_cmds
|
||||
@@ -34,3 +34,7 @@ endef
|
||||
define $(package)_stage_cmds
|
||||
$(MAKE) DESTDIR=$($(package)_staging_dir) install
|
||||
endef
|
||||
|
||||
define $(package)_postprocess_cmds
|
||||
rm -rf share
|
||||
endef
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package=unwind
|
||||
$(package)_version=1.5.0
|
||||
$(package)_download_path=https://download.savannah.nongnu.org/releases/libunwind
|
||||
$(package)_file_name=lib$(package)-$($(package)_version).tar.gz
|
||||
$(package)_sha256_hash=90337653d92d4a13de590781371c604f9031cdb50520366aa1e3a91e1efb1017
|
||||
$(package)_patches=fix_obj_order.patch
|
||||
|
||||
define $(package)_preprocess_cmds
|
||||
patch -p0 < $($(package)_patch_dir)/fix_obj_order.patch
|
||||
endef
|
||||
|
||||
define $(package)_config_cmds
|
||||
cp -f $(BASEDIR)/config.guess config/config.guess &&\
|
||||
cp -f $(BASEDIR)/config.sub config/config.sub &&\
|
||||
$($(package)_autoconf) --disable-shared --enable-static --disable-tests --disable-documentation 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,11 +0,0 @@
|
||||
--- boost_1_64_0/tools/build/src/tools/darwin.jam.O 2017-04-17 03:22:26.000000000 +0100
|
||||
+++ boost_1_64_0/tools/build/src/tools/darwin.jam 2022-05-04 17:26:29.984464447 +0000
|
||||
@@ -505,7 +505,7 @@
|
||||
if $(instruction-set) {
|
||||
options = -arch$(_)$(instruction-set) ;
|
||||
} else {
|
||||
- options = -arch arm ;
|
||||
+# options = -arch arm ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
--- boost_1_64_0/tools/build/src/tools/gcc.jam.O 2017-04-17 03:22:26.000000000 +0100
|
||||
+++ boost_1_64_0/tools/build/src/tools/gcc.jam 2019-11-15 15:46:16.957937137 +0000
|
||||
@@ -243,6 +243,8 @@
|
||||
{
|
||||
ECHO notice: using gcc archiver :: $(condition) :: $(archiver[1]) ;
|
||||
}
|
||||
+ local arflags = [ feature.get-values <arflags> : $(options) ] ;
|
||||
+ toolset.flags gcc.archive .ARFLAGS $(condition) : $(arflags) ;
|
||||
|
||||
# - Ranlib.
|
||||
local ranlib = [ common.get-invocation-command gcc
|
||||
@@ -970,6 +972,7 @@
|
||||
# logic in intel-linux, but that is hardly worth the trouble as on Linux, 'ar'
|
||||
# is always available.
|
||||
.AR = ar ;
|
||||
+.ARFLAGS = rc ;
|
||||
.RANLIB = ranlib ;
|
||||
|
||||
toolset.flags gcc.archive AROPTIONS <archiveflags> ;
|
||||
@@ -1011,7 +1014,7 @@
|
||||
#
|
||||
actions piecemeal archive
|
||||
{
|
||||
- "$(.AR)" $(AROPTIONS) rc "$(<)" "$(>)"
|
||||
+ "$(.AR)" $(AROPTIONS) $(.ARFLAGS) "$(<)" "$(>)"
|
||||
"$(.RANLIB)" "$(<)"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
Don't build object files twice
|
||||
|
||||
When passed --enable-static and --enable-shared, icu will generate
|
||||
both a shared and a static version of its libraries.
|
||||
|
||||
However, in order to do so, it builds each and every object file
|
||||
twice: once with -fPIC (for the shared library), and once without
|
||||
-fPIC (for the static library). While admittedly building -fPIC for a
|
||||
static library generates a slightly suboptimal code, this is what all
|
||||
the autotools-based project are doing. They build each object file
|
||||
once, and they use it for both the static and shared libraries.
|
||||
|
||||
icu builds the object files for the shared library as .o files, and
|
||||
the object files for static library as .ao files. By simply changing
|
||||
the suffix of object files used for static libraries to ".o", we tell
|
||||
icu to use the ones built for the shared library (i.e, with -fPIC),
|
||||
and avoid the double build of icu.
|
||||
|
||||
On a fast build server, this brings the target icu build from
|
||||
3m41.302s down to 1m43.926s (approximate numbers: some other builds
|
||||
are running on the system at the same time).
|
||||
|
||||
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
|
||||
|
||||
Index: b/source/config/mh-linux
|
||||
===================================================================
|
||||
--- a/source/config/mh-linux
|
||||
+++ b/source/config/mh-linux
|
||||
@@ -38,7 +38,7 @@
|
||||
## Shared object suffix
|
||||
SO = so
|
||||
## Non-shared intermediate object suffix
|
||||
-STATIC_O = ao
|
||||
+STATIC_O = o
|
||||
|
||||
## Compilation rules
|
||||
%.$(STATIC_O): $(srcdir)/%.c
|
||||
@@ -0,0 +1,13 @@
|
||||
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,14 +0,0 @@
|
||||
diff --git a/configure.ac b/configure.ac
|
||||
index 5c7da197..e2b25288 100644
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -1702,6 +1702,9 @@ AC_LINK_IFELSE([AC_LANG_SOURCE(AC_INCLUDES_DEFAULT
|
||||
#ifndef _OPENBSD_SOURCE
|
||||
#define _OPENBSD_SOURCE 1
|
||||
#endif
|
||||
+#ifdef __linux__
|
||||
+# error reallocarray() is currently disabled on Linux to support glibc < 2.26
|
||||
+#endif
|
||||
#include <stdlib.h>
|
||||
int main(void) {
|
||||
void* p = reallocarray(NULL, 10, 100);
|
||||
@@ -0,0 +1,20 @@
|
||||
diff --git a/configure b/configure
|
||||
index a41e3e1e..7d6a58f0 100755
|
||||
--- a/configure
|
||||
+++ b/configure
|
||||
@@ -22053,6 +22053,7 @@ else $as_nop
|
||||
withval="/usr/local /opt/local /usr/lib /usr/pkg /usr/sfw /usr"
|
||||
fi
|
||||
|
||||
+if test x_$withval = x_yes -o x_$withval != x_no; then
|
||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libexpat" >&5
|
||||
printf %s "checking for libexpat... " >&6; }
|
||||
found_libexpat="no"
|
||||
@@ -22090,6 +22091,7 @@ else $as_nop
|
||||
ac_have_decl=0
|
||||
fi
|
||||
printf "%s\n" "#define HAVE_DECL_XML_STOPPARSER $ac_have_decl" >>confdefs.h
|
||||
+fi
|
||||
|
||||
|
||||
# hiredis (redis C client for cachedb)
|
||||
@@ -0,0 +1,11 @@
|
||||
--- config/ltmain.sh.0 2020-11-10 17:25:26.000000000 +0100
|
||||
+++ config/ltmain.sh 2021-09-11 19:39:36.000000000 +0200
|
||||
@@ -10768,6 +10768,8 @@
|
||||
fi
|
||||
func_to_tool_file "$oldlib" func_convert_file_msys_to_w32
|
||||
tool_oldlib=$func_to_tool_file_result
|
||||
+ oldobjs=`for obj in $oldobjs; do echo $obj; done | sort`
|
||||
+ oldobjs=" `echo $oldobjs`"
|
||||
eval cmds=\"$old_archive_cmds\"
|
||||
|
||||
func_len " $cmds"
|
||||
@@ -91,7 +91,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
|
||||
SET(BREW OFF)
|
||||
SET(PORT OFF)
|
||||
SET(CMAKE_OSX_SYSROOT "@prefix@/native/SDK/")
|
||||
SET(CMAKE_OSX_DEPLOYMENT_TARGET "10.13")
|
||||
SET(CMAKE_OSX_DEPLOYMENT_TARGET "11.0")
|
||||
SET(CMAKE_CXX_STANDARD 17)
|
||||
SET(LLVM_ENABLE_PIC OFF)
|
||||
SET(LLVM_ENABLE_PIE OFF)
|
||||
|
||||
@@ -74,6 +74,7 @@ namespace epee
|
||||
public:
|
||||
using char_type = std::uint8_t;
|
||||
using Ch = char_type;
|
||||
using value_type = char_type;
|
||||
|
||||
//! Increase internal buffer by at least `byte_stream_increase` bytes.
|
||||
byte_stream() noexcept
|
||||
@@ -86,6 +87,7 @@ namespace epee
|
||||
~byte_stream() noexcept = default;
|
||||
byte_stream& operator=(byte_stream&& rhs) noexcept;
|
||||
|
||||
std::uint8_t* data() noexcept { return buffer_.get(); }
|
||||
const std::uint8_t* data() const noexcept { return buffer_.get(); }
|
||||
std::uint8_t* tellp() const noexcept { return next_write_; }
|
||||
std::size_t available() const noexcept { return end_ - next_write_; }
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
#include <condition_variable>
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/asio/post.hpp>
|
||||
#include <boost/asio/ssl.hpp>
|
||||
#include <boost/asio/strand.hpp>
|
||||
#include <boost/asio/steady_timer.hpp>
|
||||
@@ -64,6 +65,7 @@
|
||||
#define MONERO_DEFAULT_LOG_CATEGORY "net"
|
||||
|
||||
#define ABSTRACT_SERVER_SEND_QUE_MAX_COUNT 1000
|
||||
#define ABSTRACT_SERVER_SEND_QUE_MAX_BYTES_DEFAULT 100 * 1024 * 1024
|
||||
|
||||
namespace epee
|
||||
{
|
||||
@@ -76,6 +78,13 @@ namespace net_utils
|
||||
protected:
|
||||
virtual ~i_connection_filter(){}
|
||||
};
|
||||
|
||||
struct i_connection_limit
|
||||
{
|
||||
virtual bool is_host_limit(const epee::net_utils::network_address &address)=0;
|
||||
protected:
|
||||
virtual ~i_connection_limit(){}
|
||||
};
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
@@ -100,8 +109,8 @@ namespace net_utils
|
||||
using ec_t = boost::system::error_code;
|
||||
using handshake_t = boost::asio::ssl::stream_base::handshake_type;
|
||||
|
||||
using io_context_t = boost::asio::io_service;
|
||||
using strand_t = boost::asio::io_service::strand;
|
||||
using io_context_t = boost::asio::io_context;
|
||||
using strand_t = io_context_t::strand;
|
||||
using socket_t = boost::asio::ip::tcp::socket;
|
||||
|
||||
using network_throttle_t = epee::net_utils::network_throttle;
|
||||
@@ -162,6 +171,7 @@ namespace net_utils
|
||||
} read;
|
||||
struct {
|
||||
std::deque<epee::byte_slice> queue;
|
||||
std::size_t total_bytes;
|
||||
bool wait_consume;
|
||||
} write;
|
||||
};
|
||||
@@ -260,20 +270,28 @@ namespace net_utils
|
||||
struct shared_state : connection_basic_shared_state, t_protocol_handler::config_type
|
||||
{
|
||||
shared_state()
|
||||
: connection_basic_shared_state(), t_protocol_handler::config_type(), pfilter(nullptr), stop_signal_sent(false)
|
||||
: connection_basic_shared_state(),
|
||||
t_protocol_handler::config_type(),
|
||||
pfilter(nullptr),
|
||||
plimit(nullptr),
|
||||
response_soft_limit(ABSTRACT_SERVER_SEND_QUE_MAX_BYTES_DEFAULT),
|
||||
stop_signal_sent(false)
|
||||
{}
|
||||
|
||||
i_connection_filter* pfilter;
|
||||
i_connection_limit* plimit;
|
||||
std::size_t response_soft_limit;
|
||||
bool stop_signal_sent;
|
||||
};
|
||||
|
||||
/// Construct a connection with the given io_service.
|
||||
explicit connection( boost::asio::io_service& io_service,
|
||||
/// Construct a connection with the given io_context.
|
||||
explicit connection( io_context_t& io_context,
|
||||
std::shared_ptr<shared_state> state,
|
||||
t_connection_type connection_type,
|
||||
epee::net_utils::ssl_support_t ssl_support);
|
||||
|
||||
explicit connection( boost::asio::ip::tcp::socket&& sock,
|
||||
explicit connection( io_context_t& io_context,
|
||||
boost::asio::ip::tcp::socket&& sock,
|
||||
std::shared_ptr<shared_state> state,
|
||||
t_connection_type connection_type,
|
||||
epee::net_utils::ssl_support_t ssl_support);
|
||||
@@ -306,7 +324,7 @@ namespace net_utils
|
||||
virtual bool close();
|
||||
virtual bool call_run_once_service_io();
|
||||
virtual bool request_callback();
|
||||
virtual boost::asio::io_service& get_io_service();
|
||||
virtual io_context_t& get_io_context();
|
||||
virtual bool add_ref();
|
||||
virtual bool release();
|
||||
//------------------------------------------------------
|
||||
@@ -336,7 +354,7 @@ namespace net_utils
|
||||
/// serve up files from the given directory.
|
||||
|
||||
boosted_tcp_server(t_connection_type connection_type);
|
||||
explicit boosted_tcp_server(boost::asio::io_service& external_io_service, t_connection_type connection_type);
|
||||
explicit boosted_tcp_server(boost::asio::io_context& external_io_context, t_connection_type connection_type);
|
||||
~boosted_tcp_server();
|
||||
|
||||
std::map<std::string, t_connection_type> server_type_map;
|
||||
@@ -349,7 +367,7 @@ namespace net_utils
|
||||
const std::string port_ipv6 = "", const std::string address_ipv6 = "::", bool use_ipv6 = false, bool require_ipv4 = true,
|
||||
ssl_options_t ssl_options = ssl_support_t::e_ssl_support_autodetect);
|
||||
|
||||
/// Run the server's io_service loop.
|
||||
/// Run the server's io_context loop.
|
||||
bool run_server(size_t threads_count, bool wait = true, const boost::thread::attributes& attrs = boost::thread::attributes());
|
||||
|
||||
/// wait for service workers stop
|
||||
@@ -369,6 +387,8 @@ namespace net_utils
|
||||
size_t get_threads_count(){return m_threads_count;}
|
||||
|
||||
void set_connection_filter(i_connection_filter* pfilter);
|
||||
void set_connection_limit(i_connection_limit* plimit);
|
||||
void set_response_soft_limit(std::size_t limit);
|
||||
|
||||
void set_default_remote(epee::net_utils::network_address remote)
|
||||
{
|
||||
@@ -409,7 +429,7 @@ namespace net_utils
|
||||
return connections_count;
|
||||
}
|
||||
|
||||
boost::asio::io_service& get_io_service(){return io_service_;}
|
||||
boost::asio::io_context& get_io_context(){return io_context_;}
|
||||
|
||||
struct idle_callback_conext_base
|
||||
{
|
||||
@@ -417,7 +437,7 @@ namespace net_utils
|
||||
|
||||
virtual bool call_handler(){return true;}
|
||||
|
||||
idle_callback_conext_base(boost::asio::io_service& io_serice):
|
||||
idle_callback_conext_base(boost::asio::io_context& io_serice):
|
||||
m_timer(io_serice)
|
||||
{}
|
||||
boost::asio::deadline_timer m_timer;
|
||||
@@ -426,7 +446,7 @@ namespace net_utils
|
||||
template <class t_handler>
|
||||
struct idle_callback_conext: public idle_callback_conext_base
|
||||
{
|
||||
idle_callback_conext(boost::asio::io_service& io_serice, t_handler& h, uint64_t period):
|
||||
idle_callback_conext(boost::asio::io_context& io_serice, t_handler& h, uint64_t period):
|
||||
idle_callback_conext_base(io_serice),
|
||||
m_handler(h)
|
||||
{this->m_period = period;}
|
||||
@@ -442,7 +462,7 @@ namespace net_utils
|
||||
template<class t_handler>
|
||||
bool add_idle_handler(t_handler t_callback, uint64_t timeout_ms)
|
||||
{
|
||||
boost::shared_ptr<idle_callback_conext<t_handler>> ptr(new idle_callback_conext<t_handler>(io_service_, t_callback, timeout_ms));
|
||||
boost::shared_ptr<idle_callback_conext<t_handler>> ptr(new idle_callback_conext<t_handler>(io_context_, t_callback, timeout_ms));
|
||||
//needed call handler here ?...
|
||||
ptr->m_timer.expires_from_now(boost::posix_time::milliseconds(ptr->m_period));
|
||||
ptr->m_timer.async_wait(boost::bind(&boosted_tcp_server<t_protocol_handler>::global_timer_handler<t_handler>, this, ptr));
|
||||
@@ -461,14 +481,14 @@ namespace net_utils
|
||||
}
|
||||
|
||||
template<class t_handler>
|
||||
bool async_call(t_handler t_callback)
|
||||
bool async_call(t_handler&& t_callback)
|
||||
{
|
||||
io_service_.post(t_callback);
|
||||
boost::asio::post(io_context_, std::forward<t_handler>(t_callback));
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
/// Run the server's io_service loop.
|
||||
/// Run the server's io_context loop.
|
||||
bool worker_thread();
|
||||
/// Handle completion of an asynchronous accept operation.
|
||||
void handle_accept_ipv4(const boost::system::error_code& e);
|
||||
@@ -479,18 +499,18 @@ namespace net_utils
|
||||
|
||||
const std::shared_ptr<typename connection<t_protocol_handler>::shared_state> m_state;
|
||||
|
||||
/// The io_service used to perform asynchronous operations.
|
||||
/// The io_context used to perform asynchronous operations.
|
||||
struct worker
|
||||
{
|
||||
worker()
|
||||
: io_service(), work(io_service)
|
||||
: io_context(), work(io_context.get_executor())
|
||||
{}
|
||||
|
||||
boost::asio::io_service io_service;
|
||||
boost::asio::io_service::work work;
|
||||
boost::asio::io_context io_context;
|
||||
boost::asio::executor_work_guard<boost::asio::io_context::executor_type> work;
|
||||
};
|
||||
std::unique_ptr<worker> m_io_service_local_instance;
|
||||
boost::asio::io_service& io_service_;
|
||||
std::unique_ptr<worker> m_io_context_local_instance;
|
||||
boost::asio::io_context& io_context_;
|
||||
|
||||
/// Acceptor used to listen for incoming connections.
|
||||
boost::asio::ip::tcp::acceptor acceptor_;
|
||||
|
||||
@@ -31,11 +31,12 @@
|
||||
//
|
||||
|
||||
|
||||
|
||||
#include <boost/asio/post.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/uuid/random_generator.hpp>
|
||||
#include <boost/chrono.hpp>
|
||||
#include <boost/utility/value_init.hpp>
|
||||
#include <boost/asio/bind_executor.hpp>
|
||||
#include <boost/asio/deadline_timer.hpp>
|
||||
#include <boost/date_time/posix_time/posix_time.hpp> // TODO
|
||||
#include <boost/thread/condition_variable.hpp> // TODO
|
||||
@@ -145,23 +146,19 @@ namespace net_utils
|
||||
if (m_state.timers.general.wait_expire) {
|
||||
m_state.timers.general.cancel_expire = true;
|
||||
m_state.timers.general.reset_expire = true;
|
||||
ec_t ec;
|
||||
m_timers.general.expires_from_now(
|
||||
m_timers.general.expires_after(
|
||||
std::min(
|
||||
duration + (add ? m_timers.general.expires_from_now() : duration_t{}),
|
||||
duration + (add ? (m_timers.general.expiry() - std::chrono::steady_clock::now()) : duration_t{}),
|
||||
get_default_timeout()
|
||||
),
|
||||
ec
|
||||
)
|
||||
);
|
||||
}
|
||||
else {
|
||||
ec_t ec;
|
||||
m_timers.general.expires_from_now(
|
||||
m_timers.general.expires_after(
|
||||
std::min(
|
||||
duration + (add ? m_timers.general.expires_from_now() : duration_t{}),
|
||||
duration + (add ? (m_timers.general.expiry() - std::chrono::steady_clock::now()) : duration_t{}),
|
||||
get_default_timeout()
|
||||
),
|
||||
ec
|
||||
)
|
||||
);
|
||||
async_wait_timer();
|
||||
}
|
||||
@@ -202,8 +199,7 @@ namespace net_utils
|
||||
return;
|
||||
m_state.timers.general.cancel_expire = true;
|
||||
m_state.timers.general.reset_expire = false;
|
||||
ec_t ec;
|
||||
m_timers.general.cancel(ec);
|
||||
m_timers.general.cancel();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
@@ -225,7 +221,8 @@ namespace net_utils
|
||||
m_state.data.read.buffer.size()
|
||||
),
|
||||
boost::asio::transfer_exactly(epee::net_utils::get_ssl_magic_size()),
|
||||
m_strand.wrap(
|
||||
boost::asio::bind_executor(
|
||||
m_strand,
|
||||
[this, self](const ec_t &ec, size_t bytes_transferred){
|
||||
std::lock_guard<std::mutex> guard(m_state.lock);
|
||||
m_state.socket.wait_read = false;
|
||||
@@ -246,7 +243,8 @@ namespace net_utils
|
||||
) {
|
||||
m_state.ssl.enabled = false;
|
||||
m_state.socket.handle_read = true;
|
||||
connection_basic::strand_.post(
|
||||
boost::asio::post(
|
||||
connection_basic::strand_,
|
||||
[this, self, bytes_transferred]{
|
||||
bool success = m_handler.handle_recv(
|
||||
reinterpret_cast<char *>(m_state.data.read.buffer.data()),
|
||||
@@ -304,7 +302,8 @@ namespace net_utils
|
||||
static_cast<shared_state&>(
|
||||
connection_basic::get_state()
|
||||
).ssl_options().configure(connection_basic::socket_, handshake);
|
||||
m_strand.post(
|
||||
boost::asio::post(
|
||||
m_strand,
|
||||
[this, self, on_handshake]{
|
||||
connection_basic::socket_.async_handshake(
|
||||
handshake,
|
||||
@@ -313,7 +312,7 @@ namespace net_utils
|
||||
m_state.ssl.forced ? 0 :
|
||||
epee::net_utils::get_ssl_magic_size()
|
||||
),
|
||||
m_strand.wrap(on_handshake)
|
||||
boost::asio::bind_executor(m_strand, on_handshake)
|
||||
);
|
||||
}
|
||||
);
|
||||
@@ -328,7 +327,7 @@ namespace net_utils
|
||||
return;
|
||||
}
|
||||
auto self = connection<T>::shared_from_this();
|
||||
if (m_connection_type != e_connection_type_RPC) {
|
||||
if (speed_limit_is_enabled()) {
|
||||
auto calc_duration = []{
|
||||
CRITICAL_REGION_LOCAL(
|
||||
network_throttle_manager_t::m_lock_get_global_throttle_in
|
||||
@@ -345,8 +344,7 @@ namespace net_utils
|
||||
};
|
||||
const auto duration = calc_duration();
|
||||
if (duration > duration_t{}) {
|
||||
ec_t ec;
|
||||
m_timers.throttle.in.expires_from_now(duration, ec);
|
||||
m_timers.throttle.in.expires_after(duration);
|
||||
m_state.timers.throttle.in.wait_expire = true;
|
||||
m_timers.throttle.in.async_wait([this, self](const ec_t &ec){
|
||||
std::lock_guard<std::mutex> guard(m_state.lock);
|
||||
@@ -382,7 +380,7 @@ namespace net_utils
|
||||
m_conn_context.m_max_speed_down,
|
||||
speed
|
||||
);
|
||||
{
|
||||
if (speed_limit_is_enabled()) {
|
||||
CRITICAL_REGION_LOCAL(
|
||||
network_throttle_manager_t::m_lock_get_global_throttle_in
|
||||
);
|
||||
@@ -401,7 +399,8 @@ namespace net_utils
|
||||
// writes until the connection terminates without deadlocking waiting
|
||||
// for handle_recv.
|
||||
m_state.socket.handle_read = true;
|
||||
connection_basic::strand_.post(
|
||||
boost::asio::post(
|
||||
connection_basic::strand_,
|
||||
[this, self, bytes_transferred]{
|
||||
bool success = m_handler.handle_recv(
|
||||
reinterpret_cast<char *>(m_state.data.read.buffer.data()),
|
||||
@@ -428,17 +427,18 @@ namespace net_utils
|
||||
m_state.data.read.buffer.data(),
|
||||
m_state.data.read.buffer.size()
|
||||
),
|
||||
m_strand.wrap(on_read)
|
||||
boost::asio::bind_executor(m_strand, on_read)
|
||||
);
|
||||
else
|
||||
m_strand.post(
|
||||
boost::asio::post(
|
||||
m_strand,
|
||||
[this, self, on_read]{
|
||||
connection_basic::socket_.async_read_some(
|
||||
boost::asio::buffer(
|
||||
m_state.data.read.buffer.data(),
|
||||
m_state.data.read.buffer.size()
|
||||
),
|
||||
m_strand.wrap(on_read)
|
||||
boost::asio::bind_executor(m_strand, on_read)
|
||||
);
|
||||
}
|
||||
);
|
||||
@@ -454,7 +454,7 @@ namespace net_utils
|
||||
return;
|
||||
}
|
||||
auto self = connection<T>::shared_from_this();
|
||||
if (m_connection_type != e_connection_type_RPC) {
|
||||
if (speed_limit_is_enabled()) {
|
||||
auto calc_duration = [this]{
|
||||
CRITICAL_REGION_LOCAL(
|
||||
network_throttle_manager_t::m_lock_get_global_throttle_out
|
||||
@@ -473,8 +473,7 @@ namespace net_utils
|
||||
};
|
||||
const auto duration = calc_duration();
|
||||
if (duration > duration_t{}) {
|
||||
ec_t ec;
|
||||
m_timers.throttle.out.expires_from_now(duration, ec);
|
||||
m_timers.throttle.out.expires_after(duration);
|
||||
m_state.timers.throttle.out.wait_expire = true;
|
||||
m_timers.throttle.out.async_wait([this, self](const ec_t &ec){
|
||||
std::lock_guard<std::mutex> guard(m_state.lock);
|
||||
@@ -498,10 +497,12 @@ namespace net_utils
|
||||
if (m_state.socket.cancel_write) {
|
||||
m_state.socket.cancel_write = false;
|
||||
m_state.data.write.queue.clear();
|
||||
m_state.data.write.total_bytes = 0;
|
||||
state_status_check();
|
||||
}
|
||||
else if (ec.value()) {
|
||||
m_state.data.write.queue.clear();
|
||||
m_state.data.write.total_bytes = 0;
|
||||
interrupt();
|
||||
}
|
||||
else {
|
||||
@@ -513,7 +514,7 @@ namespace net_utils
|
||||
m_conn_context.m_max_speed_down,
|
||||
speed
|
||||
);
|
||||
{
|
||||
if (speed_limit_is_enabled()) {
|
||||
CRITICAL_REGION_LOCAL(
|
||||
network_throttle_manager_t::m_lock_get_global_throttle_out
|
||||
);
|
||||
@@ -526,8 +527,11 @@ namespace net_utils
|
||||
|
||||
start_timer(get_default_timeout(), true);
|
||||
}
|
||||
assert(bytes_transferred == m_state.data.write.queue.back().size());
|
||||
const std::size_t byte_count = m_state.data.write.queue.back().size();
|
||||
assert(bytes_transferred == byte_count);
|
||||
m_state.data.write.queue.pop_back();
|
||||
m_state.data.write.total_bytes -=
|
||||
std::min(m_state.data.write.total_bytes, byte_count);
|
||||
m_state.condition.notify_all();
|
||||
start_write();
|
||||
}
|
||||
@@ -539,10 +543,11 @@ namespace net_utils
|
||||
m_state.data.write.queue.back().data(),
|
||||
m_state.data.write.queue.back().size()
|
||||
),
|
||||
m_strand.wrap(on_write)
|
||||
boost::asio::bind_executor(m_strand, on_write)
|
||||
);
|
||||
else
|
||||
m_strand.post(
|
||||
boost::asio::post(
|
||||
m_strand,
|
||||
[this, self, on_write]{
|
||||
boost::asio::async_write(
|
||||
connection_basic::socket_,
|
||||
@@ -550,7 +555,7 @@ namespace net_utils
|
||||
m_state.data.write.queue.back().data(),
|
||||
m_state.data.write.queue.back().size()
|
||||
),
|
||||
m_strand.wrap(on_write)
|
||||
boost::asio::bind_executor(m_strand, on_write)
|
||||
);
|
||||
}
|
||||
);
|
||||
@@ -587,10 +592,11 @@ namespace net_utils
|
||||
terminate();
|
||||
}
|
||||
};
|
||||
m_strand.post(
|
||||
boost::asio::post(
|
||||
m_strand,
|
||||
[this, self, on_shutdown]{
|
||||
connection_basic::socket_.async_shutdown(
|
||||
m_strand.wrap(on_shutdown)
|
||||
boost::asio::bind_executor(m_strand, on_shutdown)
|
||||
);
|
||||
}
|
||||
);
|
||||
@@ -605,15 +611,13 @@ namespace net_utils
|
||||
wait_socket = m_state.socket.cancel_handshake = true;
|
||||
if (m_state.timers.throttle.in.wait_expire) {
|
||||
m_state.timers.throttle.in.cancel_expire = true;
|
||||
ec_t ec;
|
||||
m_timers.throttle.in.cancel(ec);
|
||||
m_timers.throttle.in.cancel();
|
||||
}
|
||||
if (m_state.socket.wait_read)
|
||||
wait_socket = m_state.socket.cancel_read = true;
|
||||
if (m_state.timers.throttle.out.wait_expire) {
|
||||
m_state.timers.throttle.out.cancel_expire = true;
|
||||
ec_t ec;
|
||||
m_timers.throttle.out.cancel(ec);
|
||||
m_timers.throttle.out.cancel();
|
||||
}
|
||||
if (m_state.socket.wait_write)
|
||||
wait_socket = m_state.socket.cancel_write = true;
|
||||
@@ -671,8 +675,9 @@ namespace net_utils
|
||||
return;
|
||||
if (m_state.timers.throttle.out.wait_expire)
|
||||
return;
|
||||
if (m_state.socket.wait_write)
|
||||
return;
|
||||
// \NOTE See on_terminating() comments
|
||||
//if (m_state.socket.wait_write)
|
||||
// return;
|
||||
if (m_state.socket.wait_shutdown)
|
||||
return;
|
||||
if (m_state.protocol.wait_init)
|
||||
@@ -730,8 +735,13 @@ namespace net_utils
|
||||
return;
|
||||
if (m_state.timers.throttle.out.wait_expire)
|
||||
return;
|
||||
if (m_state.socket.wait_write)
|
||||
return;
|
||||
// Writes cannot be canceled due to `async_write` being a "composed"
|
||||
// handler. ASIO has new cancellation routines, not available in 1.66, to
|
||||
// handle this situation. The problem is that if cancel is called after an
|
||||
// intermediate handler is queued, the op will not check the cancel flag in
|
||||
// our code, and will instead queue up another write.
|
||||
//if (m_state.socket.wait_write)
|
||||
// return;
|
||||
if (m_state.socket.wait_shutdown)
|
||||
return;
|
||||
if (m_state.protocol.wait_init)
|
||||
@@ -758,6 +768,8 @@ namespace net_utils
|
||||
std::lock_guard<std::mutex> guard(m_state.lock);
|
||||
if (m_state.status != status_t::RUNNING || m_state.socket.wait_handshake)
|
||||
return false;
|
||||
if (std::numeric_limits<std::size_t>::max() - m_state.data.write.total_bytes < message.size())
|
||||
return false;
|
||||
|
||||
// Wait for the write queue to fall below the max. If it doesn't after a
|
||||
// randomized delay, drop the connection.
|
||||
@@ -775,7 +787,14 @@ namespace net_utils
|
||||
std::uniform_int_distribution<>(5000, 6000)(rng)
|
||||
);
|
||||
};
|
||||
if (m_state.data.write.queue.size() <= ABSTRACT_SERVER_SEND_QUE_MAX_COUNT)
|
||||
|
||||
// The bytes check intentionally does not include incoming message size.
|
||||
// This allows for a soft overflow; a single http response will never fail
|
||||
// this check, but multiple responses could. Clients can avoid this case
|
||||
// by reading the entire response before making another request. P2P
|
||||
// should never hit the MAX_BYTES check (when using default values).
|
||||
if (m_state.data.write.queue.size() <= ABSTRACT_SERVER_SEND_QUE_MAX_COUNT &&
|
||||
m_state.data.write.total_bytes <= static_cast<shared_state&>(connection_basic::get_state()).response_soft_limit)
|
||||
return true;
|
||||
m_state.data.write.wait_consume = true;
|
||||
bool success = m_state.condition.wait_for(
|
||||
@@ -784,14 +803,23 @@ namespace net_utils
|
||||
[this]{
|
||||
return (
|
||||
m_state.status != status_t::RUNNING ||
|
||||
m_state.data.write.queue.size() <=
|
||||
ABSTRACT_SERVER_SEND_QUE_MAX_COUNT
|
||||
(
|
||||
m_state.data.write.queue.size() <=
|
||||
ABSTRACT_SERVER_SEND_QUE_MAX_COUNT &&
|
||||
m_state.data.write.total_bytes <=
|
||||
static_cast<shared_state&>(connection_basic::get_state()).response_soft_limit
|
||||
)
|
||||
);
|
||||
}
|
||||
);
|
||||
m_state.data.write.wait_consume = false;
|
||||
if (!success) {
|
||||
terminate();
|
||||
// synchronize with intermediate writes on `m_strand`
|
||||
auto self = connection<T>::shared_from_this();
|
||||
boost::asio::post(m_strand, [this, self] {
|
||||
std::lock_guard<std::mutex> guard(m_state.lock);
|
||||
terminate();
|
||||
});
|
||||
return false;
|
||||
}
|
||||
else
|
||||
@@ -817,7 +845,9 @@ namespace net_utils
|
||||
) {
|
||||
if (!wait_consume())
|
||||
return false;
|
||||
const std::size_t byte_count = message.size();
|
||||
m_state.data.write.queue.emplace_front(std::move(message));
|
||||
m_state.data.write.total_bytes += byte_count;
|
||||
start_write();
|
||||
}
|
||||
else {
|
||||
@@ -827,6 +857,7 @@ namespace net_utils
|
||||
m_state.data.write.queue.emplace_front(
|
||||
message.take_slice(CHUNK_SIZE)
|
||||
);
|
||||
m_state.data.write.total_bytes += m_state.data.write.queue.front().size();
|
||||
start_write();
|
||||
}
|
||||
}
|
||||
@@ -860,7 +891,7 @@ namespace net_utils
|
||||
ipv4_network_address{
|
||||
uint32_t{
|
||||
boost::asio::detail::socket_ops::host_to_network_long(
|
||||
endpoint.address().to_v4().to_ulong()
|
||||
endpoint.address().to_v4().to_uint()
|
||||
)
|
||||
},
|
||||
endpoint.port()
|
||||
@@ -873,6 +904,13 @@ namespace net_utils
|
||||
).pfilter;
|
||||
if (filter && !filter->is_remote_host_allowed(*real_remote))
|
||||
return false;
|
||||
|
||||
auto *limit = static_cast<shared_state&>(
|
||||
connection_basic::get_state()
|
||||
).plimit;
|
||||
if (limit && limit->is_host_limit(*real_remote))
|
||||
return false;
|
||||
|
||||
ec_t ec;
|
||||
#if !defined(_WIN32) || !defined(__i686)
|
||||
connection_basic::socket_.next_layer().set_option(
|
||||
@@ -938,7 +976,8 @@ namespace net_utils
|
||||
ssl_support_t ssl_support
|
||||
):
|
||||
connection(
|
||||
std::move(socket_t{io_context}),
|
||||
io_context,
|
||||
socket_t{io_context},
|
||||
std::move(shared_state),
|
||||
connection_type,
|
||||
ssl_support
|
||||
@@ -948,15 +987,16 @@ namespace net_utils
|
||||
|
||||
template<typename T>
|
||||
connection<T>::connection(
|
||||
io_context_t &io_context,
|
||||
socket_t &&socket,
|
||||
std::shared_ptr<shared_state> shared_state,
|
||||
t_connection_type connection_type,
|
||||
ssl_support_t ssl_support
|
||||
):
|
||||
connection_basic(std::move(socket), shared_state, ssl_support),
|
||||
connection_basic(io_context, std::move(socket), shared_state, ssl_support),
|
||||
m_handler(this, *shared_state, m_conn_context),
|
||||
m_connection_type(connection_type),
|
||||
m_io_context{GET_IO_SERVICE(connection_basic::socket_)},
|
||||
m_io_context{io_context},
|
||||
m_strand{m_io_context},
|
||||
m_timers{m_io_context}
|
||||
{
|
||||
@@ -1022,7 +1062,7 @@ namespace net_utils
|
||||
template<typename T>
|
||||
bool connection<T>::speed_limit_is_enabled() const
|
||||
{
|
||||
return m_connection_type != e_connection_type_RPC;
|
||||
return m_connection_type == e_connection_type_P2P;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
@@ -1075,7 +1115,7 @@ namespace net_utils
|
||||
return false;
|
||||
auto self = connection<T>::shared_from_this();
|
||||
++m_state.protocol.wait_callback;
|
||||
connection_basic::strand_.post([this, self]{
|
||||
boost::asio::post(connection_basic::strand_, [this, self]{
|
||||
m_handler.handle_qued_callback();
|
||||
std::lock_guard<std::mutex> guard(m_state.lock);
|
||||
--m_state.protocol.wait_callback;
|
||||
@@ -1088,7 +1128,7 @@ namespace net_utils
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
typename connection<T>::io_context_t &connection<T>::get_io_service()
|
||||
typename connection<T>::io_context_t &connection<T>::get_io_context()
|
||||
{
|
||||
return m_io_context;
|
||||
}
|
||||
@@ -1128,10 +1168,10 @@ namespace net_utils
|
||||
template<class t_protocol_handler>
|
||||
boosted_tcp_server<t_protocol_handler>::boosted_tcp_server( t_connection_type connection_type ) :
|
||||
m_state(std::make_shared<typename connection<t_protocol_handler>::shared_state>()),
|
||||
m_io_service_local_instance(new worker()),
|
||||
io_service_(m_io_service_local_instance->io_service),
|
||||
acceptor_(io_service_),
|
||||
acceptor_ipv6(io_service_),
|
||||
m_io_context_local_instance(new worker()),
|
||||
io_context_(m_io_context_local_instance->io_context),
|
||||
acceptor_(io_context_),
|
||||
acceptor_ipv6(io_context_),
|
||||
default_remote(),
|
||||
m_stop_signal_sent(false), m_port(0),
|
||||
m_threads_count(0),
|
||||
@@ -1145,11 +1185,11 @@ namespace net_utils
|
||||
}
|
||||
|
||||
template<class t_protocol_handler>
|
||||
boosted_tcp_server<t_protocol_handler>::boosted_tcp_server(boost::asio::io_service& extarnal_io_service, t_connection_type connection_type) :
|
||||
boosted_tcp_server<t_protocol_handler>::boosted_tcp_server(boost::asio::io_context& extarnal_io_context, t_connection_type connection_type) :
|
||||
m_state(std::make_shared<typename connection<t_protocol_handler>::shared_state>()),
|
||||
io_service_(extarnal_io_service),
|
||||
acceptor_(io_service_),
|
||||
acceptor_ipv6(io_service_),
|
||||
io_context_(extarnal_io_context),
|
||||
acceptor_(io_context_),
|
||||
acceptor_ipv6(io_context_),
|
||||
default_remote(),
|
||||
m_stop_signal_sent(false), m_port(0),
|
||||
m_threads_count(0),
|
||||
@@ -1196,24 +1236,27 @@ namespace net_utils
|
||||
|
||||
std::string ipv4_failed = "";
|
||||
std::string ipv6_failed = "";
|
||||
|
||||
boost::asio::ip::tcp::resolver resolver(io_context_);
|
||||
|
||||
try
|
||||
{
|
||||
boost::asio::ip::tcp::resolver resolver(io_service_);
|
||||
boost::asio::ip::tcp::resolver::query query(address, boost::lexical_cast<std::string>(port), boost::asio::ip::tcp::resolver::query::canonical_name);
|
||||
boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve(query);
|
||||
acceptor_.open(endpoint.protocol());
|
||||
const auto results = resolver.resolve(
|
||||
address, boost::lexical_cast<std::string>(port), boost::asio::ip::tcp::resolver::canonical_name
|
||||
);
|
||||
acceptor_.open(results.begin()->endpoint().protocol());
|
||||
#if !defined(_WIN32)
|
||||
acceptor_.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
|
||||
#endif
|
||||
acceptor_.bind(endpoint);
|
||||
acceptor_.bind(*results.begin());
|
||||
acceptor_.listen();
|
||||
boost::asio::ip::tcp::endpoint binded_endpoint = acceptor_.local_endpoint();
|
||||
m_port = binded_endpoint.port();
|
||||
MDEBUG("start accept (IPv4)");
|
||||
new_connection_.reset(new connection<t_protocol_handler>(io_service_, m_state, m_connection_type, m_state->ssl_options().support));
|
||||
new_connection_.reset(new connection<t_protocol_handler>(io_context_, m_state, m_connection_type, m_state->ssl_options().support));
|
||||
acceptor_.async_accept(new_connection_->socket(),
|
||||
boost::bind(&boosted_tcp_server<t_protocol_handler>::handle_accept_ipv4, this,
|
||||
boost::asio::placeholders::error));
|
||||
boost::bind(&boosted_tcp_server<t_protocol_handler>::handle_accept_ipv4, this,
|
||||
boost::asio::placeholders::error));
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
@@ -1234,23 +1277,25 @@ namespace net_utils
|
||||
try
|
||||
{
|
||||
if (port_ipv6 == 0) port_ipv6 = port; // default arg means bind to same port as ipv4
|
||||
boost::asio::ip::tcp::resolver resolver(io_service_);
|
||||
boost::asio::ip::tcp::resolver::query query(address_ipv6, boost::lexical_cast<std::string>(port_ipv6), boost::asio::ip::tcp::resolver::query::canonical_name);
|
||||
boost::asio::ip::tcp::endpoint endpoint = *resolver.resolve(query);
|
||||
acceptor_ipv6.open(endpoint.protocol());
|
||||
|
||||
const auto results = resolver.resolve(
|
||||
address_ipv6, boost::lexical_cast<std::string>(port_ipv6), boost::asio::ip::tcp::resolver::canonical_name
|
||||
);
|
||||
|
||||
acceptor_ipv6.open(results.begin()->endpoint().protocol());
|
||||
#if !defined(_WIN32)
|
||||
acceptor_ipv6.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
|
||||
#endif
|
||||
acceptor_ipv6.set_option(boost::asio::ip::v6_only(true));
|
||||
acceptor_ipv6.bind(endpoint);
|
||||
acceptor_ipv6.bind(*results.begin());
|
||||
acceptor_ipv6.listen();
|
||||
boost::asio::ip::tcp::endpoint binded_endpoint = acceptor_ipv6.local_endpoint();
|
||||
m_port_ipv6 = binded_endpoint.port();
|
||||
MDEBUG("start accept (IPv6)");
|
||||
new_connection_ipv6.reset(new connection<t_protocol_handler>(io_service_, m_state, m_connection_type, m_state->ssl_options().support));
|
||||
new_connection_ipv6.reset(new connection<t_protocol_handler>(io_context_, m_state, m_connection_type, m_state->ssl_options().support));
|
||||
acceptor_ipv6.async_accept(new_connection_ipv6->socket(),
|
||||
boost::bind(&boosted_tcp_server<t_protocol_handler>::handle_accept_ipv6, this,
|
||||
boost::asio::placeholders::error));
|
||||
boost::bind(&boosted_tcp_server<t_protocol_handler>::handle_accept_ipv6, this,
|
||||
boost::asio::placeholders::error));
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
@@ -1314,7 +1359,7 @@ namespace net_utils
|
||||
{
|
||||
try
|
||||
{
|
||||
io_service_.run();
|
||||
io_context_.run();
|
||||
return true;
|
||||
}
|
||||
catch(const std::exception& ex)
|
||||
@@ -1349,6 +1394,20 @@ namespace net_utils
|
||||
}
|
||||
//---------------------------------------------------------------------------------
|
||||
template<class t_protocol_handler>
|
||||
void boosted_tcp_server<t_protocol_handler>::set_connection_limit(i_connection_limit* plimit)
|
||||
{
|
||||
assert(m_state != nullptr); // always set in constructor
|
||||
m_state->plimit = plimit;
|
||||
}
|
||||
//---------------------------------------------------------------------------------
|
||||
template<class t_protocol_handler>
|
||||
void boosted_tcp_server<t_protocol_handler>::set_response_soft_limit(const std::size_t limit)
|
||||
{
|
||||
assert(m_state != nullptr); // always set in constructor
|
||||
m_state->response_soft_limit = limit;
|
||||
}
|
||||
//---------------------------------------------------------------------------------
|
||||
template<class t_protocol_handler>
|
||||
bool boosted_tcp_server<t_protocol_handler>::run_server(size_t threads_count, bool wait, const boost::thread::attributes& attrs)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
@@ -1358,7 +1417,7 @@ namespace net_utils
|
||||
while(!m_stop_signal_sent)
|
||||
{
|
||||
|
||||
// Create a pool of threads to run all of the io_services.
|
||||
// Create a pool of threads to run all of the io_contexts.
|
||||
CRITICAL_REGION_BEGIN(m_threads_lock);
|
||||
for (std::size_t i = 0; i < threads_count; ++i)
|
||||
{
|
||||
@@ -1450,7 +1509,7 @@ namespace net_utils
|
||||
}
|
||||
connections_.clear();
|
||||
connections_mutex.unlock();
|
||||
io_service_.stop();
|
||||
io_context_.stop();
|
||||
CATCH_ENTRY_L0("boosted_tcp_server<t_protocol_handler>::send_stop_signal()", void());
|
||||
}
|
||||
//---------------------------------------------------------------------------------
|
||||
@@ -1497,7 +1556,7 @@ namespace net_utils
|
||||
(*current_new_connection)->setRpcStation(); // hopefully this is not needed actually
|
||||
}
|
||||
connection_ptr conn(std::move((*current_new_connection)));
|
||||
(*current_new_connection).reset(new connection<t_protocol_handler>(io_service_, m_state, m_connection_type, conn->get_ssl_support()));
|
||||
(*current_new_connection).reset(new connection<t_protocol_handler>(io_context_, m_state, m_connection_type, conn->get_ssl_support()));
|
||||
current_acceptor->async_accept((*current_new_connection)->socket(),
|
||||
boost::bind(accept_function_pointer, this,
|
||||
boost::asio::placeholders::error));
|
||||
@@ -1532,7 +1591,7 @@ namespace net_utils
|
||||
assert(m_state != nullptr); // always set in constructor
|
||||
_erro("Some problems at accept: " << e.message() << ", connections_count = " << m_state->sock_count);
|
||||
misc_utils::sleep_no_w(100);
|
||||
(*current_new_connection).reset(new connection<t_protocol_handler>(io_service_, m_state, m_connection_type, (*current_new_connection)->get_ssl_support()));
|
||||
(*current_new_connection).reset(new connection<t_protocol_handler>(io_context_, m_state, m_connection_type, (*current_new_connection)->get_ssl_support()));
|
||||
current_acceptor->async_accept((*current_new_connection)->socket(),
|
||||
boost::bind(accept_function_pointer, this,
|
||||
boost::asio::placeholders::error));
|
||||
@@ -1541,9 +1600,9 @@ namespace net_utils
|
||||
template<class t_protocol_handler>
|
||||
bool boosted_tcp_server<t_protocol_handler>::add_connection(t_connection_context& out, boost::asio::ip::tcp::socket&& sock, network_address real_remote, epee::net_utils::ssl_support_t ssl_support)
|
||||
{
|
||||
if(std::addressof(get_io_service()) == std::addressof(GET_IO_SERVICE(sock)))
|
||||
if(std::addressof(get_io_context()) == std::addressof(sock.get_executor().context()))
|
||||
{
|
||||
connection_ptr conn(new connection<t_protocol_handler>(std::move(sock), m_state, m_connection_type, ssl_support));
|
||||
connection_ptr conn(new connection<t_protocol_handler>(io_context_, std::move(sock), m_state, m_connection_type, ssl_support));
|
||||
if(conn->start(false, 1 < m_threads_count, std::move(real_remote)))
|
||||
{
|
||||
conn->get_context(out);
|
||||
@@ -1553,7 +1612,7 @@ namespace net_utils
|
||||
}
|
||||
else
|
||||
{
|
||||
MWARNING(out << " was not added, socket/io_service mismatch");
|
||||
MWARNING(out << " was not added, socket/io_context mismatch");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -1566,7 +1625,7 @@ namespace net_utils
|
||||
sock_.open(remote_endpoint.protocol());
|
||||
if(bind_ip != "0.0.0.0" && bind_ip != "0" && bind_ip != "" )
|
||||
{
|
||||
boost::asio::ip::tcp::endpoint local_endpoint(boost::asio::ip::address::from_string(bind_ip.c_str()), 0);
|
||||
boost::asio::ip::tcp::endpoint local_endpoint(boost::asio::ip::make_address(bind_ip), 0);
|
||||
boost::system::error_code ec;
|
||||
sock_.bind(local_endpoint, ec);
|
||||
if (ec)
|
||||
@@ -1661,7 +1720,7 @@ namespace net_utils
|
||||
{
|
||||
TRY_ENTRY();
|
||||
|
||||
connection_ptr new_connection_l(new connection<t_protocol_handler>(io_service_, m_state, m_connection_type, ssl_support) );
|
||||
connection_ptr new_connection_l(new connection<t_protocol_handler>(io_context_, m_state, m_connection_type, ssl_support) );
|
||||
connections_mutex.lock();
|
||||
connections_.insert(new_connection_l);
|
||||
MDEBUG("connections_ size now " << connections_.size());
|
||||
@@ -1671,14 +1730,16 @@ namespace net_utils
|
||||
|
||||
bool try_ipv6 = false;
|
||||
|
||||
boost::asio::ip::tcp::resolver resolver(io_service_);
|
||||
boost::asio::ip::tcp::resolver::query query(boost::asio::ip::tcp::v4(), adr, port, boost::asio::ip::tcp::resolver::query::canonical_name);
|
||||
boost::asio::ip::tcp::resolver resolver(io_context_);
|
||||
boost::asio::ip::tcp::resolver::results_type results{};
|
||||
boost::system::error_code resolve_error;
|
||||
boost::asio::ip::tcp::resolver::iterator iterator;
|
||||
|
||||
try
|
||||
{
|
||||
//resolving ipv4 address as ipv6 throws, catch here and move on
|
||||
iterator = resolver.resolve(query, resolve_error);
|
||||
results = resolver.resolve(
|
||||
boost::asio::ip::tcp::v4(), adr, port, boost::asio::ip::tcp::resolver::canonical_name, resolve_error
|
||||
);
|
||||
}
|
||||
catch (const boost::system::system_error& e)
|
||||
{
|
||||
@@ -1696,8 +1757,7 @@ namespace net_utils
|
||||
|
||||
std::string bind_ip_to_use;
|
||||
|
||||
boost::asio::ip::tcp::resolver::iterator end;
|
||||
if(iterator == end)
|
||||
if(results.empty())
|
||||
{
|
||||
if (!m_use_ipv6)
|
||||
{
|
||||
@@ -1717,11 +1777,11 @@ namespace net_utils
|
||||
|
||||
if (try_ipv6)
|
||||
{
|
||||
boost::asio::ip::tcp::resolver::query query6(boost::asio::ip::tcp::v6(), adr, port, boost::asio::ip::tcp::resolver::query::canonical_name);
|
||||
results = resolver.resolve(
|
||||
boost::asio::ip::tcp::v6(), adr, port, boost::asio::ip::tcp::resolver::canonical_name, resolve_error
|
||||
);
|
||||
|
||||
iterator = resolver.resolve(query6, resolve_error);
|
||||
|
||||
if(iterator == end)
|
||||
if(results.empty())
|
||||
{
|
||||
_erro("Failed to resolve " << adr);
|
||||
return false;
|
||||
@@ -1741,6 +1801,8 @@ namespace net_utils
|
||||
|
||||
}
|
||||
|
||||
const auto iterator = results.begin();
|
||||
|
||||
MDEBUG("Trying to connect to " << adr << ":" << port << ", bind_ip = " << bind_ip_to_use);
|
||||
|
||||
//boost::asio::ip::tcp::endpoint remote_endpoint(boost::asio::ip::address::from_string(addr.c_str()), port);
|
||||
@@ -1767,7 +1829,6 @@ namespace net_utils
|
||||
if (r)
|
||||
{
|
||||
new_connection_l->get_context(conn_context);
|
||||
//new_connection_l.reset(new connection<t_protocol_handler>(io_service_, m_config, m_sock_count, m_pfilter));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1786,7 +1847,7 @@ namespace net_utils
|
||||
bool boosted_tcp_server<t_protocol_handler>::connect_async(const std::string& adr, const std::string& port, uint32_t conn_timeout, const t_callback &cb, const std::string& bind_ip, epee::net_utils::ssl_support_t ssl_support)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
connection_ptr new_connection_l(new connection<t_protocol_handler>(io_service_, m_state, m_connection_type, ssl_support) );
|
||||
connection_ptr new_connection_l(new connection<t_protocol_handler>(io_context_, m_state, m_connection_type, ssl_support) );
|
||||
connections_mutex.lock();
|
||||
connections_.insert(new_connection_l);
|
||||
MDEBUG("connections_ size now " << connections_.size());
|
||||
@@ -1796,14 +1857,16 @@ namespace net_utils
|
||||
|
||||
bool try_ipv6 = false;
|
||||
|
||||
boost::asio::ip::tcp::resolver resolver(io_service_);
|
||||
boost::asio::ip::tcp::resolver::query query(boost::asio::ip::tcp::v4(), adr, port, boost::asio::ip::tcp::resolver::query::canonical_name);
|
||||
boost::asio::ip::tcp::resolver resolver(io_context_);
|
||||
boost::asio::ip::tcp::resolver::results_type results{};
|
||||
boost::system::error_code resolve_error;
|
||||
boost::asio::ip::tcp::resolver::iterator iterator;
|
||||
|
||||
try
|
||||
{
|
||||
//resolving ipv4 address as ipv6 throws, catch here and move on
|
||||
iterator = resolver.resolve(query, resolve_error);
|
||||
results = resolver.resolve(
|
||||
boost::asio::ip::tcp::v4(), adr, port, boost::asio::ip::tcp::resolver::canonical_name, resolve_error
|
||||
);
|
||||
}
|
||||
catch (const boost::system::system_error& e)
|
||||
{
|
||||
@@ -1819,8 +1882,7 @@ namespace net_utils
|
||||
throw;
|
||||
}
|
||||
|
||||
boost::asio::ip::tcp::resolver::iterator end;
|
||||
if(iterator == end)
|
||||
if(results.empty())
|
||||
{
|
||||
if (!try_ipv6)
|
||||
{
|
||||
@@ -1835,24 +1897,23 @@ namespace net_utils
|
||||
|
||||
if (try_ipv6)
|
||||
{
|
||||
boost::asio::ip::tcp::resolver::query query6(boost::asio::ip::tcp::v6(), adr, port, boost::asio::ip::tcp::resolver::query::canonical_name);
|
||||
results = resolver.resolve(
|
||||
boost::asio::ip::tcp::v6(), adr, port, boost::asio::ip::tcp::resolver::canonical_name, resolve_error
|
||||
);
|
||||
|
||||
iterator = resolver.resolve(query6, resolve_error);
|
||||
|
||||
if(iterator == end)
|
||||
if(results.empty())
|
||||
{
|
||||
_erro("Failed to resolve " << adr);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
boost::asio::ip::tcp::endpoint remote_endpoint(*iterator);
|
||||
boost::asio::ip::tcp::endpoint remote_endpoint(*results.begin());
|
||||
|
||||
sock_.open(remote_endpoint.protocol());
|
||||
if(bind_ip != "0.0.0.0" && bind_ip != "0" && bind_ip != "" )
|
||||
{
|
||||
boost::asio::ip::tcp::endpoint local_endpoint(boost::asio::ip::address::from_string(bind_ip.c_str()), 0);
|
||||
boost::asio::ip::tcp::endpoint local_endpoint(boost::asio::ip::make_address(bind_ip.c_str()), 0);
|
||||
boost::system::error_code ec;
|
||||
sock_.bind(local_endpoint, ec);
|
||||
if (ec)
|
||||
@@ -1864,7 +1925,7 @@ namespace net_utils
|
||||
}
|
||||
}
|
||||
|
||||
boost::shared_ptr<boost::asio::deadline_timer> sh_deadline(new boost::asio::deadline_timer(io_service_));
|
||||
boost::shared_ptr<boost::asio::deadline_timer> sh_deadline(new boost::asio::deadline_timer(io_context_));
|
||||
//start deadline
|
||||
sh_deadline->expires_from_now(boost::posix_time::milliseconds(conn_timeout));
|
||||
sh_deadline->async_wait([=](const boost::system::error_code& error)
|
||||
|
||||
@@ -112,21 +112,20 @@ class connection_basic { // not-templated base class for rapid developmet of som
|
||||
std::deque<byte_slice> m_send_que;
|
||||
volatile bool m_is_multithreaded;
|
||||
/// Strand to ensure the connection's handlers are not called concurrently.
|
||||
boost::asio::io_service::strand strand_;
|
||||
boost::asio::io_context::strand strand_;
|
||||
/// Socket for the connection.
|
||||
boost::asio::ssl::stream<boost::asio::ip::tcp::socket> socket_;
|
||||
ssl_support_t m_ssl_support;
|
||||
|
||||
public:
|
||||
// first counter is the ++/-- count of current sockets, the other socket_number is only-increasing ++ number generator
|
||||
connection_basic(boost::asio::ip::tcp::socket&& socket, std::shared_ptr<connection_basic_shared_state> state, ssl_support_t ssl_support);
|
||||
connection_basic(boost::asio::io_service &io_service, std::shared_ptr<connection_basic_shared_state> state, ssl_support_t ssl_support);
|
||||
connection_basic(boost::asio::io_context &context, boost::asio::ip::tcp::socket&& sock, std::shared_ptr<connection_basic_shared_state> state, ssl_support_t ssl_support);
|
||||
connection_basic(boost::asio::io_context &context, std::shared_ptr<connection_basic_shared_state> state, ssl_support_t ssl_support);
|
||||
|
||||
virtual ~connection_basic() noexcept(false);
|
||||
|
||||
//! \return `shared_state` object passed in construction (ptr never changes).
|
||||
connection_basic_shared_state& get_state() noexcept { return *m_state; /* verified in constructor */ }
|
||||
connection_basic(boost::asio::io_service& io_service, std::atomic<long> &ref_sock_count, std::atomic<long> &sock_number, ssl_support_t ssl);
|
||||
|
||||
boost::asio::ip::tcp::socket& socket() { return socket_.next_layer(); }
|
||||
ssl_support_t get_ssl_support() const { return m_ssl_support; }
|
||||
@@ -135,7 +134,7 @@ class connection_basic { // not-templated base class for rapid developmet of som
|
||||
bool handshake(boost::asio::ssl::stream_base::handshake_type type, boost::asio::const_buffer buffer = {})
|
||||
{
|
||||
//m_state != nullptr verified in constructor
|
||||
return m_state->ssl_options().handshake(socket_, type, buffer);
|
||||
return m_state->ssl_options().handshake(strand_.context(), socket_, type, buffer);
|
||||
}
|
||||
|
||||
template<typename MutableBufferSequence, typename ReadHandler>
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
|
||||
#include <boost/optional/optional.hpp>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include "net_utils_base.h"
|
||||
#include "http_auth.h"
|
||||
#include "http_base.h"
|
||||
@@ -54,8 +55,13 @@ namespace net_utils
|
||||
{
|
||||
std::string m_folder;
|
||||
std::vector<std::string> m_access_control_origins;
|
||||
std::unordered_map<std::string, std::size_t> m_connections;
|
||||
boost::optional<login> m_user;
|
||||
size_t m_max_content_length{std::numeric_limits<size_t>::max()};
|
||||
std::size_t m_connection_count{0};
|
||||
std::size_t m_max_public_ip_connections{3};
|
||||
std::size_t m_max_private_ip_connections{25};
|
||||
std::size_t m_max_connections{100};
|
||||
critical_section m_lock;
|
||||
};
|
||||
|
||||
@@ -70,7 +76,7 @@ namespace net_utils
|
||||
typedef http_server_config config_type;
|
||||
|
||||
simple_http_connection_handler(i_service_endpoint* psnd_hndlr, config_type& config, t_connection_context& conn_context);
|
||||
virtual ~simple_http_connection_handler(){}
|
||||
virtual ~simple_http_connection_handler();
|
||||
|
||||
bool release_protocol()
|
||||
{
|
||||
@@ -86,10 +92,7 @@ namespace net_utils
|
||||
{
|
||||
return true;
|
||||
}
|
||||
bool after_init_connection()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
bool after_init_connection();
|
||||
virtual bool handle_recv(const void* ptr, size_t cb);
|
||||
virtual bool handle_request(const http::http_request_info& query_info, http_response_info& response);
|
||||
|
||||
@@ -146,6 +149,7 @@ namespace net_utils
|
||||
protected:
|
||||
i_service_endpoint* m_psnd_hndlr;
|
||||
t_connection_context& m_conn_context;
|
||||
bool m_initialized;
|
||||
};
|
||||
|
||||
template<class t_connection_context>
|
||||
@@ -212,10 +216,6 @@ namespace net_utils
|
||||
}
|
||||
void handle_qued_callback()
|
||||
{}
|
||||
bool after_init_connection()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
//simple_http_connection_handler::config_type m_stub_config;
|
||||
|
||||
@@ -208,11 +208,46 @@ namespace net_utils
|
||||
m_newlines(0),
|
||||
m_bytes_read(0),
|
||||
m_psnd_hndlr(psnd_hndlr),
|
||||
m_conn_context(conn_context)
|
||||
m_conn_context(conn_context),
|
||||
m_initialized(false)
|
||||
{
|
||||
|
||||
}
|
||||
//--------------------------------------------------------------------------------------------
|
||||
template<class t_connection_context>
|
||||
simple_http_connection_handler<t_connection_context>::~simple_http_connection_handler()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (m_initialized)
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_config.m_lock);
|
||||
if (m_config.m_connection_count)
|
||||
--m_config.m_connection_count;
|
||||
auto elem = m_config.m_connections.find(m_conn_context.m_remote_address.host_str());
|
||||
if (elem != m_config.m_connections.end())
|
||||
{
|
||||
if (elem->second == 1 || elem->second == 0)
|
||||
m_config.m_connections.erase(elem);
|
||||
else
|
||||
--(elem->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{}
|
||||
}
|
||||
//--------------------------------------------------------------------------------------------
|
||||
template<class t_connection_context>
|
||||
bool simple_http_connection_handler<t_connection_context>::after_init_connection()
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_config.m_lock);
|
||||
++m_config.m_connections[m_conn_context.m_remote_address.host_str()];
|
||||
++m_config.m_connection_count;
|
||||
m_initialized = true;
|
||||
return true;
|
||||
}
|
||||
//--------------------------------------------------------------------------------------------
|
||||
template<class t_connection_context>
|
||||
bool simple_http_connection_handler<t_connection_context>::set_ready_state()
|
||||
{
|
||||
|
||||
@@ -71,7 +71,7 @@
|
||||
else if((query_info.m_URI == s_pattern) && (cond)) \
|
||||
{ \
|
||||
handled = true; \
|
||||
uint64_t ticks = misc_utils::get_tick_count(); \
|
||||
uint64_t ticks = epee::misc_utils::get_tick_count(); \
|
||||
boost::value_initialized<command_type::request> req; \
|
||||
bool parse_res = epee::serialization::load_t_from_json(static_cast<command_type::request&>(req), query_info.m_body); \
|
||||
if (!parse_res) \
|
||||
@@ -107,7 +107,7 @@
|
||||
else if(query_info.m_URI == s_pattern) \
|
||||
{ \
|
||||
handled = true; \
|
||||
uint64_t ticks = misc_utils::get_tick_count(); \
|
||||
uint64_t ticks = epee::misc_utils::get_tick_count(); \
|
||||
boost::value_initialized<command_type::request> req; \
|
||||
bool parse_res = epee::serialization::load_t_from_binary(static_cast<command_type::request&>(req), epee::strspan<uint8_t>(query_info.m_body)); \
|
||||
if (!parse_res) \
|
||||
@@ -117,7 +117,7 @@
|
||||
response_info.m_response_comment = "Bad request"; \
|
||||
return true; \
|
||||
} \
|
||||
uint64_t ticks1 = misc_utils::get_tick_count(); \
|
||||
uint64_t ticks1 = epee::misc_utils::get_tick_count(); \
|
||||
boost::value_initialized<command_type::response> resp;\
|
||||
MINFO(m_conn_context << "calling " << s_pattern); \
|
||||
bool res = false; \
|
||||
@@ -129,7 +129,7 @@
|
||||
response_info.m_response_comment = "Internal Server Error"; \
|
||||
return true; \
|
||||
} \
|
||||
uint64_t ticks2 = misc_utils::get_tick_count(); \
|
||||
uint64_t ticks2 = epee::misc_utils::get_tick_count(); \
|
||||
epee::byte_slice buffer; \
|
||||
epee::serialization::store_t_to_binary(static_cast<command_type::response&>(resp), buffer, 64 * 1024); \
|
||||
uint64_t ticks3 = epee::misc_utils::get_tick_count(); \
|
||||
@@ -171,6 +171,13 @@
|
||||
epee::serialization::store_t_to_json(static_cast<epee::json_rpc::error_response&>(rsp), response_info.m_body); \
|
||||
return true; \
|
||||
} \
|
||||
epee::serialization::storage_entry params_; \
|
||||
params_ = epee::serialization::storage_entry(epee::serialization::section()); \
|
||||
if(!ps.get_value("params", params_, nullptr)) \
|
||||
{ \
|
||||
epee::serialization::section params_section; \
|
||||
ps.set_value("params", std::move(params_section), nullptr); \
|
||||
} \
|
||||
if(false) return true; //just a stub to have "else if"
|
||||
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include <boost/thread.hpp>
|
||||
#include <boost/bind/bind.hpp>
|
||||
|
||||
#include "cryptonote_config.h"
|
||||
#include "net/abstract_tcp_server2.h"
|
||||
#include "http_protocol_handler.h"
|
||||
#include "net/http_server_handlers_map2.h"
|
||||
@@ -44,7 +45,8 @@ namespace epee
|
||||
{
|
||||
|
||||
template<class t_child_class, class t_connection_context = epee::net_utils::connection_context_base>
|
||||
class http_server_impl_base: public net_utils::http::i_http_server_handler<t_connection_context>
|
||||
class http_server_impl_base: public net_utils::http::i_http_server_handler<t_connection_context>,
|
||||
net_utils::i_connection_limit
|
||||
{
|
||||
|
||||
public:
|
||||
@@ -52,7 +54,7 @@ namespace epee
|
||||
: m_net_server(epee::net_utils::e_connection_type_RPC)
|
||||
{}
|
||||
|
||||
explicit http_server_impl_base(boost::asio::io_service& external_io_service)
|
||||
explicit http_server_impl_base(boost::asio::io_context& external_io_service)
|
||||
: m_net_server(external_io_service)
|
||||
{}
|
||||
|
||||
@@ -60,8 +62,16 @@ namespace epee
|
||||
const std::string& bind_ipv6_address = "::", bool use_ipv6 = false, bool require_ipv4 = true,
|
||||
std::vector<std::string> access_control_origins = std::vector<std::string>(),
|
||||
boost::optional<net_utils::http::login> user = boost::none,
|
||||
net_utils::ssl_options_t ssl_options = net_utils::ssl_support_t::e_ssl_support_autodetect)
|
||||
net_utils::ssl_options_t ssl_options = net_utils::ssl_support_t::e_ssl_support_autodetect,
|
||||
const std::size_t max_public_ip_connections = DEFAULT_RPC_MAX_CONNECTIONS_PER_PUBLIC_IP,
|
||||
const std::size_t max_private_ip_connections = DEFAULT_RPC_MAX_CONNECTIONS_PER_PRIVATE_IP,
|
||||
const std::size_t max_connections = DEFAULT_RPC_MAX_CONNECTIONS,
|
||||
const std::size_t response_soft_limit = DEFAULT_RPC_SOFT_LIMIT_SIZE)
|
||||
{
|
||||
if (max_connections < max_public_ip_connections)
|
||||
throw std::invalid_argument{"Max public IP connections cannot be more than max connections"};
|
||||
if (max_connections < max_private_ip_connections)
|
||||
throw std::invalid_argument{"Max private IP connections cannot be more than max connections"};
|
||||
|
||||
//set self as callback handler
|
||||
m_net_server.get_config_object().m_phandler = static_cast<t_child_class*>(this);
|
||||
@@ -75,6 +85,11 @@ namespace epee
|
||||
m_net_server.get_config_object().m_access_control_origins = std::move(access_control_origins);
|
||||
|
||||
m_net_server.get_config_object().m_user = std::move(user);
|
||||
m_net_server.get_config_object().m_max_public_ip_connections = max_public_ip_connections;
|
||||
m_net_server.get_config_object().m_max_private_ip_connections = max_private_ip_connections;
|
||||
m_net_server.get_config_object().m_max_connections = max_connections;
|
||||
m_net_server.set_response_soft_limit(response_soft_limit);
|
||||
m_net_server.set_connection_limit(this);
|
||||
|
||||
MGINFO("Binding on " << bind_ip << " (IPv4):" << bind_port);
|
||||
if (use_ipv6)
|
||||
@@ -131,6 +146,26 @@ namespace epee
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
virtual bool is_host_limit(const net_utils::network_address& na) override final
|
||||
{
|
||||
auto& config = m_net_server.get_config_object();
|
||||
CRITICAL_REGION_LOCAL(config.m_lock);
|
||||
if (config.m_max_connections <= config.m_connection_count)
|
||||
return true;
|
||||
|
||||
const bool is_private = na.is_loopback() || na.is_local();
|
||||
const auto elem = config.m_connections.find(na.host_str());
|
||||
if (elem != config.m_connections.end())
|
||||
{
|
||||
if (is_private)
|
||||
return config.m_max_private_ip_connections <= elem->second;
|
||||
else
|
||||
return config.m_max_public_ip_connections <= elem->second;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
net_utils::boosted_tcp_server<net_utils::http::http_custom_handler<t_connection_context> > m_net_server;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -200,7 +200,7 @@ public:
|
||||
struct anvoke_handler: invoke_response_handler_base
|
||||
{
|
||||
anvoke_handler(const callback_t& cb, uint64_t timeout, async_protocol_handler& con, int command)
|
||||
:m_cb(cb), m_timeout(timeout), m_con(con), m_timer(con.m_pservice_endpoint->get_io_service()), m_timer_started(false),
|
||||
:m_cb(cb), m_timeout(timeout), m_con(con), m_timer(con.m_pservice_endpoint->get_io_context()), m_timer_started(false),
|
||||
m_cancel_timer_called(false), m_timer_cancelled(false), m_command(command)
|
||||
{
|
||||
if(m_con.start_outer_call())
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
#include <atomic>
|
||||
#include <string>
|
||||
#include <boost/version.hpp>
|
||||
#include <boost/asio/io_service.hpp>
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <boost/asio/read.hpp>
|
||||
#include <boost/asio/ssl.hpp>
|
||||
@@ -158,11 +158,11 @@ namespace net_utils
|
||||
inline
|
||||
try_connect_result_t try_connect(const std::string& addr, const std::string& port, std::chrono::milliseconds timeout)
|
||||
{
|
||||
m_deadline.expires_from_now(timeout);
|
||||
m_deadline.expires_after(timeout);
|
||||
boost::unique_future<boost::asio::ip::tcp::socket> connection = m_connector(addr, port, m_deadline);
|
||||
for (;;)
|
||||
{
|
||||
m_io_service.reset();
|
||||
m_io_service.restart();
|
||||
m_io_service.run_one();
|
||||
|
||||
if (connection.is_ready())
|
||||
@@ -178,7 +178,7 @@ namespace net_utils
|
||||
// SSL Options
|
||||
if (m_ssl_options.support == epee::net_utils::ssl_support_t::e_ssl_support_enabled || m_ssl_options.support == epee::net_utils::ssl_support_t::e_ssl_support_autodetect)
|
||||
{
|
||||
if (!m_ssl_options.handshake(*m_ssl_socket, boost::asio::ssl::stream_base::client, {}, addr, timeout))
|
||||
if (!m_ssl_options.handshake(m_io_service, *m_ssl_socket, boost::asio::ssl::stream_base::client, {}, addr, timeout))
|
||||
{
|
||||
if (m_ssl_options.support == epee::net_utils::ssl_support_t::e_ssl_support_autodetect)
|
||||
{
|
||||
@@ -285,7 +285,7 @@ namespace net_utils
|
||||
|
||||
try
|
||||
{
|
||||
m_deadline.expires_from_now(timeout);
|
||||
m_deadline.expires_after(timeout);
|
||||
|
||||
// Set up the variable that receives the result of the asynchronous
|
||||
// operation. The error code is set to would_block to signal that the
|
||||
@@ -303,7 +303,7 @@ namespace net_utils
|
||||
// Block until the asynchronous operation has completed.
|
||||
while (ec == boost::asio::error::would_block)
|
||||
{
|
||||
m_io_service.reset();
|
||||
m_io_service.restart();
|
||||
m_io_service.run_one();
|
||||
}
|
||||
|
||||
@@ -409,7 +409,7 @@ namespace net_utils
|
||||
// Set a deadline for the asynchronous operation. Since this function uses
|
||||
// a composed operation (async_read_until), the deadline applies to the
|
||||
// entire operation, rather than individual reads from the socket.
|
||||
m_deadline.expires_from_now(timeout);
|
||||
m_deadline.expires_after(timeout);
|
||||
|
||||
// Set up the variable that receives the result of the asynchronous
|
||||
// operation. The error code is set to would_block to signal that the
|
||||
@@ -436,7 +436,7 @@ namespace net_utils
|
||||
// Block until the asynchronous operation has completed.
|
||||
while (ec == boost::asio::error::would_block && !m_shutdowned)
|
||||
{
|
||||
m_io_service.reset();
|
||||
m_io_service.restart();
|
||||
m_io_service.run_one();
|
||||
}
|
||||
|
||||
@@ -495,7 +495,7 @@ namespace net_utils
|
||||
// Set a deadline for the asynchronous operation. Since this function uses
|
||||
// a composed operation (async_read_until), the deadline applies to the
|
||||
// entire operation, rather than individual reads from the socket.
|
||||
m_deadline.expires_from_now(timeout);
|
||||
m_deadline.expires_after(timeout);
|
||||
|
||||
// Set up the variable that receives the result of the asynchronous
|
||||
// operation. The error code is set to would_block to signal that the
|
||||
@@ -580,7 +580,7 @@ namespace net_utils
|
||||
return true;
|
||||
}
|
||||
|
||||
boost::asio::io_service& get_io_service()
|
||||
boost::asio::io_context& get_io_service()
|
||||
{
|
||||
return m_io_service;
|
||||
}
|
||||
@@ -607,7 +607,7 @@ namespace net_utils
|
||||
// Check whether the deadline has passed. We compare the deadline against
|
||||
// the current time since a new asynchronous operation may have moved the
|
||||
// deadline before this actor had a chance to run.
|
||||
if (m_deadline.expires_at() <= std::chrono::steady_clock::now())
|
||||
if (m_deadline.expiry() <= std::chrono::steady_clock::now())
|
||||
{
|
||||
// The deadline has passed. The socket is closed so that any outstanding
|
||||
// asynchronous operations are cancelled. This allows the blocked
|
||||
@@ -628,11 +628,11 @@ namespace net_utils
|
||||
void shutdown_ssl() {
|
||||
// ssl socket shutdown blocks if server doesn't respond. We close after 2 secs
|
||||
boost::system::error_code ec = boost::asio::error::would_block;
|
||||
m_deadline.expires_from_now(std::chrono::milliseconds(2000));
|
||||
m_deadline.expires_after(std::chrono::milliseconds(2000));
|
||||
m_ssl_socket->async_shutdown(boost::lambda::var(ec) = boost::lambda::_1);
|
||||
while (ec == boost::asio::error::would_block)
|
||||
{
|
||||
m_io_service.reset();
|
||||
m_io_service.restart();
|
||||
m_io_service.run_one();
|
||||
}
|
||||
// Ignore "short read" error
|
||||
@@ -676,7 +676,7 @@ namespace net_utils
|
||||
}
|
||||
|
||||
protected:
|
||||
boost::asio::io_service m_io_service;
|
||||
boost::asio::io_context m_io_service;
|
||||
boost::asio::ssl::context m_ctx;
|
||||
std::shared_ptr<boost::asio::ssl::stream<boost::asio::ip::tcp::socket>> m_ssl_socket;
|
||||
std::function<connect_func> m_connector;
|
||||
@@ -688,119 +688,6 @@ namespace net_utils
|
||||
std::atomic<uint64_t> m_bytes_sent;
|
||||
std::atomic<uint64_t> m_bytes_received;
|
||||
};
|
||||
|
||||
|
||||
/************************************************************************/
|
||||
/* */
|
||||
/************************************************************************/
|
||||
class async_blocked_mode_client: public blocked_mode_client
|
||||
{
|
||||
public:
|
||||
async_blocked_mode_client():m_send_deadline(blocked_mode_client::m_io_service)
|
||||
{
|
||||
|
||||
// No deadline is required until the first socket operation is started. We
|
||||
// set the deadline to positive infinity so that the actor takes no action
|
||||
// until a specific deadline is set.
|
||||
m_send_deadline.expires_at(boost::posix_time::pos_infin);
|
||||
|
||||
// Start the persistent actor that checks for deadline expiry.
|
||||
check_send_deadline();
|
||||
}
|
||||
~async_blocked_mode_client()
|
||||
{
|
||||
m_send_deadline.cancel();
|
||||
}
|
||||
|
||||
bool shutdown()
|
||||
{
|
||||
blocked_mode_client::shutdown();
|
||||
m_send_deadline.cancel();
|
||||
return true;
|
||||
}
|
||||
|
||||
inline
|
||||
bool send(const void* data, size_t sz)
|
||||
{
|
||||
try
|
||||
{
|
||||
/*
|
||||
m_send_deadline.expires_from_now(boost::posix_time::milliseconds(m_reciev_timeout));
|
||||
|
||||
// Set up the variable that receives the result of the asynchronous
|
||||
// operation. The error code is set to would_block to signal that the
|
||||
// operation is incomplete. Asio guarantees that its asynchronous
|
||||
// operations will never fail with would_block, so any other value in
|
||||
// ec indicates completion.
|
||||
boost::system::error_code ec = boost::asio::error::would_block;
|
||||
|
||||
// Start the asynchronous operation itself. The boost::lambda function
|
||||
// object is used as a callback and will update the ec variable when the
|
||||
// operation completes. The blocking_udp_client.cpp example shows how you
|
||||
// can use boost::bind rather than boost::lambda.
|
||||
boost::asio::async_write(m_socket, boost::asio::buffer(data, sz), boost::lambda::var(ec) = boost::lambda::_1);
|
||||
|
||||
// Block until the asynchronous operation has completed.
|
||||
while(ec == boost::asio::error::would_block)
|
||||
{
|
||||
m_io_service.run_one();
|
||||
}*/
|
||||
|
||||
boost::system::error_code ec;
|
||||
|
||||
size_t writen = write(data, sz, ec);
|
||||
|
||||
if (!writen || ec)
|
||||
{
|
||||
LOG_PRINT_L3("Problems at write: " << ec.message());
|
||||
return false;
|
||||
}else
|
||||
{
|
||||
m_send_deadline.expires_at(boost::posix_time::pos_infin);
|
||||
}
|
||||
}
|
||||
|
||||
catch(const boost::system::system_error& er)
|
||||
{
|
||||
LOG_ERROR("Some problems at connect, message: " << er.what());
|
||||
return false;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
LOG_ERROR("Some fatal problems.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
boost::asio::deadline_timer m_send_deadline;
|
||||
|
||||
void check_send_deadline()
|
||||
{
|
||||
// Check whether the deadline has passed. We compare the deadline against
|
||||
// the current time since a new asynchronous operation may have moved the
|
||||
// deadline before this actor had a chance to run.
|
||||
if (m_send_deadline.expires_at() <= boost::asio::deadline_timer::traits_type::now())
|
||||
{
|
||||
// The deadline has passed. The socket is closed so that any outstanding
|
||||
// asynchronous operations are cancelled. This allows the blocked
|
||||
// connect(), read_line() or write_line() functions to return.
|
||||
LOG_PRINT_L3("Timed out socket");
|
||||
m_ssl_socket->next_layer().close();
|
||||
|
||||
// There is no longer an active deadline. The expiry is set to positive
|
||||
// infinity so that the actor takes no action until a new deadline is set.
|
||||
m_send_deadline.expires_at(boost::posix_time::pos_infin);
|
||||
}
|
||||
|
||||
// Put the actor back to sleep.
|
||||
m_send_deadline.async_wait(boost::bind(&async_blocked_mode_client::check_send_deadline, this));
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <boost/utility/string_ref.hpp>
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <boost/asio/ssl.hpp>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
@@ -125,6 +126,7 @@ namespace net_utils
|
||||
\note It is strongly encouraged that clients using `system_ca`
|
||||
verification provide a non-empty `host` for rfc2818 verification.
|
||||
|
||||
\param io_context associated with `socket`.
|
||||
\param socket Used in SSL handshake and verification
|
||||
\param type Client or server
|
||||
\param host This parameter is only used when
|
||||
@@ -136,6 +138,7 @@ namespace net_utils
|
||||
\return True if the SSL handshake completes with peer verification
|
||||
settings. */
|
||||
bool handshake(
|
||||
boost::asio::io_context& io_context,
|
||||
boost::asio::ssl::stream<boost::asio::ip::tcp::socket> &socket,
|
||||
boost::asio::ssl::stream_base::handshake_type type,
|
||||
boost::asio::const_buffer buffer = {},
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
#define _NET_UTILS_BASE_H_
|
||||
|
||||
#include <boost/uuid/uuid.hpp>
|
||||
#include <boost/asio/io_service.hpp>
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <boost/asio/ip/address_v6.hpp>
|
||||
#include <typeinfo>
|
||||
#include <type_traits>
|
||||
@@ -47,10 +47,12 @@
|
||||
#define MAKE_IP( a1, a2, a3, a4 ) (a1|(a2<<8)|(a3<<16)|(((uint32_t)a4)<<24))
|
||||
#endif
|
||||
|
||||
/* Use the below function carefully. The executor and io_context are slightly
|
||||
different concepts. */
|
||||
#if BOOST_VERSION >= 107000
|
||||
#define GET_IO_SERVICE(s) ((boost::asio::io_context&)(s).get_executor().context())
|
||||
#define MONERO_GET_EXECUTOR(type) type . get_executor()
|
||||
#else
|
||||
#define GET_IO_SERVICE(s) ((s).get_io_service())
|
||||
#define MONERO_GET_EXECUTOR(type) type . get_io_context()
|
||||
#endif
|
||||
|
||||
namespace net
|
||||
@@ -443,7 +445,7 @@ namespace net_utils
|
||||
virtual bool send_done()=0;
|
||||
virtual bool call_run_once_service_io()=0;
|
||||
virtual bool request_callback()=0;
|
||||
virtual boost::asio::io_service& get_io_service()=0;
|
||||
virtual boost::asio::io_context& get_io_context()=0;
|
||||
//protect from deletion connection object(with protocol instance) during external call "invoke"
|
||||
virtual bool add_ref()=0;
|
||||
virtual bool release()=0;
|
||||
|
||||
@@ -46,13 +46,13 @@ namespace net_utils
|
||||
|
||||
|
||||
class network_throttle : public i_network_throttle {
|
||||
private:
|
||||
public:
|
||||
struct packet_info {
|
||||
size_t m_size; // octets sent. Summary for given small-window (e.g. for all packaged in 1 second)
|
||||
packet_info();
|
||||
};
|
||||
|
||||
|
||||
private:
|
||||
network_speed_bps m_target_speed;
|
||||
size_t m_network_add_cost; // estimated add cost of headers
|
||||
size_t m_network_minimal_segment; // estimated minimal cost of sending 1 byte to round up to
|
||||
|
||||
@@ -98,16 +98,18 @@ public: \
|
||||
#define KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE_N(varialble, val_name) \
|
||||
epee::serialization::selector<is_store>::serialize_t_val_as_blob(this_ref.varialble, stg, hparent_section, val_name);
|
||||
|
||||
#define KV_SERIALIZE_VAL_POD_AS_BLOB_N(varialble, val_name) \
|
||||
static_assert(std::is_pod<decltype(this_ref.varialble)>::value, "t_type must be a POD type."); \
|
||||
KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE_N(varialble, val_name)
|
||||
#define KV_SERIALIZE_VAL_POD_AS_BLOB_N(variable, val_name) \
|
||||
static_assert(std::is_trivially_copyable<decltype(this_ref.variable)>(), "t_type must be a trivially copyable type."); \
|
||||
static_assert(std::is_standard_layout<decltype(this_ref.variable)>(), "t_type must be a standard layout type."); \
|
||||
KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE_N(variable, val_name)
|
||||
|
||||
#define KV_SERIALIZE_VAL_POD_AS_BLOB_OPT_N(varialble, val_name, default_value) \
|
||||
#define KV_SERIALIZE_VAL_POD_AS_BLOB_OPT_N(variable, val_name, default_value) \
|
||||
do { \
|
||||
static_assert(std::is_pod<decltype(this_ref.varialble)>::value, "t_type must be a POD type."); \
|
||||
bool ret = KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE_N(varialble, val_name); \
|
||||
static_assert(std::is_trivially_copyable<decltype(this_ref.variable)>(), "t_type must be a trivially copyable type."); \
|
||||
static_assert(std::is_standard_layout<decltype(this_ref.variable)>(), "t_type must be a standard layout type."); \
|
||||
bool ret = KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE_N(variable, val_name) \
|
||||
if (!ret) \
|
||||
epee::serialize_default(this_ref.varialble, default_value); \
|
||||
epee::serialize_default(this_ref.variable, default_value); \
|
||||
} while(0);
|
||||
|
||||
#define KV_SERIALIZE_CONTAINER_POD_AS_BLOB_N(varialble, val_name) \
|
||||
@@ -118,7 +120,7 @@ public: \
|
||||
#define KV_SERIALIZE(varialble) KV_SERIALIZE_N(varialble, #varialble)
|
||||
#define KV_SERIALIZE_VAL_POD_AS_BLOB(varialble) KV_SERIALIZE_VAL_POD_AS_BLOB_N(varialble, #varialble)
|
||||
#define KV_SERIALIZE_VAL_POD_AS_BLOB_OPT(varialble, def) KV_SERIALIZE_VAL_POD_AS_BLOB_OPT_N(varialble, #varialble, def)
|
||||
#define KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE(varialble) KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE_N(varialble, #varialble) //skip is_pod compile time check
|
||||
#define KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE(varialble) KV_SERIALIZE_VAL_POD_AS_BLOB_FORCE_N(varialble, #varialble) //skip is_trivially_copyable and is_standard_layout compile time check
|
||||
#define KV_SERIALIZE_CONTAINER_POD_AS_BLOB(varialble) KV_SERIALIZE_CONTAINER_POD_AS_BLOB_N(varialble, #varialble)
|
||||
#define KV_SERIALIZE_OPT(variable,default_value) KV_SERIALIZE_OPT_N(variable, #variable, default_value)
|
||||
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <set>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
|
||||
+13
-10
@@ -133,17 +133,14 @@ namespace epee
|
||||
return {src.data(), src.size()};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool has_padding() noexcept
|
||||
{
|
||||
return !std::is_standard_layout<T>() || alignof(T) != 1;
|
||||
}
|
||||
|
||||
//! \return Cast data from `src` as `span<const std::uint8_t>`.
|
||||
template<typename T>
|
||||
span<const std::uint8_t> to_byte_span(const span<const T> src) noexcept
|
||||
{
|
||||
static_assert(!has_padding<T>(), "source type may have padding");
|
||||
static_assert(!std::is_empty<T>(), "empty value types will not work -> sizeof == 1");
|
||||
static_assert(std::is_standard_layout<T>(), "type must have standard layout");
|
||||
static_assert(std::is_trivially_copyable<T>(), "type must be trivially copyable");
|
||||
static_assert(alignof(T) == 1, "type may have padding");
|
||||
return {reinterpret_cast<const std::uint8_t*>(src.data()), src.size_bytes()};
|
||||
}
|
||||
|
||||
@@ -153,7 +150,9 @@ namespace epee
|
||||
{
|
||||
using value_type = typename T::value_type;
|
||||
static_assert(!std::is_empty<value_type>(), "empty value types will not work -> sizeof == 1");
|
||||
static_assert(!has_padding<value_type>(), "source value type may have padding");
|
||||
static_assert(std::is_standard_layout<value_type>(), "value type must have standard layout");
|
||||
static_assert(std::is_trivially_copyable<value_type>(), "value type must be trivially copyable");
|
||||
static_assert(alignof(value_type) == 1, "value type may have padding");
|
||||
return {reinterpret_cast<std::uint8_t*>(src.data()), src.size() * sizeof(value_type)};
|
||||
}
|
||||
|
||||
@@ -162,7 +161,9 @@ namespace epee
|
||||
span<const std::uint8_t> as_byte_span(const T& src) noexcept
|
||||
{
|
||||
static_assert(!std::is_empty<T>(), "empty types will not work -> sizeof == 1");
|
||||
static_assert(!has_padding<T>(), "source type may have padding");
|
||||
static_assert(std::is_standard_layout<T>(), "type must have standard layout");
|
||||
static_assert(std::is_trivially_copyable<T>(), "type must be trivially copyable");
|
||||
static_assert(alignof(T) == 1, "type may have padding");
|
||||
return {reinterpret_cast<const std::uint8_t*>(std::addressof(src)), sizeof(T)};
|
||||
}
|
||||
|
||||
@@ -171,7 +172,9 @@ namespace epee
|
||||
span<std::uint8_t> as_mut_byte_span(T& src) noexcept
|
||||
{
|
||||
static_assert(!std::is_empty<T>(), "empty types will not work -> sizeof == 1");
|
||||
static_assert(!has_padding<T>(), "source type may have padding");
|
||||
static_assert(std::is_standard_layout<T>(), "type must have standard layout");
|
||||
static_assert(std::is_trivially_copyable<T>(), "type must be trivially copyable");
|
||||
static_assert(alignof(T) == 1, "type may have padding");
|
||||
return {reinterpret_cast<std::uint8_t*>(std::addressof(src)), sizeof(T)};
|
||||
}
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
|
||||
#include <boost/numeric/conversion/bounds.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/numeric/conversion/bounds.hpp>
|
||||
#include <typeinfo>
|
||||
#include <iomanip>
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "mlocker.h"
|
||||
|
||||
#include <boost/utility/string_ref.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
@@ -69,23 +70,17 @@ namespace string_tools
|
||||
#ifdef _WIN32
|
||||
std::string get_current_module_path();
|
||||
#endif
|
||||
bool set_module_name_and_folder(const std::string& path_to_process_);
|
||||
bool trim_left(std::string& str);
|
||||
bool trim_right(std::string& str);
|
||||
void set_module_name_and_folder(const std::string& path_to_process_);
|
||||
//----------------------------------------------------------------------------
|
||||
inline std::string& trim(std::string& str)
|
||||
{
|
||||
trim_left(str);
|
||||
trim_right(str);
|
||||
boost::trim(str);
|
||||
return str;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
inline std::string trim(const std::string& str_)
|
||||
inline std::string trim(const std::string& str)
|
||||
{
|
||||
std::string str = str_;
|
||||
trim_left(str);
|
||||
trim_right(str);
|
||||
return str;
|
||||
return boost::trim_copy(str);
|
||||
}
|
||||
std::string pad_string(std::string s, size_t n, char c = ' ', bool prepend = false);
|
||||
|
||||
@@ -94,6 +89,7 @@ namespace string_tools
|
||||
std::string pod_to_hex(const t_pod_type& s)
|
||||
{
|
||||
static_assert(std::is_standard_layout<t_pod_type>(), "expected standard layout type");
|
||||
static_assert(alignof(t_pod_type) == 1, "type may have padding");
|
||||
return to_hex::string(as_byte_span(s));
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -101,6 +97,8 @@ namespace string_tools
|
||||
bool hex_to_pod(const boost::string_ref hex_str, t_pod_type& s)
|
||||
{
|
||||
static_assert(std::is_standard_layout<t_pod_type>(), "expected standard layout type");
|
||||
static_assert(alignof(t_pod_type) == 1, "type may have padding");
|
||||
static_assert(std::is_trivially_copyable<t_pod_type>(), "type must be trivially copyable");
|
||||
return from_hex::to_buffer(as_mut_byte_span(s), hex_str);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
@@ -135,6 +135,13 @@ namespace http
|
||||
http::url_content parsed{};
|
||||
const bool r = parse_url(address, parsed);
|
||||
CHECK_AND_ASSERT_MES(r, false, "failed to parse url: " << address);
|
||||
if (parsed.port == 0)
|
||||
{
|
||||
if (parsed.schema == "http")
|
||||
parsed.port = 80;
|
||||
else if (parsed.schema == "https")
|
||||
parsed.port = 443;
|
||||
}
|
||||
set_server(std::move(parsed.host), std::to_string(parsed.port), std::move(user), std::move(ssl_options));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -152,7 +152,11 @@ namespace epee
|
||||
{
|
||||
std::size_t space_needed = 0;
|
||||
for (const auto& source : sources)
|
||||
{
|
||||
if (std::numeric_limits<std::size_t>::max() - space_needed < source.size())
|
||||
throw std::bad_alloc{};
|
||||
space_needed += source.size();
|
||||
}
|
||||
|
||||
if (space_needed)
|
||||
{
|
||||
@@ -162,9 +166,9 @@ namespace epee
|
||||
|
||||
for (const auto& source : sources)
|
||||
{
|
||||
assert(source.size() <= out.size()); // see check above
|
||||
std::memcpy(out.data(), source.data(), source.size());
|
||||
if (out.remove_prefix(source.size()) < source.size())
|
||||
throw std::bad_alloc{}; // size_t overflow on space_needed
|
||||
out.remove_prefix(source.size());
|
||||
}
|
||||
storage_ = std::move(storage);
|
||||
}
|
||||
|
||||
@@ -46,12 +46,6 @@
|
||||
// TODO:
|
||||
#include "net/network_throttle-detail.hpp"
|
||||
|
||||
#if BOOST_VERSION >= 107000
|
||||
#define GET_IO_SERVICE(s) ((boost::asio::io_context&)(s).get_executor().context())
|
||||
#else
|
||||
#define GET_IO_SERVICE(s) ((s).get_io_service())
|
||||
#endif
|
||||
|
||||
#undef MONERO_DEFAULT_LOG_CATEGORY
|
||||
#define MONERO_DEFAULT_LOG_CATEGORY "net.conn"
|
||||
|
||||
@@ -127,12 +121,12 @@ connection_basic_pimpl::connection_basic_pimpl(const std::string &name) : m_thro
|
||||
int connection_basic_pimpl::m_default_tos;
|
||||
|
||||
// methods:
|
||||
connection_basic::connection_basic(boost::asio::ip::tcp::socket&& sock, std::shared_ptr<connection_basic_shared_state> state, ssl_support_t ssl_support)
|
||||
connection_basic::connection_basic(boost::asio::io_context &io_context, boost::asio::ip::tcp::socket&& sock, std::shared_ptr<connection_basic_shared_state> state, ssl_support_t ssl_support)
|
||||
:
|
||||
m_state(std::move(state)),
|
||||
mI( new connection_basic_pimpl("peer") ),
|
||||
strand_(GET_IO_SERVICE(sock)),
|
||||
socket_(GET_IO_SERVICE(sock), get_context(m_state.get())),
|
||||
strand_(io_context),
|
||||
socket_(io_context, get_context(m_state.get())),
|
||||
m_want_close_connection(false),
|
||||
m_was_shutdown(false),
|
||||
m_is_multithreaded(false),
|
||||
@@ -152,12 +146,12 @@ connection_basic::connection_basic(boost::asio::ip::tcp::socket&& sock, std::sha
|
||||
_note("Spawned connection #"<<mI->m_peer_number<<" to " << remote_addr_str << " currently we have sockets count:" << m_state->sock_count);
|
||||
}
|
||||
|
||||
connection_basic::connection_basic(boost::asio::io_service &io_service, std::shared_ptr<connection_basic_shared_state> state, ssl_support_t ssl_support)
|
||||
connection_basic::connection_basic(boost::asio::io_context &io_context, std::shared_ptr<connection_basic_shared_state> state, ssl_support_t ssl_support)
|
||||
:
|
||||
m_state(std::move(state)),
|
||||
mI( new connection_basic_pimpl("peer") ),
|
||||
strand_(io_service),
|
||||
socket_(io_service, get_context(m_state.get())),
|
||||
strand_(io_context),
|
||||
socket_(io_context, get_context(m_state.get())),
|
||||
m_want_close_connection(false),
|
||||
m_was_shutdown(false),
|
||||
m_is_multithreaded(false),
|
||||
|
||||
@@ -176,11 +176,12 @@ void mlog_configure(const std::string &filename_base, bool console, const std::s
|
||||
std::vector<boost::filesystem::path> found_files;
|
||||
const boost::filesystem::directory_iterator end_itr;
|
||||
const boost::filesystem::path filename_base_path(filename_base);
|
||||
const std::string filename_base_name = filename_base_path.filename().string();
|
||||
const boost::filesystem::path parent_path = filename_base_path.has_parent_path() ? filename_base_path.parent_path() : ".";
|
||||
for (boost::filesystem::directory_iterator iter(parent_path); iter != end_itr; ++iter)
|
||||
{
|
||||
const std::string filename = iter->path().string();
|
||||
if (filename.size() >= filename_base.size() && std::memcmp(filename.data(), filename_base.data(), filename_base.size()) == 0)
|
||||
const std::string filename = iter->path().filename().string();
|
||||
if (filename.size() >= filename_base_name.size() && std::memcmp(filename.data(), filename_base_name.data(), filename_base_name.size()) == 0)
|
||||
{
|
||||
found_files.push_back(iter->path());
|
||||
}
|
||||
|
||||
@@ -4,22 +4,38 @@ namespace epee
|
||||
{
|
||||
namespace net_utils
|
||||
{
|
||||
namespace
|
||||
{
|
||||
struct new_connection
|
||||
{
|
||||
boost::promise<boost::asio::ip::tcp::socket> result_;
|
||||
boost::asio::ip::tcp::socket socket_;
|
||||
|
||||
template<typename T>
|
||||
explicit new_connection(T&& executor)
|
||||
: result_(), socket_(std::forward<T>(executor))
|
||||
{}
|
||||
};
|
||||
}
|
||||
|
||||
boost::unique_future<boost::asio::ip::tcp::socket>
|
||||
direct_connect::operator()(const std::string& addr, const std::string& port, boost::asio::steady_timer& timeout) const
|
||||
{
|
||||
// Get a list of endpoints corresponding to the server name.
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
boost::asio::ip::tcp::resolver resolver(GET_IO_SERVICE(timeout));
|
||||
boost::asio::ip::tcp::resolver::query query(boost::asio::ip::tcp::v4(), addr, port, boost::asio::ip::tcp::resolver::query::canonical_name);
|
||||
boost::asio::ip::tcp::resolver resolver(MONERO_GET_EXECUTOR(timeout));
|
||||
|
||||
bool try_ipv6 = false;
|
||||
boost::asio::ip::tcp::resolver::iterator iterator;
|
||||
boost::asio::ip::tcp::resolver::iterator end;
|
||||
boost::asio::ip::tcp::resolver::results_type results{};
|
||||
boost::system::error_code resolve_error;
|
||||
|
||||
try
|
||||
{
|
||||
iterator = resolver.resolve(query, resolve_error);
|
||||
if(iterator == end) // Documentation states that successful call is guaranteed to be non-empty
|
||||
results = resolver.resolve(
|
||||
boost::asio::ip::tcp::v4(), addr, port, boost::asio::ip::tcp::resolver::canonical_name, resolve_error
|
||||
);
|
||||
|
||||
if (results.empty())
|
||||
{
|
||||
// if IPv4 resolution fails, try IPv6. Unintentional outgoing IPv6 connections should only
|
||||
// be possible if for some reason a hostname was given and that hostname fails IPv4 resolution,
|
||||
@@ -37,27 +53,20 @@ namespace net_utils
|
||||
}
|
||||
try_ipv6 = true;
|
||||
}
|
||||
|
||||
if (try_ipv6)
|
||||
{
|
||||
boost::asio::ip::tcp::resolver::query query6(boost::asio::ip::tcp::v6(), addr, port, boost::asio::ip::tcp::resolver::query::canonical_name);
|
||||
iterator = resolver.resolve(query6);
|
||||
if (iterator == end)
|
||||
results = resolver.resolve(
|
||||
boost::asio::ip::tcp::v6(), addr, port, boost::asio::ip::tcp::resolver::canonical_name
|
||||
);
|
||||
if (results.empty())
|
||||
throw boost::system::system_error{boost::asio::error::fault, "Failed to resolve " + addr};
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct new_connection
|
||||
{
|
||||
boost::promise<boost::asio::ip::tcp::socket> result_;
|
||||
boost::asio::ip::tcp::socket socket_;
|
||||
|
||||
explicit new_connection(boost::asio::io_service& io_service)
|
||||
: result_(), socket_(io_service)
|
||||
{}
|
||||
};
|
||||
|
||||
const auto shared = std::make_shared<new_connection>(GET_IO_SERVICE(timeout));
|
||||
const auto shared = std::make_shared<new_connection>(MONERO_GET_EXECUTOR(timeout));
|
||||
timeout.async_wait([shared] (boost::system::error_code error)
|
||||
{
|
||||
if (error != boost::system::errc::operation_canceled && shared && shared->socket_.is_open())
|
||||
@@ -66,7 +75,7 @@ namespace net_utils
|
||||
shared->socket_.close();
|
||||
}
|
||||
});
|
||||
shared->socket_.async_connect(*iterator, [shared] (boost::system::error_code error)
|
||||
shared->socket_.async_connect(*results.begin(), [shared] (boost::system::error_code error)
|
||||
{
|
||||
if (shared)
|
||||
{
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
|
||||
#include <string.h>
|
||||
#include <thread>
|
||||
#include <boost/asio/post.hpp>
|
||||
#include <boost/asio/ssl.hpp>
|
||||
#include <boost/cerrno.hpp>
|
||||
#include <boost/filesystem/operations.hpp>
|
||||
@@ -45,6 +46,13 @@
|
||||
#undef MONERO_DEFAULT_LOG_CATEGORY
|
||||
#define MONERO_DEFAULT_LOG_CATEGORY "net.ssl"
|
||||
|
||||
|
||||
#if BOOST_VERSION >= 107300
|
||||
#define MONERO_HOSTNAME_VERIFY boost::asio::ssl::host_name_verification
|
||||
#else
|
||||
#define MONERO_HOSTNAME_VERIFY boost::asio::ssl::rfc2818_verification
|
||||
#endif
|
||||
|
||||
// openssl genrsa -out /tmp/KEY 4096
|
||||
// openssl req -new -key /tmp/KEY -out /tmp/REQ
|
||||
// openssl x509 -req -days 999999 -sha256 -in /tmp/REQ -signkey /tmp/KEY -out /tmp/CERT
|
||||
@@ -526,7 +534,7 @@ void ssl_options_t::configure(
|
||||
// preverified means it passed system or user CA check. System CA is never loaded
|
||||
// when fingerprints are whitelisted.
|
||||
const bool verified = preverified &&
|
||||
(verification != ssl_verification_t::system_ca || host.empty() || boost::asio::ssl::rfc2818_verification(host)(preverified, ctx));
|
||||
(verification != ssl_verification_t::system_ca || host.empty() || MONERO_HOSTNAME_VERIFY(host)(preverified, ctx));
|
||||
|
||||
if (!verified && !has_fingerprint(ctx))
|
||||
{
|
||||
@@ -544,6 +552,7 @@ void ssl_options_t::configure(
|
||||
}
|
||||
|
||||
bool ssl_options_t::handshake(
|
||||
boost::asio::io_context& io_context,
|
||||
boost::asio::ssl::stream<boost::asio::ip::tcp::socket> &socket,
|
||||
boost::asio::ssl::stream_base::handshake_type type,
|
||||
boost::asio::const_buffer buffer,
|
||||
@@ -555,12 +564,11 @@ bool ssl_options_t::handshake(
|
||||
auto start_handshake = [&]{
|
||||
using ec_t = boost::system::error_code;
|
||||
using timer_t = boost::asio::steady_timer;
|
||||
using strand_t = boost::asio::io_service::strand;
|
||||
using strand_t = boost::asio::io_context::strand;
|
||||
using socket_t = boost::asio::ip::tcp::socket;
|
||||
|
||||
auto &io_context = GET_IO_SERVICE(socket);
|
||||
if (io_context.stopped())
|
||||
io_context.reset();
|
||||
io_context.restart();
|
||||
strand_t strand(io_context);
|
||||
timer_t deadline(io_context, timeout);
|
||||
|
||||
@@ -595,13 +603,13 @@ bool ssl_options_t::handshake(
|
||||
state.result = ec;
|
||||
if (!state.cancel_handshake) {
|
||||
state.cancel_timer = true;
|
||||
ec_t ec;
|
||||
deadline.cancel(ec);
|
||||
deadline.cancel();
|
||||
}
|
||||
};
|
||||
|
||||
deadline.async_wait(on_timer);
|
||||
strand.post(
|
||||
boost::asio::post(
|
||||
strand,
|
||||
[&]{
|
||||
socket.async_handshake(
|
||||
type,
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
#include "misc_log_ex.h"
|
||||
#include <boost/chrono.hpp>
|
||||
#include "misc_language.h"
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include <algorithm>
|
||||
|
||||
@@ -186,6 +186,23 @@ void network_throttle::handle_trafic_exact(size_t packet_size)
|
||||
_handle_trafic_exact(packet_size, packet_size);
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
struct output_history
|
||||
{
|
||||
const boost::circular_buffer< network_throttle::packet_info >& history;
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, const output_history& source)
|
||||
{
|
||||
out << '[';
|
||||
for (auto sample: source.history)
|
||||
out << sample.m_size << ' ';
|
||||
out << ']';
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
void network_throttle::_handle_trafic_exact(size_t packet_size, size_t orginal_size)
|
||||
{
|
||||
tick();
|
||||
@@ -196,14 +213,11 @@ void network_throttle::_handle_trafic_exact(size_t packet_size, size_t orginal_s
|
||||
m_total_packets++;
|
||||
m_total_bytes += packet_size;
|
||||
|
||||
std::ostringstream oss; oss << "["; for (auto sample: m_history) oss << sample.m_size << " "; oss << "]" << std::ends;
|
||||
std::string history_str = oss.str();
|
||||
|
||||
MTRACE("Throttle " << m_name << ": packet of ~"<<packet_size<<"b " << " (from "<<orginal_size<<" b)"
|
||||
<< " Speed AVG=" << std::setw(4) << ((long int)(cts .average/1024)) <<"[w="<<cts .window<<"]"
|
||||
<< " " << std::setw(4) << ((long int)(cts2.average/1024)) <<"[w="<<cts2.window<<"]"
|
||||
<<" / " << " Limit="<< ((long int)(m_target_speed/1024)) <<" KiB/sec "
|
||||
<< " " << history_str
|
||||
<< " " << output_history{m_history}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -289,8 +303,6 @@ void network_throttle::calculate_times(size_t packet_size, calculate_times_struc
|
||||
}
|
||||
|
||||
if (dbg) {
|
||||
std::ostringstream oss; oss << "["; for (auto sample: m_history) oss << sample.m_size << " "; oss << "]" << std::ends;
|
||||
std::string history_str = oss.str();
|
||||
MTRACE((cts.delay > 0 ? "SLEEP" : "")
|
||||
<< "dbg " << m_name << ": "
|
||||
<< "speed is A=" << std::setw(8) <<cts.average<<" vs "
|
||||
@@ -300,7 +312,7 @@ void network_throttle::calculate_times(size_t packet_size, calculate_times_struc
|
||||
<< "E="<< std::setw(8) << E << " (Enow="<<std::setw(8)<<Enow<<") "
|
||||
<< "M=" << std::setw(8) << M <<" W="<< std::setw(8) << cts.window << " "
|
||||
<< "R=" << std::setw(8) << cts.recomendetDataSize << " Wgood" << std::setw(8) << Wgood << " "
|
||||
<< "History: " << std::setw(8) << history_str << " "
|
||||
<< "History: " << std::setw(8) << output_history{m_history} << " "
|
||||
<< "m_last_sample_time=" << std::setw(8) << m_last_sample_time
|
||||
);
|
||||
|
||||
|
||||
@@ -38,9 +38,12 @@
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <system_error>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/utility/string_ref.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include "misc_log_ex.h"
|
||||
#include "storages/parserse_base_utils.h"
|
||||
#include "hex.h"
|
||||
@@ -157,46 +160,20 @@ namespace string_tools
|
||||
return pname;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool set_module_name_and_folder(const std::string& path_to_process_)
|
||||
{
|
||||
std::string path_to_process = path_to_process_;
|
||||
|
||||
void set_module_name_and_folder(const std::string& path_to_process_)
|
||||
{
|
||||
boost::filesystem::path path_to_process = path_to_process_;
|
||||
|
||||
#ifdef _WIN32
|
||||
path_to_process = get_current_module_path();
|
||||
#endif
|
||||
std::string::size_type a = path_to_process.rfind( '\\' );
|
||||
if(a == std::string::npos )
|
||||
{
|
||||
a = path_to_process.rfind( '/' );
|
||||
}
|
||||
if ( a != std::string::npos )
|
||||
{
|
||||
get_current_module_name() = path_to_process.substr(a+1, path_to_process.size());
|
||||
get_current_module_folder() = path_to_process.substr(0, a);
|
||||
return true;
|
||||
}else
|
||||
return false;
|
||||
|
||||
}
|
||||
get_current_module_name() = path_to_process.filename().string();
|
||||
get_current_module_folder() = path_to_process.parent_path().string();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool trim_left(std::string& str)
|
||||
{
|
||||
for(std::string::iterator it = str.begin(); it!= str.end() && isspace(static_cast<unsigned char>(*it));)
|
||||
str.erase(str.begin());
|
||||
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
bool trim_right(std::string& str)
|
||||
{
|
||||
|
||||
for(std::string::reverse_iterator it = str.rbegin(); it!= str.rend() && isspace(static_cast<unsigned char>(*it));)
|
||||
str.erase( --((it++).base()));
|
||||
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
std::string pad_string(std::string s, size_t n, char c, bool prepend)
|
||||
{
|
||||
if (s.size() < n)
|
||||
@@ -209,28 +186,22 @@ namespace string_tools
|
||||
return s;
|
||||
}
|
||||
|
||||
std::string get_extension(const std::string& str)
|
||||
{
|
||||
std::string res;
|
||||
std::string::size_type pos = str.rfind('.');
|
||||
if(std::string::npos == pos)
|
||||
return res;
|
||||
|
||||
res = str.substr(pos+1, str.size()-pos);
|
||||
return res;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
std::string cut_off_extension(const std::string& str)
|
||||
{
|
||||
std::string res;
|
||||
std::string::size_type pos = str.rfind('.');
|
||||
if(std::string::npos == pos)
|
||||
return str;
|
||||
std::string get_extension(const std::string& str)
|
||||
{
|
||||
std::string ext_with_dot = boost::filesystem::path(str).extension().string();
|
||||
|
||||
if (ext_with_dot.empty())
|
||||
return {};
|
||||
|
||||
return ext_with_dot.erase(0, 1);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
std::string cut_off_extension(const std::string& str)
|
||||
{
|
||||
return boost::filesystem::path(str).replace_extension("").string();
|
||||
}
|
||||
|
||||
res = str.substr(0, pos);
|
||||
return res;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
#ifdef _WIN32
|
||||
std::wstring utf8_to_utf16(const std::string& str)
|
||||
{
|
||||
|
||||
Vendored
+1
@@ -70,3 +70,4 @@ add_subdirectory(db_drivers)
|
||||
add_subdirectory(easylogging++)
|
||||
add_subdirectory(qrcodegen)
|
||||
add_subdirectory(randomx EXCLUDE_FROM_ALL)
|
||||
add_subdirectory(mx25519)
|
||||
|
||||
+4
@@ -0,0 +1,4 @@
|
||||
# Boost Serialization Vendoring
|
||||
|
||||
* optional_shim.hpp - Compare to file include/boost/serialization/optional.hpp in the Boost serialization repository, checked out at commit ff0a5f9f4a4040c6f992581245fed48d9634acfe. This is the newest version of the file at time of writing. Once minimum required Boost version is >= 1.84, then we can drop this header.
|
||||
* std_variant_shim.hpp - Compare to file include/boost/serialization/std_variant.hpp in the Boost serialization repository, checked out at commit 2805bc3faa8f8fb7ce80ec518158563c5fcf26f6. This is the newest version of the file at time of writing. Once minimum required Boost version includes commit 042c590a7ac84933413243d8e9c3b06a791803a7 in the multiprecision repository, then we can drop this header. Commit 042c590a7ac84933413243d8e9c3b06a791803a7 removes a namespace clash in Boost's multiprecision library with the std_variant.hpp header.
|
||||
+177
@@ -0,0 +1,177 @@
|
||||
#include <boost/version.hpp>
|
||||
|
||||
#ifndef BOOST_VERSION
|
||||
#error "Missing Boost version"
|
||||
#endif
|
||||
|
||||
#if BOOST_VERSION >= 108400
|
||||
#include <boost/serialization/optional.hpp>
|
||||
#else
|
||||
|
||||
|
||||
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
|
||||
|
||||
// (C) Copyright 2002-4 Pavel Vozenilek .
|
||||
// Use, modification and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// Provides non-intrusive serialization for boost::optional.
|
||||
|
||||
#ifndef BOOST_SERIALIZATION_OPTIONAL_HPP
|
||||
#define BOOST_SERIALIZATION_OPTIONAL_HPP
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#ifndef BOOST_NO_CXX17_HDR_OPTIONAL
|
||||
#include <optional>
|
||||
#endif
|
||||
|
||||
#include <boost/serialization/item_version_type.hpp>
|
||||
#include <boost/serialization/version.hpp>
|
||||
#include <boost/serialization/split_free.hpp>
|
||||
#include <boost/serialization/nvp.hpp>
|
||||
#include <boost/type_traits/is_pointer.hpp>
|
||||
#include <boost/serialization/detail/is_default_constructible.hpp>
|
||||
|
||||
// function specializations must be defined in the appropriate
|
||||
// namespace - boost::serialization
|
||||
namespace boost {
|
||||
namespace serialization {
|
||||
namespace detail {
|
||||
|
||||
// OT is of the form optional<T>
|
||||
template<class Archive, class OT>
|
||||
void save_impl(
|
||||
Archive & ar,
|
||||
const OT & ot
|
||||
){
|
||||
// It is an inherent limitation to the serialization of optional.hpp
|
||||
// that the underlying type must be either a pointer or must have a
|
||||
// default constructor. It's possible that this could change sometime
|
||||
// in the future, but for now, one will have to work around it. This can
|
||||
// be done by serialization the optional<T> as optional<T *>
|
||||
#ifndef BOOST_NO_CXX11_HDR_TYPE_TRAITS
|
||||
BOOST_STATIC_ASSERT(
|
||||
boost::serialization::detail::is_default_constructible<typename OT::value_type>::value
|
||||
|| boost::is_pointer<typename OT::value_type>::value
|
||||
);
|
||||
#endif
|
||||
const bool tflag(ot);
|
||||
ar << boost::serialization::make_nvp("initialized", tflag);
|
||||
if (tflag){
|
||||
ar << boost::serialization::make_nvp("value", *ot);
|
||||
}
|
||||
}
|
||||
|
||||
// OT is of the form optional<T>
|
||||
template<class Archive, class OT>
|
||||
void load_impl(
|
||||
Archive & ar,
|
||||
OT & ot,
|
||||
const unsigned int version
|
||||
){
|
||||
bool tflag;
|
||||
ar >> boost::serialization::make_nvp("initialized", tflag);
|
||||
if(! tflag){
|
||||
ot.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
if(0 == version){
|
||||
boost::serialization::item_version_type item_version(0);
|
||||
auto library_version(
|
||||
ar.get_library_version()
|
||||
);
|
||||
if(decltype(library_version)(3) < library_version){
|
||||
ar >> BOOST_SERIALIZATION_NVP(item_version);
|
||||
}
|
||||
}
|
||||
typename OT::value_type t;
|
||||
ar >> boost::serialization::make_nvp("value",t);
|
||||
ot = t;
|
||||
}
|
||||
|
||||
} // detail
|
||||
|
||||
template<class Archive, class T>
|
||||
void save(
|
||||
Archive & ar,
|
||||
const boost::optional< T > & ot,
|
||||
const unsigned int /*version*/
|
||||
){
|
||||
detail::save_impl(ar, ot);
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_CXX17_HDR_OPTIONAL
|
||||
template<class Archive, class T>
|
||||
void save(
|
||||
Archive & ar,
|
||||
const std::optional< T > & ot,
|
||||
const unsigned int /*version*/
|
||||
){
|
||||
detail::save_impl(ar, ot);
|
||||
}
|
||||
#endif
|
||||
|
||||
template<class Archive, class T>
|
||||
void load(
|
||||
Archive & ar,
|
||||
boost::optional< T > & ot,
|
||||
const unsigned int version
|
||||
){
|
||||
detail::load_impl(ar, ot, version);
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_CXX17_HDR_OPTIONAL
|
||||
template<class Archive, class T>
|
||||
void load(
|
||||
Archive & ar,
|
||||
std::optional< T > & ot,
|
||||
const unsigned int version
|
||||
){
|
||||
detail::load_impl(ar, ot, version);
|
||||
}
|
||||
#endif
|
||||
|
||||
template<class Archive, class T>
|
||||
void serialize(
|
||||
Archive & ar,
|
||||
boost::optional< T > & ot,
|
||||
const unsigned int version
|
||||
){
|
||||
boost::serialization::split_free(ar, ot, version);
|
||||
}
|
||||
|
||||
#ifndef BOOST_NO_CXX17_HDR_OPTIONAL
|
||||
template<class Archive, class T>
|
||||
void serialize(
|
||||
Archive & ar,
|
||||
std::optional< T > & ot,
|
||||
const unsigned int version
|
||||
){
|
||||
boost::serialization::split_free(ar, ot, version);
|
||||
}
|
||||
#endif
|
||||
|
||||
template<class T>
|
||||
struct version<boost::optional<T> >{
|
||||
BOOST_STATIC_CONSTANT(int, value = 1);
|
||||
};
|
||||
|
||||
#ifndef BOOST_NO_CXX17_HDR_OPTIONAL
|
||||
template<class T>
|
||||
struct version<std::optional<T> >{
|
||||
BOOST_STATIC_CONSTANT(int, value = 1);
|
||||
};
|
||||
#endif
|
||||
|
||||
} // serialization
|
||||
} // boost
|
||||
|
||||
#endif // BOOST_SERIALIZATION_OPTIONAL_HPP
|
||||
#endif //BOOST_VERSION < 108400
|
||||
+204
@@ -0,0 +1,204 @@
|
||||
#ifndef BOOST_SERIALIZATION_STD_VARIANT_HPP
|
||||
#define BOOST_SERIALIZATION_STD_VARIANT_HPP
|
||||
|
||||
// MS compatible compilers support #pragma once
|
||||
#if defined(_MSC_VER)
|
||||
# pragma once
|
||||
#endif
|
||||
|
||||
/////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
|
||||
// variant.hpp - non-intrusive serialization of variant types
|
||||
//
|
||||
// copyright (c) 2019 Samuel Debionne, ESRF
|
||||
//
|
||||
// Use, modification and distribution is subject to the Boost Software
|
||||
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//
|
||||
// See http://www.boost.org for updates, documentation, and revision history.
|
||||
//
|
||||
// Widely inspired form boost::variant serialization
|
||||
//
|
||||
|
||||
#include <boost/serialization/throw_exception.hpp>
|
||||
|
||||
#include <variant>
|
||||
|
||||
#include <boost/archive/archive_exception.hpp>
|
||||
|
||||
#include <boost/serialization/split_free.hpp>
|
||||
#include <boost/serialization/serialization.hpp>
|
||||
#include <boost/serialization/nvp.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace serialization {
|
||||
|
||||
template<class Archive>
|
||||
struct std_variant_save_visitor
|
||||
{
|
||||
std_variant_save_visitor(Archive& ar) :
|
||||
m_ar(ar)
|
||||
{}
|
||||
template<class T>
|
||||
void operator()(T const & value) const
|
||||
{
|
||||
m_ar << BOOST_SERIALIZATION_NVP(value);
|
||||
}
|
||||
private:
|
||||
Archive & m_ar;
|
||||
};
|
||||
|
||||
|
||||
template<class Archive>
|
||||
struct std_variant_load_visitor
|
||||
{
|
||||
std_variant_load_visitor(Archive& ar) :
|
||||
m_ar(ar)
|
||||
{}
|
||||
template<class T>
|
||||
void operator()(T & value) const
|
||||
{
|
||||
m_ar >> BOOST_SERIALIZATION_NVP(value);
|
||||
}
|
||||
private:
|
||||
Archive & m_ar;
|
||||
};
|
||||
|
||||
template<class Archive, class ...Types>
|
||||
void save(
|
||||
Archive & ar,
|
||||
std::variant<Types...> const & v,
|
||||
unsigned int /*version*/
|
||||
){
|
||||
const std::size_t which = v.index();
|
||||
ar << BOOST_SERIALIZATION_NVP(which);
|
||||
std_variant_save_visitor<Archive> visitor(ar);
|
||||
std::visit(visitor, v);
|
||||
}
|
||||
|
||||
// Minimalist metaprogramming for handling parameter pack
|
||||
namespace mp_shim {
|
||||
namespace detail {
|
||||
template <typename Seq>
|
||||
struct front_impl;
|
||||
|
||||
template <template <typename...> class Seq, typename T, typename... Ts>
|
||||
struct front_impl<Seq<T, Ts...>> {
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template <typename Seq>
|
||||
struct pop_front_impl;
|
||||
|
||||
template <template <typename...> class Seq, typename T, typename... Ts>
|
||||
struct pop_front_impl<Seq<T, Ts...>> {
|
||||
using type = Seq<Ts...>;
|
||||
};
|
||||
} //namespace detail
|
||||
|
||||
template <typename... Ts>
|
||||
struct typelist {};
|
||||
|
||||
template <typename Seq>
|
||||
using front = typename detail::front_impl<Seq>::type;
|
||||
|
||||
template <typename Seq>
|
||||
using pop_front = typename detail::pop_front_impl<Seq>::type;
|
||||
} // namespace mp_shim
|
||||
|
||||
template<std::size_t N, class Seq>
|
||||
struct variant_impl_shim
|
||||
{
|
||||
template<class Archive, class V>
|
||||
static void load (
|
||||
Archive & ar,
|
||||
std::size_t which,
|
||||
V & v,
|
||||
const unsigned int version
|
||||
){
|
||||
if(which == 0){
|
||||
// note: A non-intrusive implementation (such as this one)
|
||||
// necessary has to copy the value. This wouldn't be necessary
|
||||
// with an implementation that de-serialized to the address of the
|
||||
// aligned storage included in the variant.
|
||||
using type = mp_shim::front<Seq>;
|
||||
type value;
|
||||
ar >> BOOST_SERIALIZATION_NVP(value);
|
||||
v = std::move(value);
|
||||
type * new_address = & std::get<type>(v);
|
||||
ar.reset_object_address(new_address, & value);
|
||||
return;
|
||||
}
|
||||
//typedef typename mpl::pop_front<S>::type type;
|
||||
using types = mp_shim::pop_front<Seq>;
|
||||
variant_impl_shim<N - 1, types>::load(ar, which - 1, v, version);
|
||||
}
|
||||
};
|
||||
|
||||
template<class Seq>
|
||||
struct variant_impl_shim<0, Seq>
|
||||
{
|
||||
template<class Archive, class V>
|
||||
static void load (
|
||||
Archive & /*ar*/,
|
||||
std::size_t /*which*/,
|
||||
V & /*v*/,
|
||||
const unsigned int /*version*/
|
||||
){}
|
||||
};
|
||||
|
||||
template<class Archive, class... Types>
|
||||
void load(
|
||||
Archive & ar,
|
||||
std::variant<Types...>& v,
|
||||
const unsigned int version
|
||||
){
|
||||
std::size_t which;
|
||||
ar >> BOOST_SERIALIZATION_NVP(which);
|
||||
if(which >= sizeof...(Types))
|
||||
// this might happen if a type was removed from the list of variant types
|
||||
boost::serialization::throw_exception(
|
||||
boost::archive::archive_exception(
|
||||
boost::archive::archive_exception::unsupported_version
|
||||
)
|
||||
);
|
||||
variant_impl_shim<sizeof...(Types), mp_shim::typelist<Types...>>::load(ar, which, v, version);
|
||||
}
|
||||
|
||||
template<class Archive,class... Types>
|
||||
inline void serialize(
|
||||
Archive & ar,
|
||||
std::variant<Types...> & v,
|
||||
const unsigned int file_version
|
||||
){
|
||||
split_free(ar,v,file_version);
|
||||
}
|
||||
|
||||
// Specialization for std::monostate
|
||||
template<class Archive>
|
||||
void serialize(Archive &, std::monostate &, const unsigned int /*version*/)
|
||||
{}
|
||||
|
||||
} // namespace serialization
|
||||
} // namespace boost
|
||||
|
||||
//template<typename T0_, BOOST_VARIANT_ENUM_SHIFTED_PARAMS(typename T)>
|
||||
|
||||
#include <boost/serialization/tracking.hpp>
|
||||
|
||||
namespace boost {
|
||||
namespace serialization {
|
||||
|
||||
template<class... Types>
|
||||
struct tracking_level<
|
||||
std::variant<Types...>
|
||||
>{
|
||||
typedef mpl::integral_c_tag tag;
|
||||
typedef mpl::int_< ::boost::serialization::track_always> type;
|
||||
BOOST_STATIC_CONSTANT(int, value = type::value);
|
||||
};
|
||||
|
||||
} // namespace serialization
|
||||
} // namespace boost
|
||||
|
||||
#endif //BOOST_SERIALIZATION_VARIANT_HPP
|
||||
+1
Submodule external/mx25519 added at e808a6406b
Executable
+31
@@ -0,0 +1,31 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Get the git information
|
||||
TAG=`git tag -l --points-at HEAD`
|
||||
COMMIT=`git rev-parse --short=9 HEAD`
|
||||
|
||||
# Build the 64-bit Windows release
|
||||
USE_DEVICE_TREZOR=OFF make depends target=x86_64-w64-mingw32 -j12
|
||||
pushd ./build/x86_64-w64-mingw32/release/bin > /dev/null
|
||||
zip -ur ~/releases/salvium-${TAG}-win64.zip salviumd.exe salvium-wallet-cli.exe salvium-wallet-rpc.exe
|
||||
popd > /dev/null
|
||||
|
||||
# Build the 64-bit Apple Silicon release
|
||||
USE_DEVICE_TREZOR=OFF make depends target=aarch64-apple-darwin -j12
|
||||
pushd ./build/aarch64-apple-darwin/release/bin > /dev/null
|
||||
zip -ur ~/releases/salvium-${TAG}-macos-arm64.zip salviumd salvium-wallet-cli salvium-wallet-rpc
|
||||
popd > /dev/null
|
||||
|
||||
# Build the 64-bit MacOS Intel Silicon release
|
||||
USE_DEVICE_TREZOR=OFF make depends target=x86_64-apple-darwin -j12
|
||||
pushd ./build/x86_64-apple-darwin/release/bin > /dev/null
|
||||
zip -ur ~/releases/salvium-${TAG}-macos-x86_64.zip salviumd salvium-wallet-cli salvium-wallet-rpc
|
||||
popd > /dev/null
|
||||
|
||||
# Build the 64-bit Linux release
|
||||
USE_DEVICE_TREZOR=OFF make depends target=x86_64-linux-gnu -j12
|
||||
pushd ./build/x86_64-linux-gnu/release/bin > /dev/null
|
||||
zip -ur ~/releases/salvium-${TAG}-linux-x86_64.zip salviumd salvium-wallet-cli salvium-wallet-rpc
|
||||
popd > /dev/null
|
||||
|
||||
# Finish
|
||||
@@ -0,0 +1,5 @@
|
||||
48417220800f174a3613881a56131d25c49d344228fca124c8331e0b58a8ff06 salvium-v1.0.7-ubuntu22.04-linux-x86_64.zip
|
||||
52226551a9e1842df46cf068292cfa3c1e05328e0695cf6723365d4401af19a6 salvium-v1.0.7-ubuntu22.04-linux-aarch64.zip
|
||||
b40c3765479c9d5712e766ddd01314b63e5080472b7639d34388e6b74b36142e salvium-v1.0.7-macos-x86_64.zip
|
||||
60b05548f69040fe901e336e8fc4189a1028a8d7ded09bad555b3c854a0e8d6e salvium-v1.0.7-macos-aarch64.zip
|
||||
b2c3e0bb8254ad1f62a78d6670c6e5adba1e42bb823919faad1cbf5796d53910 salvium-v1.0.7-win64.zip
|
||||
@@ -0,0 +1,5 @@
|
||||
e032e42ebac862bf90d71f0a231d9f3ddb5583e321ec153ee05144d87629980b salvium-v1.1.0-macos-aarch64.zip
|
||||
0f31f09cf7be38b50a35510172bc94b7a4fb07c7107c79c4f055754c282c99f5 salvium-v1.1.0-macos-x86_64.zip
|
||||
4424fd93391daab7eee47c54ab7aad7810a16f4c866209d41ba016d984605ffb salvium-v1.1.0-ubuntu22.04-linux-aarch64.zip
|
||||
d1a5138f892189dfccc1d51d72ce24147fe6f1a2a5d465d350651426a71282a4 salvium-v1.1.0-ubuntu22.04-linux-x86_64.zip
|
||||
bb9c9175726b82e061a6a332a27a6845805be4779928df3abbbd5c0f54691c9a salvium-v1.1.0-win64.zip
|
||||
@@ -0,0 +1,5 @@
|
||||
d0a8b0515ae2ee79849cbc17b0639bb7859e30efcd50e5b058540874cd0919ce salvium-v1.1.0-rc4-ubuntu22.04-linux-x86_64.zip
|
||||
6528b8b23f09c574fc9383b48b88e87f99609ff5ce1b727872b5554505a69d77 salvium-v1.1.0-rc4-ubuntu22.04-linux-aarch64.zip
|
||||
00ca183c47f852b8b30e4b87ce3b3536a0e97866e6027bf25d389b4a1bc9c471 salvium-v1.1.0-rc4-macos-x86_64.zip
|
||||
50480b1043e9b5901576ab45f926b0b51a5d21237c6da549603ad1f13819e6ed salvium-v1.1.0-rc4-macos-aarch64.zip
|
||||
adf96eee17e16f318fc047721acb5bfa8ae7ed1c0ff8d022da8ab5df64d8ce3f salvium-v1.1.0-rc4-win64.zip
|
||||
@@ -0,0 +1,5 @@
|
||||
23a03277e922c3f41ba6ddb0efc7581c3287d9f3faa2ddd19cc2d018a6797701 salvium-v1.1.0-rc5-ubuntu22.04-linux-x86_64.zip
|
||||
94409b190eae890792b2d04cfffe148828dc23d658cd54a8d7802b12a9f274a4 salvium-v1.1.0-rc5-ubuntu22.04-linux-aarch64.zip
|
||||
76cc02603cb21cd0729f0e5c9a39bb32310428b15580458ec8d74dcba39c9319 salvium-v1.1.0-rc5-macos-x86_64.zip
|
||||
dc477718bfb370ecbafebf3e1736df5978200302f13542374f1b1fd43e07ab45 salvium-v1.1.0-rc5-macos-aarch64.zip
|
||||
0e9b81eeaa32a4709a1cbd4c198721455a3c8cc86c1f1915cfc74af7885f8fee salvium-v1.1.0-rc5-win64.zip
|
||||
@@ -0,0 +1,5 @@
|
||||
b712adec8fa6bbcbe461b0748649e4c9e4fb61934fc1adb064779afed28c0758 salvium-v1.1.0-rc6-macos-aarch64.zip
|
||||
8635955ff784f936a8b8de5be267e5dcdc0b55dfbf0b6f65ba24d098d8b8ab00 salvium-v1.1.0-rc6-macos-x86_64.zip
|
||||
79b65ba9a074aeba87f03d83a07c3a6c51815d376049b3136a38c1a33260bfac salvium-v1.1.0-rc6-ubuntu22.04-linux-aarch64.zip
|
||||
9031763ad60d1c8c572c76c5cb51a96b1680b9708c287264388f3d411bda464f salvium-v1.1.0-rc6-ubuntu22.04-linux-x86_64.zip
|
||||
e3a8e53e092041ed9ed32c98d5d0ecf548f42232402748f862371ba21e1f1f9f salvium-v1.1.0-rc6-win64.zip
|
||||
@@ -0,0 +1,5 @@
|
||||
d22bbe19fa5e7eb7ebaf95eee336d73cbd59ded7b5e737213e89a8b84d5791eb salvium-v1.1.1-macos-aarch64.zip
|
||||
262e2bdffc3c4fee89ec79451a6181175671db5874726d359077c4479754076e salvium-v1.1.1-macos-x86_64.zip
|
||||
72b37fa30df6b136dba380b88e9ccc4d66804d8286a221a87e944e337f4ba593 salvium-v1.1.1-ubuntu22.04-linux-aarch64.zip
|
||||
33321419bb426507de0f5de7c1977e436ca34bf4db620fa00eede1fa318b7994 salvium-v1.1.1-ubuntu22.04-linux-x86_64.zip
|
||||
33e7c1e1bc4e5a1f9c40482eba993a5efb97a8feedfb36dca863bbb5bd9e794f salvium-v1.1.1-win64.zip
|
||||
@@ -83,6 +83,8 @@ endfunction ()
|
||||
include(Version)
|
||||
monero_add_library(version SOURCES ${CMAKE_BINARY_DIR}/version.cpp DEPENDS genversion)
|
||||
|
||||
add_subdirectory(carrot_core)
|
||||
add_subdirectory(carrot_impl)
|
||||
add_subdirectory(common)
|
||||
add_subdirectory(crypto)
|
||||
add_subdirectory(ringct)
|
||||
@@ -97,6 +99,7 @@ add_subdirectory(hardforks)
|
||||
add_subdirectory(blockchain_db)
|
||||
add_subdirectory(mnemonics)
|
||||
add_subdirectory(rpc)
|
||||
add_subdirectory(seraphis_crypto)
|
||||
if(NOT IOS)
|
||||
add_subdirectory(serialization)
|
||||
endif()
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "cryptonote_basic/cryptonote_format_utils.h"
|
||||
#include "profile_tools.h"
|
||||
#include "ringct/rctOps.h"
|
||||
#include "ringct/rctSigs.h"
|
||||
|
||||
#include "lmdb/db_lmdb.h"
|
||||
|
||||
@@ -237,10 +238,13 @@ void BlockchainDB::add_transaction(const crypto::hash& blk_hash, const std::pair
|
||||
LOG_PRINT_L1("Failed to get output unlock time, aborting transaction addition");
|
||||
throw std::runtime_error("Unexpected error getting output unlock_time, aborting");
|
||||
}
|
||||
if (miner_tx && tx.version == 2)
|
||||
if (miner_tx && tx.version >= 2)
|
||||
{
|
||||
cryptonote::tx_out vout = tx.vout[i];
|
||||
rct::key commitment = rct::zeroCommit(vout.amount);
|
||||
// TODO: avoid multiple expensive zeroCommitVartime call here + get_outs_by_last_locked_block + ver_non_input_consensus
|
||||
rct::key commitment;
|
||||
if (!rct::getCommitment(tx, i, commitment))
|
||||
throw std::runtime_error("Failed to get miner tx commitment, aborting");
|
||||
vout.amount = 0;
|
||||
amount_output_indices[i] = add_output(tx_hash, vout, i, unlock_time,
|
||||
&commitment);
|
||||
@@ -267,8 +271,9 @@ uint64_t BlockchainDB::add_block( const std::pair<block, blobdata>& blck
|
||||
, const difficulty_type& cumulative_difficulty
|
||||
, const uint64_t& coins_generated
|
||||
, const std::vector<std::pair<transaction, blobdata>>& txs
|
||||
, const cryptonote::network_type& nettype
|
||||
, const cryptonote::network_type nettype
|
||||
, cryptonote::yield_block_info& ybi
|
||||
, cryptonote::audit_block_info& abi
|
||||
)
|
||||
{
|
||||
const block &blk = blck.first;
|
||||
@@ -289,13 +294,28 @@ uint64_t BlockchainDB::add_block( const std::pair<block, blobdata>& blck
|
||||
time1 = epee::misc_utils::get_tick_count();
|
||||
|
||||
uint64_t num_rct_outs = 0;
|
||||
oracle::asset_type_counts num_rct_outs_by_asset_type;
|
||||
oracle::asset_type_counts_v2 num_rct_outs_by_asset_type;
|
||||
|
||||
// add newly created tokens
|
||||
for (const std::pair<transaction, blobdata>& tx : txs)
|
||||
{
|
||||
if (tx.first.type == cryptonote::transaction_type::CREATE_TOKEN)
|
||||
{
|
||||
uint32_t asset_type_id = cryptonote::asset_id_from_type("sal" + tx.first.token_metadata.asset_type);
|
||||
if (!num_rct_outs_by_asset_type.add_asset_type(asset_type_id))
|
||||
throw std::runtime_error("Failed to add asset_type 'sal" + tx.first.token_metadata.asset_type + "'");
|
||||
}
|
||||
|
||||
if (!is_tx_paid_for(tx.first))
|
||||
throw std::runtime_error("TX is not paid for");
|
||||
}
|
||||
|
||||
blobdata miner_bd = tx_to_blob(blk.miner_tx);
|
||||
add_transaction(blk_hash, std::make_pair(blk.miner_tx, blobdata_ref(miner_bd)));
|
||||
blobdata protocol_bd = tx_to_blob(blk.protocol_tx);
|
||||
add_transaction(blk_hash, std::make_pair(blk.protocol_tx, blobdata_ref(protocol_bd)));
|
||||
|
||||
if (blk.miner_tx.version == 2)
|
||||
if (blk.miner_tx.version >= 2)
|
||||
{
|
||||
num_rct_outs += blk.miner_tx.vout.size();
|
||||
|
||||
@@ -304,13 +324,15 @@ uint64_t BlockchainDB::add_block( const std::pair<block, blobdata>& blck
|
||||
std::string asset_type;
|
||||
if (!get_output_asset_type(vout, asset_type))
|
||||
throw std::runtime_error("Failed to get output asset type");
|
||||
num_rct_outs_by_asset_type.add(asset_type, 1);
|
||||
uint32_t asset_type_id = cryptonote::asset_id_from_type(asset_type);
|
||||
num_rct_outs_by_asset_type.add_asset_type(asset_type_id);
|
||||
num_rct_outs_by_asset_type.add(asset_type_id, 1);
|
||||
}
|
||||
}
|
||||
|
||||
std::map<std::string, int64_t> slippage_counts;
|
||||
uint64_t yield_total = 0;
|
||||
if (blk.protocol_tx.version == 2)
|
||||
uint64_t audit_total = 0, token_total = 0, yield_total = 0;
|
||||
if (blk.protocol_tx.version >= 2)
|
||||
{
|
||||
num_rct_outs += blk.protocol_tx.vout.size();
|
||||
|
||||
@@ -321,10 +343,12 @@ uint64_t BlockchainDB::add_block( const std::pair<block, blobdata>& blck
|
||||
std::string asset_type;
|
||||
if (!get_output_asset_type(vout, asset_type))
|
||||
throw std::runtime_error("Failed to get output asset type");
|
||||
uint32_t asset_type_id = cryptonote::asset_id_from_type(asset_type);
|
||||
|
||||
// Update the RCT outs for the asset_type
|
||||
num_rct_outs_by_asset_type.add_asset_type(asset_type_id);
|
||||
num_rct_outs_by_asset_type.add(asset_type_id, 1);
|
||||
|
||||
// Update the RCT outs
|
||||
num_rct_outs_by_asset_type.add(asset_type, 1);
|
||||
|
||||
// Update the amount tallies by DEDUCTING the minted amount
|
||||
if (slippage_counts.count(asset_type) == 0)
|
||||
slippage_counts[asset_type] = 0;
|
||||
@@ -345,7 +369,9 @@ uint64_t BlockchainDB::add_block( const std::pair<block, blobdata>& blck
|
||||
throw std::runtime_error("Failed to get output asset type");
|
||||
if (vout.amount == 0) {
|
||||
++num_rct_outs;
|
||||
num_rct_outs_by_asset_type.add(asset_type, 1);
|
||||
uint32_t asset_type_id = cryptonote::asset_id_from_type(asset_type);
|
||||
num_rct_outs_by_asset_type.add_asset_type(asset_type_id);
|
||||
num_rct_outs_by_asset_type.add(asset_type_id, 1);
|
||||
}
|
||||
|
||||
// Is this a CONVERT TX?
|
||||
@@ -355,11 +381,26 @@ uint64_t BlockchainDB::add_block( const std::pair<block, blobdata>& blck
|
||||
slippage_counts[asset_type] = 0;
|
||||
slippage_counts[asset_type] += tx.first.amount_burnt;
|
||||
}
|
||||
}
|
||||
|
||||
// Is this a YIELD TX?
|
||||
if (tx.first.type == cryptonote::transaction_type::STAKE) {
|
||||
yield_total += tx.first.amount_burnt;
|
||||
}
|
||||
// Is this an AUDIT TX?
|
||||
if (tx.first.type == cryptonote::transaction_type::AUDIT) {
|
||||
audit_total += tx.first.amount_burnt;
|
||||
}
|
||||
|
||||
// Is this an create_token TX?
|
||||
if (tx.first.type == cryptonote::transaction_type::CREATE_TOKEN) {
|
||||
token_total += tx.first.amount_burnt;
|
||||
/*
|
||||
uint32_t asset_type_id = cryptonote::asset_id_from_type(tx.first.token_metadata.asset_type);
|
||||
if (!num_rct_outs_by_asset_type.add_asset_type(asset_type_id))
|
||||
throw std::runtime_error("Failed to add asset_type '" + tx.first.token_metadata.asset_type + "' to RCT outputs");
|
||||
*/
|
||||
}
|
||||
|
||||
// Is this a STAKE TX?
|
||||
if (tx.first.type == cryptonote::transaction_type::STAKE) {
|
||||
yield_total += tx.first.amount_burnt;
|
||||
}
|
||||
++tx_i;
|
||||
}
|
||||
@@ -410,7 +451,7 @@ uint64_t BlockchainDB::add_block( const std::pair<block, blobdata>& blck
|
||||
|
||||
// call out to subclass implementation to add the block & metadata
|
||||
time1 = epee::misc_utils::get_tick_count();
|
||||
add_block(blk, block_weight, long_term_block_weight, cumulative_difficulty, coins_generated, num_rct_outs, num_rct_outs_by_asset_type, blk_hash, slippage_total, yield_total, nettype, ybi);
|
||||
add_block(blk, block_weight, long_term_block_weight, cumulative_difficulty, coins_generated, num_rct_outs, num_rct_outs_by_asset_type, blk_hash, slippage_total, yield_total, audit_total, token_total, nettype, ybi, abi);
|
||||
TIME_MEASURE_FINISH(time1);
|
||||
time_add_block1 += time1;
|
||||
|
||||
|
||||
@@ -207,6 +207,29 @@ typedef struct yield_tx_info {
|
||||
crypto::public_key return_pubkey;
|
||||
} yield_tx_info;
|
||||
|
||||
typedef struct yield_tx_info_carrot {
|
||||
uint64_t block_height;
|
||||
uint8_t version;
|
||||
crypto::hash tx_hash;
|
||||
uint64_t locked_coins;
|
||||
crypto::public_key return_address;
|
||||
crypto::public_key return_pubkey;
|
||||
carrot::view_tag_t return_view_tag;
|
||||
carrot::encrypted_janus_anchor_t return_anchor_enc;
|
||||
} yield_tx_info_carrot;
|
||||
|
||||
typedef struct token_tx_info_carrot {
|
||||
uint64_t block_height;
|
||||
uint8_t version;
|
||||
crypto::hash tx_hash;
|
||||
uint64_t locked_coins;
|
||||
crypto::public_key return_address;
|
||||
crypto::public_key return_pubkey;
|
||||
carrot::view_tag_t return_view_tag;
|
||||
carrot::encrypted_janus_anchor_t return_anchor_enc;
|
||||
uint32_t asset_type_id;
|
||||
} token_tx_info_carrot;
|
||||
|
||||
#define DBF_SAFE 1
|
||||
#define DBF_FAST 2
|
||||
#define DBF_FASTEST 4
|
||||
@@ -426,12 +449,15 @@ private:
|
||||
const difficulty_type& cumulative_difficulty,
|
||||
const uint64_t& coins_generated,
|
||||
uint64_t num_rct_outs,
|
||||
oracle::asset_type_counts& cum_rct_by_asset_type,
|
||||
oracle::asset_type_counts_v2& cum_rct_by_asset_type,
|
||||
const crypto::hash& blk_hash,
|
||||
uint64_t slippage_total,
|
||||
uint64_t yield_total,
|
||||
const cryptonote::network_type& nettype,
|
||||
cryptonote::yield_block_info& ybi
|
||||
uint64_t audit_total,
|
||||
uint64_t token_total,
|
||||
const cryptonote::network_type nettype,
|
||||
cryptonote::yield_block_info& ybi,
|
||||
cryptonote::audit_block_info& abi
|
||||
) = 0;
|
||||
|
||||
/**
|
||||
@@ -884,8 +910,9 @@ public:
|
||||
, const difficulty_type& cumulative_difficulty
|
||||
, const uint64_t& coins_generated
|
||||
, const std::vector<std::pair<transaction, blobdata>>& txs
|
||||
, const cryptonote::network_type& nettype
|
||||
, const cryptonote::network_type nettype
|
||||
, cryptonote::yield_block_info& ybi
|
||||
, cryptonote::audit_block_info& abi
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -1198,6 +1225,20 @@ public:
|
||||
virtual std::map<std::string, uint64_t> get_circulating_supply() const = 0;
|
||||
|
||||
|
||||
/**
|
||||
* @brief fetch the tokens from the blockchain
|
||||
*
|
||||
* @return the current token values
|
||||
*/
|
||||
virtual std::map<std::string, cryptonote::token_metadata_t> get_tokens() const = 0;
|
||||
|
||||
/**
|
||||
* @brief determine if a TX has been paid for
|
||||
*
|
||||
* @return the current token values
|
||||
*/
|
||||
virtual bool is_tx_paid_for(const cryptonote::transaction& tx) const = 0;
|
||||
|
||||
/**
|
||||
* <!--
|
||||
* TODO: Rewrite (if necessary) such that all calls to remove_* are
|
||||
@@ -1915,8 +1956,15 @@ public:
|
||||
*/
|
||||
virtual uint64_t get_database_size() const = 0;
|
||||
|
||||
virtual int get_yield_block_info(const uint64_t height, yield_block_info& ybi) = 0;
|
||||
virtual int get_yield_tx_info(const uint64_t height, std::vector<yield_tx_info>& yti_container) = 0;
|
||||
virtual int get_audit_block_info(const uint64_t height, audit_block_info& abi) const = 0;
|
||||
virtual int get_audit_tx_info(const uint64_t height, std::vector<yield_tx_info>& ati_container) const = 0;
|
||||
|
||||
virtual int get_yield_block_info(const uint64_t height, yield_block_info& ybi) const = 0;
|
||||
virtual int get_yield_tx_info(const uint64_t height, std::vector<yield_tx_info>& yti_container) const = 0;
|
||||
|
||||
virtual int get_carrot_yield_tx_info(const uint64_t height, std::vector<yield_tx_info_carrot>& yti_container) const = 0;
|
||||
|
||||
virtual int get_token_tx_info(const uint64_t height, std::vector<token_tx_info_carrot>& tti_container) const = 0;
|
||||
|
||||
|
||||
/**
|
||||
|
||||
+1232
-79
File diff suppressed because it is too large
Load Diff
@@ -78,7 +78,18 @@ typedef struct mdb_txn_cursors
|
||||
MDB_cursor *m_txc_circ_supply_tally;
|
||||
MDB_cursor *m_txc_yield_txs;
|
||||
MDB_cursor *m_txc_yield_blocks;
|
||||
MDB_cursor *m_txc_audit_txs;
|
||||
MDB_cursor *m_txc_audit_blocks;
|
||||
MDB_cursor *m_txc_carrot_yield_txs;
|
||||
|
||||
MDB_cursor *m_txc_token_txs;
|
||||
MDB_cursor *m_txc_tokens;
|
||||
MDB_cursor *m_txc_asset_type_counts;
|
||||
|
||||
MDB_cursor *m_txc_rct_count_info;
|
||||
|
||||
MDB_cursor *m_txc_rollup_tx_info;
|
||||
|
||||
} mdb_txn_cursors;
|
||||
|
||||
#define m_cur_blocks m_cursors->m_txc_blocks
|
||||
@@ -104,6 +115,17 @@ typedef struct mdb_txn_cursors
|
||||
#define m_cur_circ_supply_tally m_cursors->m_txc_circ_supply_tally
|
||||
#define m_cur_yield_txs m_cursors->m_txc_yield_txs
|
||||
#define m_cur_yield_blocks m_cursors->m_txc_yield_blocks
|
||||
#define m_cur_audit_txs m_cursors->m_txc_audit_txs
|
||||
#define m_cur_audit_blocks m_cursors->m_txc_audit_blocks
|
||||
#define m_cur_carrot_yield_txs m_cursors->m_txc_carrot_yield_txs
|
||||
|
||||
#define m_cur_token_txs m_cursors->m_txc_token_txs
|
||||
#define m_cur_tokens m_cursors->m_txc_tokens
|
||||
#define m_cur_asset_type_counts m_cursors->m_txc_asset_type_counts
|
||||
|
||||
#define m_cur_rct_count_info m_cursors->m_txc_rct_count_info
|
||||
|
||||
#define m_cur_rollup_tx_info m_cursors->m_txc_rollup_tx_info
|
||||
|
||||
typedef struct mdb_rflags
|
||||
{
|
||||
@@ -131,6 +153,18 @@ typedef struct mdb_rflags
|
||||
bool m_rf_circ_supply_tally;
|
||||
bool m_rf_yield_txs;
|
||||
bool m_rf_yield_blocks;
|
||||
bool m_rf_audit_txs;
|
||||
bool m_rf_audit_blocks;
|
||||
bool m_rf_carrot_yield_txs;
|
||||
|
||||
bool m_rf_token_txs;
|
||||
bool m_rf_tokens;
|
||||
bool m_rf_asset_type_counts;
|
||||
|
||||
bool m_rf_rct_count_info;
|
||||
|
||||
bool m_rf_rollup_tx_info;
|
||||
|
||||
} mdb_rflags;
|
||||
|
||||
typedef struct mdb_threadinfo
|
||||
@@ -233,6 +267,8 @@ public:
|
||||
|
||||
virtual cryptonote::blobdata get_block_blob_from_height(const uint64_t& height) const;
|
||||
|
||||
virtual std::pair<std::vector<uint64_t>, uint64_t> get_block_cumulative_rct_outputs_old(const std::vector<uint64_t> &heights, const std::string asset_type) const;
|
||||
|
||||
virtual std::pair<std::vector<uint64_t>, uint64_t> get_block_cumulative_rct_outputs(const std::vector<uint64_t> &heights, const std::string asset_type) const;
|
||||
|
||||
virtual uint64_t get_block_timestamp(const uint64_t& height) const;
|
||||
@@ -268,6 +304,10 @@ public:
|
||||
virtual uint64_t height() const;
|
||||
|
||||
virtual std::map<std::string, uint64_t> get_circulating_supply() const;
|
||||
|
||||
virtual std::map<std::string, cryptonote::token_metadata_t> get_tokens() const;
|
||||
|
||||
virtual bool is_tx_paid_for(const cryptonote::transaction& tx) const;
|
||||
|
||||
virtual bool tx_exists(const crypto::hash& h) const;
|
||||
virtual bool tx_exists(const crypto::hash& h, uint64_t& tx_index) const;
|
||||
@@ -341,8 +381,9 @@ public:
|
||||
, const difficulty_type& cumulative_difficulty
|
||||
, const uint64_t& coins_generated
|
||||
, const std::vector<std::pair<transaction, blobdata>>& txs
|
||||
, const cryptonote::network_type& nettype
|
||||
, const cryptonote::network_type nettype
|
||||
, cryptonote::yield_block_info& ybi
|
||||
, cryptonote::audit_block_info& abi
|
||||
);
|
||||
|
||||
virtual void set_batch_transactions(bool batch_transactions);
|
||||
@@ -396,12 +437,15 @@ private:
|
||||
const difficulty_type& cumulative_difficulty,
|
||||
const uint64_t& coins_generated,
|
||||
uint64_t num_rct_outs,
|
||||
oracle::asset_type_counts& cum_rct_by_asset_type,
|
||||
oracle::asset_type_counts_v2& cum_rct_by_asset_type,
|
||||
const crypto::hash& blk_hash,
|
||||
uint64_t slippage_total,
|
||||
uint64_t yield_total,
|
||||
const cryptonote::network_type& nettype,
|
||||
cryptonote::yield_block_info& ybi
|
||||
uint64_t audit_total,
|
||||
uint64_t token_total,
|
||||
const cryptonote::network_type nettype,
|
||||
cryptonote::yield_block_info& ybi,
|
||||
cryptonote::audit_block_info& abi
|
||||
);
|
||||
|
||||
virtual void remove_block();
|
||||
@@ -455,12 +499,19 @@ private:
|
||||
// migrate from older DB version to current
|
||||
void migrate(const uint32_t oldversion);
|
||||
|
||||
// migrate from DB version 0 to 1
|
||||
//void migrate_0_1();
|
||||
// migrate from DB version 2 to 3
|
||||
void migrate_2_3();
|
||||
|
||||
void cleanup_batch();
|
||||
|
||||
virtual int get_yield_block_info(const uint64_t height, yield_block_info& ybi);
|
||||
virtual int get_yield_tx_info(const uint64_t height, std::vector<yield_tx_info>& yti_container);
|
||||
virtual int get_audit_block_info(const uint64_t height, audit_block_info& abi) const;
|
||||
virtual int get_audit_tx_info(const uint64_t height, std::vector<yield_tx_info>& ati_container) const;
|
||||
|
||||
virtual int get_yield_block_info(const uint64_t height, yield_block_info& ybi) const;
|
||||
virtual int get_yield_tx_info(const uint64_t height, std::vector<yield_tx_info>& yti_container) const;
|
||||
virtual int get_carrot_yield_tx_info(const uint64_t height, std::vector<yield_tx_info_carrot>& yti_container) const;
|
||||
|
||||
virtual int get_token_tx_info(const uint64_t height, std::vector<token_tx_info_carrot>& tti_container) const;
|
||||
|
||||
private:
|
||||
MDB_env* m_env;
|
||||
@@ -498,6 +549,19 @@ private:
|
||||
|
||||
MDB_dbi m_yield_txs;
|
||||
MDB_dbi m_yield_blocks;
|
||||
|
||||
MDB_dbi m_audit_txs;
|
||||
MDB_dbi m_audit_blocks;
|
||||
|
||||
MDB_dbi m_carrot_yield_txs;
|
||||
|
||||
MDB_dbi m_token_txs;
|
||||
MDB_dbi m_tokens;
|
||||
MDB_dbi m_asset_type_counts;
|
||||
|
||||
MDB_dbi m_rct_count_info;
|
||||
|
||||
MDB_dbi m_rollup_tx_info;
|
||||
|
||||
mutable uint64_t m_cum_size; // used in batch size estimation
|
||||
mutable unsigned int m_cum_count;
|
||||
|
||||
+38
-14
@@ -76,7 +76,7 @@ public:
|
||||
virtual uint64_t get_block_height(const crypto::hash& h) const override { return 0; }
|
||||
virtual cryptonote::block_header get_block_header(const crypto::hash& h) const override { return cryptonote::block_header(); }
|
||||
virtual uint64_t get_block_timestamp(const uint64_t& height) const override { return 0; }
|
||||
virtual std::vector<uint64_t> get_block_cumulative_rct_outputs(const std::vector<uint64_t> &heights) const override { return {}; }
|
||||
virtual std::pair<std::vector<uint64_t>, uint64_t> get_block_cumulative_rct_outputs(const std::vector<uint64_t> &heights, const std::string asset_type) const override { return {}; }
|
||||
virtual uint64_t get_top_block_timestamp() const override { return 0; }
|
||||
virtual size_t get_block_weight(const uint64_t& height) const override { return 128; }
|
||||
virtual std::vector<uint64_t> get_block_weights(uint64_t start_height, size_t count) const override { return {}; }
|
||||
@@ -92,6 +92,7 @@ public:
|
||||
virtual crypto::hash top_block_hash(uint64_t *block_height = NULL) const override { if (block_height) *block_height = 0; return crypto::hash(); }
|
||||
virtual cryptonote::block get_top_block() const override { return cryptonote::block(); }
|
||||
virtual uint64_t height() const override { return 1; }
|
||||
virtual std::map<std::string, uint64_t> get_circulating_supply() const override { return std::map<std::string, uint64_t>{}; }
|
||||
virtual bool tx_exists(const crypto::hash& h) const override { return false; }
|
||||
virtual bool tx_exists(const crypto::hash& h, uint64_t& tx_index) const override { return false; }
|
||||
virtual uint64_t get_tx_unlock_time(const crypto::hash& h) const override { return 0; }
|
||||
@@ -101,20 +102,23 @@ public:
|
||||
virtual std::vector<cryptonote::transaction> get_tx_list(const std::vector<crypto::hash>& hlist) const override { return std::vector<cryptonote::transaction>(); }
|
||||
virtual uint64_t get_tx_block_height(const crypto::hash& h) const override { return 0; }
|
||||
virtual uint64_t get_num_outputs(const uint64_t& amount) const override { return 1; }
|
||||
virtual uint64_t get_num_outputs_of_asset_type(const std::string asset_type) const override { return 1; }
|
||||
virtual uint64_t get_indexing_base() const override { return 0; }
|
||||
virtual cryptonote::output_data_t get_output_key(const uint64_t& amount, const uint64_t& index, bool include_commitmemt) const override { return cryptonote::output_data_t(); }
|
||||
virtual cryptonote::tx_out_index get_output_tx_and_index_from_global(const uint64_t& index) const override { return cryptonote::tx_out_index(); }
|
||||
virtual cryptonote::tx_out_index get_output_tx_and_index(const uint64_t& amount, const uint64_t& index) const override { return cryptonote::tx_out_index(); }
|
||||
virtual void get_output_tx_and_index(const uint64_t& amount, const std::vector<uint64_t> &offsets, std::vector<cryptonote::tx_out_index> &indices) const override {}
|
||||
virtual void get_output_key(const epee::span<const uint64_t> &amounts, const std::vector<uint64_t> &offsets, std::vector<cryptonote::output_data_t> &outputs, bool allow_partial = false) const override {}
|
||||
virtual void get_output_id_from_asset_type_output_index(const std::string asset_type, const std::vector<uint64_t> &asset_type_output_indices, std::vector<uint64_t> &output_indices) const override {}
|
||||
virtual uint64_t get_output_id_from_asset_type_output_index(const std::string asset_type, const uint64_t &asset_type_output_index) const override { return 1; }
|
||||
virtual bool can_thread_bulk_indices() const override { return false; }
|
||||
virtual std::vector<std::vector<uint64_t>> get_tx_amount_output_indices(const uint64_t tx_index, size_t n_txes) const override { return std::vector<std::vector<uint64_t>>(); }
|
||||
virtual std::vector<std::vector<std::pair<uint64_t, uint64_t>>> get_tx_amount_output_indices(const uint64_t tx_index, size_t n_txes) const override { return std::vector<std::vector<std::pair<uint64_t, uint64_t>>>(); }
|
||||
virtual bool has_key_image(const crypto::key_image& img) const override { return false; }
|
||||
virtual void remove_block() override { }
|
||||
virtual uint64_t add_transaction_data(const crypto::hash& blk_hash, const std::pair<cryptonote::transaction, cryptonote::blobdata_ref>& tx, const crypto::hash& tx_hash, const crypto::hash& tx_prunable_hash) override {return 0;}
|
||||
virtual void remove_transaction_data(const crypto::hash& tx_hash, const cryptonote::transaction& tx) override {}
|
||||
virtual uint64_t add_output(const crypto::hash& tx_hash, const cryptonote::tx_out& tx_output, const uint64_t& local_index, const uint64_t unlock_time, const rct::key *commitment) override {return 0;}
|
||||
virtual void add_tx_amount_output_indices(const uint64_t tx_index, const std::vector<uint64_t>& amount_output_indices) override {}
|
||||
virtual uint64_t add_transaction_data(const crypto::hash& blk_hash, const std::pair<cryptonote::transaction, cryptonote::blobdata_ref>& tx, const crypto::hash& tx_hash, const crypto::hash& tx_prunable_hash, const bool miner_tx) override {return 0;}
|
||||
virtual void remove_transaction_data(const crypto::hash& tx_hash, const cryptonote::transaction& tx, const bool miner_tx) override {}
|
||||
virtual std::pair<uint64_t, uint64_t> add_output(const crypto::hash& tx_hash, const cryptonote::tx_out& tx_output, const uint64_t& local_index, const uint64_t unlock_time, const rct::key *commitment) override {return std::make_pair(0,0);}
|
||||
virtual void add_tx_amount_output_indices(const uint64_t tx_index, const std::vector<std::pair<uint64_t, uint64_t>>& amount_output_indices) override {}
|
||||
virtual void add_spent_key(const crypto::key_image& k_image) override {}
|
||||
virtual void remove_spent_key(const crypto::key_image& k_image) override {}
|
||||
|
||||
@@ -135,17 +139,37 @@ public:
|
||||
virtual bool get_txpool_tx_meta(const crypto::hash& txid, cryptonote::txpool_tx_meta_t &meta) const override { return false; }
|
||||
virtual bool get_txpool_tx_blob(const crypto::hash& txid, cryptonote::blobdata &bd, relay_category tx_category) const override { return false; }
|
||||
virtual uint64_t get_database_size() const override { return 0; }
|
||||
|
||||
virtual int get_audit_block_info(const uint64_t height, audit_block_info& abi) const override { return 0; }
|
||||
virtual int get_audit_tx_info(const uint64_t height, std::vector<yield_tx_info>& ati_container) const override { return 0; }
|
||||
|
||||
virtual int get_yield_block_info(const uint64_t height, yield_block_info& ybi) const override { return 0; }
|
||||
virtual int get_yield_tx_info(const uint64_t height, std::vector<yield_tx_info>& yti_container) const override { return 0; }
|
||||
virtual int get_carrot_yield_tx_info(const uint64_t height, std::vector<yield_tx_info_carrot>& yti_container) const override { return 0; }
|
||||
|
||||
virtual cryptonote::blobdata get_txpool_tx_blob(const crypto::hash& txid, relay_category tx_category) const override { return ""; }
|
||||
virtual bool for_all_txpool_txes(std::function<bool(const crypto::hash&, const cryptonote::txpool_tx_meta_t&, const cryptonote::blobdata_ref*)>, bool include_blob = false, relay_category category = relay_category::broadcasted) const override { return false; }
|
||||
|
||||
virtual void add_block( const cryptonote::block& blk
|
||||
, size_t block_weight
|
||||
, uint64_t long_term_block_weight
|
||||
, const cryptonote::difficulty_type& cumulative_difficulty
|
||||
, const uint64_t& coins_generated
|
||||
, uint64_t num_rct_outs
|
||||
, const crypto::hash& blk_hash
|
||||
) override { }
|
||||
virtual void add_block( const block& blk,
|
||||
size_t block_weight,
|
||||
uint64_t long_term_block_weight,
|
||||
const difficulty_type& cumulative_difficulty,
|
||||
const uint64_t& coins_generated,
|
||||
uint64_t num_rct_outs,
|
||||
oracle::asset_type_counts_v2& cum_rct_by_asset_type,
|
||||
const crypto::hash& blk_hash,
|
||||
uint64_t slippage_total,
|
||||
uint64_t yield_total,
|
||||
uint64_t audit_total,
|
||||
uint64_t token_total,
|
||||
const cryptonote::network_type nettype,
|
||||
cryptonote::yield_block_info& ybi,
|
||||
cryptonote::audit_block_info& abi
|
||||
) override { }
|
||||
|
||||
virtual std::map<std::string, cryptonote::token_metadata_t> get_tokens() const override { return {}; }
|
||||
virtual bool is_tx_paid_for(const cryptonote::transaction& tx) const override { return true; }
|
||||
virtual int get_token_tx_info(const uint64_t height, std::vector<token_tx_info_carrot>& tti_container) const override { return 0; }
|
||||
virtual cryptonote::block get_block_from_height(const uint64_t& height) const override { return cryptonote::block(); }
|
||||
virtual void set_hard_fork_version(uint64_t height, uint8_t version) override {}
|
||||
virtual uint8_t get_hard_fork_version(uint64_t height) const override { return 0; }
|
||||
|
||||
@@ -133,6 +133,31 @@ monero_private_headers(blockchain_stats
|
||||
${blockchain_stats_private_headers})
|
||||
|
||||
|
||||
set(blockchain_scanner_sources
|
||||
blockchain_scanner.cpp
|
||||
)
|
||||
|
||||
set(blockchain_scanner_private_headers)
|
||||
|
||||
monero_private_headers(blockchain_scanner
|
||||
${blockchain_scanner_private_headers})
|
||||
|
||||
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/blockchain_audit.cpp" AND NOT IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/blockchain_audit.cpp")
|
||||
set(blockchain_audit_sources
|
||||
blockchain_audit.cpp
|
||||
threadpool_boost.cpp
|
||||
)
|
||||
|
||||
set(blockchain_audit_private_headers
|
||||
threadpool_boost.h
|
||||
)
|
||||
|
||||
monero_private_headers(blockchain_audit
|
||||
${blockchain_audit_private_headers})
|
||||
else()
|
||||
message(STATUS "blockchain_audit.cpp not found - not building the audit tool")
|
||||
endif()
|
||||
|
||||
monero_add_executable(blockchain_import
|
||||
${blockchain_import_sources}
|
||||
${blockchain_import_private_headers})
|
||||
@@ -281,6 +306,56 @@ set_property(TARGET blockchain_depth
|
||||
OUTPUT_NAME "salvium-blockchain-depth")
|
||||
install(TARGETS blockchain_depth DESTINATION bin)
|
||||
|
||||
monero_add_executable(blockchain_scanner
|
||||
${blockchain_scanner_sources}
|
||||
${blockchain_scanner_private_headers})
|
||||
|
||||
target_link_libraries(blockchain_scanner
|
||||
PRIVATE
|
||||
cryptonote_core
|
||||
blockchain_db
|
||||
version
|
||||
epee
|
||||
${Boost_FILESYSTEM_LIBRARY}
|
||||
${Boost_SYSTEM_LIBRARY}
|
||||
${Boost_THREAD_LIBRARY}
|
||||
${CMAKE_THREAD_LIBS_INIT}
|
||||
${EXTRA_LIBRARIES})
|
||||
|
||||
set_property(TARGET blockchain_scanner
|
||||
PROPERTY
|
||||
OUTPUT_NAME "salvium-blockchain-scanner")
|
||||
install(TARGETS blockchain_scanner DESTINATION bin)
|
||||
|
||||
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/blockchain_audit.cpp" AND NOT IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/blockchain_audit.cpp")
|
||||
monero_add_executable(blockchain_audit
|
||||
${blockchain_audit_sources}
|
||||
${blockchain_audit_private_headers})
|
||||
|
||||
target_include_directories(blockchain_audit PRIVATE /usr/include/mysql-cppconn/jdbc)
|
||||
|
||||
target_link_libraries(blockchain_audit
|
||||
PRIVATE
|
||||
wallet
|
||||
crypto
|
||||
cncrypto
|
||||
cryptonote_core
|
||||
blockchain_db
|
||||
version
|
||||
epee
|
||||
mysqlcppconn
|
||||
${Boost_FILESYSTEM_LIBRARY}
|
||||
${Boost_SYSTEM_LIBRARY}
|
||||
${Boost_THREAD_LIBRARY}
|
||||
${CMAKE_THREAD_LIBS_INIT}
|
||||
${EXTRA_LIBRARIES})
|
||||
|
||||
set_property(TARGET blockchain_audit
|
||||
PROPERTY
|
||||
OUTPUT_NAME "salvium-blockchain-audit")
|
||||
install(TARGETS blockchain_audit DESTINATION bin)
|
||||
endif()
|
||||
|
||||
monero_add_executable(blockchain_stats
|
||||
${blockchain_stats_sources}
|
||||
${blockchain_stats_private_headers})
|
||||
|
||||
@@ -488,8 +488,9 @@ int import_from_file(cryptonote::core& core, const std::string& import_file_path
|
||||
try
|
||||
{
|
||||
cryptonote::yield_block_info ybi; // This just gets discarded because we aren't looking to maintain a cache of YBI data in the import utility
|
||||
cryptonote::audit_block_info abi; // This just gets discarded because we aren't looking to maintain a cache of ABI data in the import utility
|
||||
uint64_t long_term_block_weight = core.get_blockchain_storage().get_next_long_term_block_weight(block_weight);
|
||||
core.get_blockchain_storage().get_db().add_block(std::make_pair(b, block_to_blob(b)), block_weight, long_term_block_weight, cumulative_difficulty, coins_generated, txs, opt_testnet ? cryptonote::TESTNET : opt_stagenet ? cryptonote::STAGENET : cryptonote::MAINNET, ybi);
|
||||
core.get_blockchain_storage().get_db().add_block(std::make_pair(b, block_to_blob(b)), block_weight, long_term_block_weight, cumulative_difficulty, coins_generated, txs, opt_testnet ? cryptonote::TESTNET : opt_stagenet ? cryptonote::STAGENET : cryptonote::MAINNET, ybi, abi);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,383 @@
|
||||
// Copyright (c) 2014-2019, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include "common/command_line.h"
|
||||
#include "common/i18n.h"
|
||||
#include "common/password.h"
|
||||
#include "common/varint.h"
|
||||
#include "cryptonote_basic/cryptonote_boost_serialization.h"
|
||||
#include "cryptonote_core/tx_pool.h"
|
||||
#include "cryptonote_core/cryptonote_core.h"
|
||||
#include "cryptonote_core/cryptonote_tx_utils.h"
|
||||
#include "cryptonote_core/blockchain.h"
|
||||
#include "blockchain_db/blockchain_db.h"
|
||||
#include "oracle/pricing_record.h"
|
||||
#include "version.h"
|
||||
|
||||
#undef MONERO_DEFAULT_LOG_CATEGORY
|
||||
#define MONERO_DEFAULT_LOG_CATEGORY "bcutil"
|
||||
|
||||
#define DELIM "|"
|
||||
#define DEF_STAKE_MODE "all"
|
||||
|
||||
namespace po = boost::program_options;
|
||||
using namespace epee;
|
||||
using namespace cryptonote;
|
||||
|
||||
namespace scanner
|
||||
{
|
||||
const char* tr(const char* str)
|
||||
{
|
||||
return i18n_translate(str, "tools::scanner");
|
||||
}
|
||||
}
|
||||
|
||||
static bool stop_requested = false;
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
TRY_ENTRY();
|
||||
|
||||
epee::string_tools::set_module_name_and_folder(argv[0]);
|
||||
|
||||
uint32_t log_level = 0;
|
||||
uint64_t block_start = 0;
|
||||
uint64_t block_stop = 0;
|
||||
|
||||
tools::on_startup();
|
||||
|
||||
boost::filesystem::path output_file_path;
|
||||
|
||||
po::options_description desc_cmd_only("Command line options");
|
||||
po::options_description desc_cmd_sett("Command line options and settings options");
|
||||
const command_line::arg_descriptor<std::string> arg_log_level = {"log-level", "0-4 or categories", ""};
|
||||
const command_line::arg_descriptor<uint64_t> arg_block_start = {"block-start", "start at block number", block_start};
|
||||
const command_line::arg_descriptor<uint64_t> arg_block_stop = {"block-stop", "Stop at block number", block_stop};
|
||||
const command_line::arg_descriptor<std::string> arg_delimiter = {"delimiter", "\"<string>\"", DELIM};
|
||||
const command_line::arg_descriptor<std::string> arg_stake_mode = {"stake", "\"<string>\"", DEF_STAKE_MODE};
|
||||
const command_line::arg_descriptor<bool> arg_check_asset_types = {"check-asset-types", "Scan for asset-type issues", false};
|
||||
|
||||
command_line::add_arg(desc_cmd_sett, cryptonote::arg_data_dir);
|
||||
command_line::add_arg(desc_cmd_sett, cryptonote::arg_testnet_on);
|
||||
command_line::add_arg(desc_cmd_sett, cryptonote::arg_stagenet_on);
|
||||
command_line::add_arg(desc_cmd_sett, arg_log_level);
|
||||
command_line::add_arg(desc_cmd_sett, arg_block_start);
|
||||
command_line::add_arg(desc_cmd_sett, arg_block_stop);
|
||||
command_line::add_arg(desc_cmd_sett, arg_delimiter);
|
||||
command_line::add_arg(desc_cmd_sett, arg_stake_mode);
|
||||
command_line::add_arg(desc_cmd_sett, arg_check_asset_types);
|
||||
command_line::add_arg(desc_cmd_only, command_line::arg_help);
|
||||
|
||||
po::options_description desc_options("Allowed options");
|
||||
desc_options.add(desc_cmd_only).add(desc_cmd_sett);
|
||||
|
||||
po::variables_map vm;
|
||||
bool r = command_line::handle_error_helper(desc_options, [&]()
|
||||
{
|
||||
auto parser = po::command_line_parser(argc, argv).options(desc_options);
|
||||
po::store(parser.run(), vm);
|
||||
po::notify(vm);
|
||||
return true;
|
||||
});
|
||||
if (! r)
|
||||
return 1;
|
||||
|
||||
if (command_line::get_arg(vm, command_line::arg_help))
|
||||
{
|
||||
std::cout << "Salvium '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL << ENDL;
|
||||
std::cout << desc_options << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
mlog_configure(mlog_get_default_log_path("monero-blockchain-stats.log"), true);
|
||||
if (!command_line::is_arg_defaulted(vm, arg_log_level))
|
||||
mlog_set_log(command_line::get_arg(vm, arg_log_level).c_str());
|
||||
else
|
||||
mlog_set_log(std::string(std::to_string(log_level) + ",bcutil:INFO").c_str());
|
||||
|
||||
LOG_PRINT_L0("Starting...");
|
||||
|
||||
std::string opt_data_dir = command_line::get_arg(vm, cryptonote::arg_data_dir);
|
||||
bool opt_testnet = command_line::get_arg(vm, cryptonote::arg_testnet_on);
|
||||
bool opt_stagenet = command_line::get_arg(vm, cryptonote::arg_stagenet_on);
|
||||
network_type net_type = opt_testnet ? TESTNET : opt_stagenet ? STAGENET : MAINNET;
|
||||
block_start = command_line::get_arg(vm, arg_block_start);
|
||||
block_stop = command_line::get_arg(vm, arg_block_stop);
|
||||
std::string delimiter = command_line::get_arg(vm, arg_delimiter);
|
||||
std::string stake_mode = command_line::get_arg(vm, arg_stake_mode);
|
||||
bool opt_check_asset_types = command_line::get_arg(vm, arg_check_asset_types);
|
||||
|
||||
// If we wanted to use the memory pool, we would set up a fake_core.
|
||||
|
||||
// Use Blockchain instead of lower-level BlockchainDB for two reasons:
|
||||
// 1. Blockchain has the init() method for easy setup
|
||||
// 2. exporter needs to use get_current_blockchain_height(), get_block_id_by_height(), get_block_by_hash()
|
||||
//
|
||||
// cannot match blockchain_storage setup above with just one line,
|
||||
// e.g.
|
||||
// Blockchain* core_storage = new Blockchain(NULL);
|
||||
// because unlike blockchain_storage constructor, which takes a pointer to
|
||||
// tx_memory_pool, Blockchain's constructor takes tx_memory_pool object.
|
||||
LOG_PRINT_L0("Initializing source blockchain (BlockchainDB)");
|
||||
std::unique_ptr<BlockchainAndPool> core_storage = std::make_unique<BlockchainAndPool>();
|
||||
|
||||
BlockchainDB* db = new_db();
|
||||
if (db == NULL)
|
||||
{
|
||||
LOG_ERROR("Failed to initialize a database");
|
||||
throw std::runtime_error("Failed to initialize a database");
|
||||
}
|
||||
LOG_PRINT_L0("database: LMDB");
|
||||
|
||||
boost::filesystem::path folder(opt_data_dir);
|
||||
if (opt_stagenet) {
|
||||
folder /= std::to_string(STAGENET_VERSION);
|
||||
} else if (opt_testnet) {
|
||||
folder /= std::to_string(TESTNET_VERSION);
|
||||
}
|
||||
folder /= db->get_db_name();
|
||||
LOG_PRINT_L0("Loading blockchain from folder " << folder << " ...");
|
||||
const std::string filename = folder.string();
|
||||
|
||||
try
|
||||
{
|
||||
db->open(filename, DBF_RDONLY);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
LOG_PRINT_L0("Error opening database: " << e.what());
|
||||
return 1;
|
||||
}
|
||||
r = core_storage->blockchain.init(db, net_type);
|
||||
|
||||
CHECK_AND_ASSERT_MES(r, 1, "Failed to initialize source blockchain storage");
|
||||
LOG_PRINT_L0("Source blockchain storage initialized OK");
|
||||
|
||||
tools::signal_handler::install([](int type) {
|
||||
stop_requested = true;
|
||||
});
|
||||
|
||||
const uint64_t db_height = db->height();
|
||||
if (!block_stop)
|
||||
block_stop = db_height;
|
||||
MINFO("Starting from height " << block_start << ", stopping at height " << block_stop);
|
||||
|
||||
/*
|
||||
* The default output can be plotted with GnuPlot using these commands:
|
||||
set key autotitle columnhead
|
||||
set title "Salvium Blockchain Growth"
|
||||
set timefmt "%Y-%m-%d"
|
||||
set xdata time
|
||||
set xrange ["2014-04-17":*]
|
||||
set format x "%Y-%m-%d"
|
||||
set yrange [0:*]
|
||||
set y2range [0:*]
|
||||
set ylabel "Txs/Day"
|
||||
set y2label "Bytes"
|
||||
set y2tics nomirror
|
||||
plot 'stats.csv' index "DATA" using (timecolumn(1,"%Y-%m-%d")):4 with lines, '' using (timecolumn(1,"%Y-%m-%d")):7 axes x1y2 with lines
|
||||
*/
|
||||
|
||||
// spit out a comment that GnuPlot can use as an index
|
||||
std::cout << ENDL << "# DATA" << ENDL;
|
||||
std::cout << "Date" << delimiter << "Height" << delimiter << "Transaction ID" << delimiter << "Reason" << delimiter << "Extra Information";
|
||||
std::cout << ENDL;
|
||||
|
||||
#define MAX_INOUT 0xffffffff
|
||||
#define MAX_RINGS 0xffffffff
|
||||
|
||||
struct tm prevtm = {0}, currtm;
|
||||
// uint64_t currsz = 0;
|
||||
// uint64_t currtxs = 0;
|
||||
// uint64_t currblks = 0;
|
||||
|
||||
const std::map<uint8_t, std::pair<uint64_t, std::pair<std::string, std::string>>> audit_hard_forks = get_config(net_type).AUDIT_HARD_FORKS;
|
||||
|
||||
for (uint64_t h = block_start; h < block_stop; ++h)
|
||||
{
|
||||
cryptonote::blobdata bd = db->get_block_blob_from_height(h);
|
||||
cryptonote::block blk;
|
||||
if (!cryptonote::parse_and_validate_block_from_blob(bd, blk))
|
||||
{
|
||||
LOG_PRINT_L0("Bad block from db");
|
||||
return 1;
|
||||
}
|
||||
time_t tt = blk.timestamp;
|
||||
char timebuf[64];
|
||||
epee::misc_utils::get_gmt_time(tt, currtm);
|
||||
if (!prevtm.tm_year)
|
||||
prevtm = currtm;
|
||||
// catch change of day
|
||||
if (currtm.tm_mday > prevtm.tm_mday || (currtm.tm_mday == 1 && prevtm.tm_mday > 27))
|
||||
{
|
||||
// check for timestamp fudging around month ends
|
||||
if (prevtm.tm_mday == 1 && currtm.tm_mday > 27)
|
||||
goto skip;
|
||||
strftime(timebuf, sizeof(timebuf), "%Y-%m-%d", &currtm);
|
||||
prevtm = currtm;
|
||||
}
|
||||
skip:
|
||||
// currsz += bd.size();
|
||||
std::set<std::string> used_assets, miner_tx_assets, protocol_tx_assets;
|
||||
std::map<size_t, std::vector<std::string>> used_tx_versions;
|
||||
used_assets.insert("SAL");
|
||||
|
||||
uint8_t hf_version = blk.major_version;
|
||||
|
||||
// Check TX versions
|
||||
if (blk.miner_tx.version != 2) {
|
||||
std::cout << timebuf << "" << delimiter << "" << h << "" << delimiter << "" << blk.miner_tx.hash << "" << delimiter << "invalid miner TX version detected" << delimiter << "version:" << blk.miner_tx.version << std::endl;
|
||||
}
|
||||
if (blk.protocol_tx.version != 2 && h>0) {
|
||||
std::cout << timebuf << "" << delimiter << "" << h << "" << delimiter << "" << blk.protocol_tx.hash << "" << delimiter << "invalid protocol TX version detected" << delimiter << "version:" << blk.protocol_tx.version << std::endl;
|
||||
}
|
||||
|
||||
// Get the miner_tx assets
|
||||
std::set<crypto::public_key> used_keys;
|
||||
for (const auto& miner_tx_vout : blk.miner_tx.vout) {
|
||||
std::string asset_type;
|
||||
if (!cryptonote::get_output_asset_type(miner_tx_vout, asset_type)) {
|
||||
throw std::runtime_error("Aborting: failed to get output asset type from miner_tx");
|
||||
} else if (blk.major_version >= HF_VERSION_SALVIUM_ONE_PROOFS && asset_type != "SAL1") {
|
||||
throw std::runtime_error("Aborting: invalid output asset type from miner_tx: " + asset_type);
|
||||
} else if (blk.major_version < HF_VERSION_SALVIUM_ONE_PROOFS && asset_type != "SAL") {
|
||||
throw std::runtime_error("Aborting: invalid output asset type from miner_tx: " + asset_type + ", HF:" + std::to_string(blk.major_version));
|
||||
}
|
||||
miner_tx_assets.insert(asset_type);
|
||||
if (miner_tx_vout.amount > 13500000000 && h>0) {
|
||||
std::cout << timebuf << "" << delimiter << "" << h << "" << delimiter << "" << blk.miner_tx.hash << "" << delimiter << "invalid miner TX amount detected" << delimiter << "amount:" << miner_tx_vout.amount << std::endl;
|
||||
}
|
||||
crypto::public_key key;
|
||||
cryptonote::get_output_public_key(miner_tx_vout, key);
|
||||
if (used_keys.count(key)) {
|
||||
std::cout << timebuf << "" << delimiter << "" << h << "" << delimiter << "" << blk.miner_tx.hash << "" << delimiter << "invalid miner TX - duplicate output detected" << delimiter << "pubkey:" << key << std::endl;
|
||||
}
|
||||
used_keys.insert(key);
|
||||
}
|
||||
|
||||
// Get the protocol_tx assets
|
||||
used_keys.clear();
|
||||
for (const auto& protocol_tx_vout : blk.protocol_tx.vout) {
|
||||
std::string asset_type;
|
||||
if (!cryptonote::get_output_asset_type(protocol_tx_vout, asset_type)) {
|
||||
throw std::runtime_error("Aborting: failed to get output asset type from protocol_tx");
|
||||
} else if (blk.major_version >= HF_VERSION_SALVIUM_ONE_PROOFS && asset_type != "SAL1") {
|
||||
throw std::runtime_error("Aborting: invalid output asset type from protocol_tx: " + asset_type);
|
||||
} else if (blk.major_version < HF_VERSION_SALVIUM_ONE_PROOFS && asset_type != "SAL") {
|
||||
throw std::runtime_error("Aborting: invalid output asset type from protocol_tx: " + asset_type + ", HF:" + std::to_string(blk.major_version));
|
||||
}
|
||||
protocol_tx_assets.insert(asset_type);
|
||||
if (protocol_tx_vout.amount > 25000000000000) {
|
||||
//std::cout << timebuf << "" << delimiter << "" << h << "" << delimiter << "" << blk.protocol_tx.hash << "" << delimiter << "large protocol TX amount detected from height " << (h-audit_lock_period) << delimiter << "amount:" << protocol_tx_vout.amount << std::endl;
|
||||
}
|
||||
crypto::public_key key;
|
||||
cryptonote::get_output_public_key(protocol_tx_vout, key);
|
||||
if (used_keys.count(key)) {
|
||||
std::cout << timebuf << "" << delimiter << "" << h << "" << delimiter << "" << blk.protocol_tx.hash << "" << delimiter << "invalid protocol TX - duplicate output detected" << delimiter << "pubkey:" << key << std::endl;
|
||||
}
|
||||
used_keys.insert(key);
|
||||
}
|
||||
|
||||
for (const auto& tx_id : blk.tx_hashes)
|
||||
{
|
||||
if (tx_id == crypto::null_hash)
|
||||
{
|
||||
throw std::runtime_error("Aborting: tx == null_hash");
|
||||
}
|
||||
if (!db->get_pruned_tx_blob(tx_id, bd))
|
||||
{
|
||||
throw std::runtime_error("Aborting: tx not found");
|
||||
}
|
||||
transaction tx;
|
||||
if (!parse_and_validate_tx_base_from_blob(bd, tx))
|
||||
{
|
||||
std::cout << timebuf << "" << delimiter << "" << h << "" << delimiter << "" << tx_id << "" << delimiter << "invalid TX detected" << delimiter << std::endl;
|
||||
continue;
|
||||
}
|
||||
// currsz += bd.size();
|
||||
// if (db->get_prunable_tx_blob(tx_id, bd))
|
||||
// currsz += bd.size();
|
||||
// currtxs++;
|
||||
db->get_prunable_tx_blob(tx_id, bd);
|
||||
|
||||
if (tx.type != cryptonote::transaction_type::TRANSFER &&
|
||||
tx.type != cryptonote::transaction_type::BURN &&
|
||||
tx.type != cryptonote::transaction_type::STAKE &&
|
||||
tx.type != cryptonote::transaction_type::AUDIT) {
|
||||
std::cout << timebuf << "" << delimiter << "" << h << "" << delimiter << "" << tx_id << "" << delimiter << "invalid TX type detected" << delimiter << "type:" << (uint8_t)tx.type << std::endl;
|
||||
}
|
||||
|
||||
if ((tx.version != 2 && hf_version < HF_VERSION_ENABLE_N_OUTS) || (tx.version != 3 && hf_version < HF_VERSION_ENABLE_N_OUTS && tx.type == cryptonote::transaction_type::TRANSFER)) {
|
||||
std::cout << timebuf << "" << delimiter << "" << h << "" << delimiter << "" << tx_id << "" << delimiter << "invalid TX version detected" << delimiter << "version:" << tx.version << std::endl;
|
||||
}
|
||||
|
||||
if (tx.type == cryptonote::transaction_type::STAKE && stake_mode.compare("off")) {
|
||||
if (stake_mode.compare("all") == 0) {
|
||||
std::cout << timebuf << "" << delimiter << "" << h << "" << delimiter << "" << tx_id << "" << delimiter << "STAKE TX detected" << delimiter << "amount:" << (tx.amount_burnt / 100000000) << std::endl;
|
||||
} else if (stake_mode.compare("large") == 0 && tx.amount_burnt > 25000000000000llu) {
|
||||
std::cout << timebuf << "" << delimiter << "" << h << "" << delimiter << "" << tx_id << "" << delimiter << "large STAKE TX detected" << delimiter << "amount:" << (tx.amount_burnt / 100000000) << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
if (opt_check_asset_types) {
|
||||
if (tx.source_asset_type != "SAL") {
|
||||
throw std::runtime_error("Aborting: invalid source asset type found in tx");
|
||||
} else if (tx.destination_asset_type != "SAL") {
|
||||
if (tx.destination_asset_type == "BURN") {
|
||||
std::cout << timebuf << "" << delimiter << "" << h << "" << delimiter << "" << tx_id << "" << delimiter << "BURN TX detected" << delimiter << "amount:" << tx.amount_burnt << std::endl;
|
||||
} else {
|
||||
throw std::runtime_error("Aborting: invalid destination asset type found in tx");
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& tx_vout : tx.vout) {
|
||||
std::string asset_type;
|
||||
if (!cryptonote::get_output_asset_type(tx_vout, asset_type)) {
|
||||
throw std::runtime_error("Aborting: failed to get output asset type from tx");
|
||||
} else if (asset_type != "SAL") {
|
||||
throw std::runtime_error("Aborting: invalid output asset type from tx");
|
||||
}
|
||||
}
|
||||
|
||||
// Add the source currency to the list of expected ones
|
||||
used_assets.insert(tx.source_asset_type);
|
||||
}
|
||||
}
|
||||
|
||||
// currblks++;
|
||||
|
||||
if (stop_requested)
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
CATCH_ENTRY("Stats reporting error", 1);
|
||||
}
|
||||
@@ -211,8 +211,15 @@ int main(int argc, char* argv[])
|
||||
throw std::runtime_error("Failed to initialize a database");
|
||||
}
|
||||
|
||||
const std::string filename = (boost::filesystem::path(opt_data_dir) / db->get_db_name()).string();
|
||||
LOG_PRINT_L0("Loading blockchain from folder " << filename << " ...");
|
||||
boost::filesystem::path folder(opt_data_dir);
|
||||
if (opt_stagenet) {
|
||||
folder /= std::to_string(STAGENET_VERSION);
|
||||
} else if (opt_testnet) {
|
||||
folder /= std::to_string(TESTNET_VERSION);
|
||||
}
|
||||
folder /= db->get_db_name();
|
||||
LOG_PRINT_L0("Loading blockchain from folder " << folder << " ...");
|
||||
const std::string filename = folder.string();
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
#include <iostream>
|
||||
#include "threadpool_boost.h"
|
||||
|
||||
ThreadPool::ThreadPool(size_t numThreads)
|
||||
: workGuard(boost::asio::make_work_guard(ioService)) {
|
||||
for (size_t i = 0; i < numThreads; ++i) {
|
||||
workers.emplace_back([this]() {
|
||||
std::cerr << "Thread started" << std::endl;
|
||||
ioService.run();
|
||||
std::cerr << "Thread finished" << std::endl;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void ThreadPool::enqueue(std::function<void()> task) {
|
||||
ioService.post([task]() {
|
||||
try {
|
||||
task(); // Run the task
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << "Exception in thread pool task: " << e.what() << std::endl;
|
||||
} catch (...) {
|
||||
std::cerr << "Unknown exception in thread pool task!" << std::endl;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
bool ThreadPool::isStopping() const {
|
||||
return ioService.stopped(); // Check if io_context has stopped
|
||||
}
|
||||
|
||||
void ThreadPool::waitForCompletion() {
|
||||
std::cout << "Waiting for completion...\n";
|
||||
workGuard.reset(); // Allow ioService to stop when no more tasks
|
||||
ioService.run(); // Ensure no threads are left hanging
|
||||
|
||||
for (auto &worker : workers) {
|
||||
if (worker.joinable()) worker.join();
|
||||
}
|
||||
std::cout << "All threads joined.\n";
|
||||
}
|
||||
|
||||
ThreadPool::~ThreadPool() {
|
||||
waitForCompletion();
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
#ifndef THREADPOOL_BOOST_H
|
||||
#define THREADPOOL_BOOST_H
|
||||
|
||||
#include <boost/thread.hpp>
|
||||
#include <boost/asio.hpp>
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
|
||||
class ThreadPool {
|
||||
public:
|
||||
explicit ThreadPool(size_t numThreads);
|
||||
~ThreadPool();
|
||||
|
||||
void enqueue(std::function<void()> task);
|
||||
bool isStopping() const;
|
||||
void waitForCompletion();
|
||||
|
||||
private:
|
||||
boost::asio::io_service ioService;
|
||||
boost::asio::executor_work_guard<boost::asio::io_context::executor_type> workGuard;
|
||||
std::vector<boost::thread> workers;
|
||||
};
|
||||
|
||||
#endif // THREADPOOL_BOOST_H
|
||||
Binary file not shown.
@@ -0,0 +1,66 @@
|
||||
# Copyright (c) 2024, The Monero Project
|
||||
#
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification, are
|
||||
# permitted provided that the following conditions are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
# conditions and the following disclaimer.
|
||||
#
|
||||
# 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
# of conditions and the following disclaimer in the documentation and/or other
|
||||
# materials provided with the distribution.
|
||||
#
|
||||
# 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
# used to endorse or promote products derived from this software without specific
|
||||
# prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
# THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
set(carrot_core_sources
|
||||
account_secrets.cpp
|
||||
address_utils.cpp
|
||||
account.cpp
|
||||
carrot_enote_types.cpp
|
||||
core_types.cpp
|
||||
destination.cpp
|
||||
device_ram_borrowed.cpp
|
||||
enote_utils.cpp
|
||||
hash_functions.cpp
|
||||
lazy_amount_commitment.cpp
|
||||
output_set_finalization.cpp
|
||||
payment_proposal.cpp
|
||||
scan.cpp
|
||||
scan_unsafe.cpp
|
||||
sparc.cpp)
|
||||
|
||||
monero_find_all_headers(carrot_core_headers, "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
|
||||
monero_add_library(carrot_core
|
||||
${carrot_core_sources}
|
||||
${carrot_core_headers})
|
||||
|
||||
target_link_libraries(carrot_core
|
||||
PUBLIC
|
||||
cncrypto
|
||||
epee
|
||||
mx25519_static
|
||||
ringct_basic
|
||||
seraphis_crypto
|
||||
PRIVATE
|
||||
${EXTRA_LIBRARIES})
|
||||
|
||||
target_include_directories(carrot_core
|
||||
PUBLIC
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
PRIVATE
|
||||
${Boost_INCLUDE_DIRS})
|
||||
@@ -0,0 +1,480 @@
|
||||
// Copyright (c) 2014-2022, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#include "include_base_utils.h"
|
||||
#include "account.h"
|
||||
#include "warnings.h"
|
||||
#include "crypto/crypto.h"
|
||||
#include "crypto/generators.h"
|
||||
extern "C"
|
||||
{
|
||||
#include "crypto/keccak.h"
|
||||
}
|
||||
#include "cryptonote_basic/account.h"
|
||||
#include "cryptonote_config.h"
|
||||
#include "ringct/rctOps.h"
|
||||
|
||||
#undef MONERO_DEFAULT_LOG_CATEGORY
|
||||
#define MONERO_DEFAULT_LOG_CATEGORY "carrot_impl_account"
|
||||
|
||||
using namespace std;
|
||||
|
||||
DISABLE_VS_WARNINGS(4244 4345)
|
||||
|
||||
namespace carrot
|
||||
{
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
CarrotDestinationV1 carrot_and_legacy_account::cryptonote_address(const payment_id_t payment_id,
|
||||
const AddressDeriveType derive_type) const
|
||||
{
|
||||
CarrotDestinationV1 addr;
|
||||
switch (resolve_derive_type(derive_type))
|
||||
{
|
||||
case AddressDeriveType::Carrot:
|
||||
make_carrot_integrated_address_v1(get_keys().m_carrot_main_address.m_spend_public_key,
|
||||
get_keys().m_carrot_main_address.m_view_public_key,
|
||||
payment_id,
|
||||
addr);
|
||||
break;
|
||||
case AddressDeriveType::PreCarrot:
|
||||
make_carrot_integrated_address_v1(get_keys().m_account_address.m_spend_public_key,
|
||||
get_keys().m_account_address.m_view_public_key,
|
||||
payment_id,
|
||||
addr);
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("address derive type not recognized");
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
CarrotDestinationV1 carrot_and_legacy_account::subaddress(const subaddress_index_extended &subaddress_index) const
|
||||
{
|
||||
if (!subaddress_index.index.is_subaddress())
|
||||
return cryptonote_address(null_payment_id, subaddress_index.derive_type);
|
||||
|
||||
const cryptonote::account_keys &keys = get_keys();
|
||||
|
||||
CarrotDestinationV1 addr;
|
||||
cryptonote::account_public_address cnaddr;
|
||||
switch (resolve_derive_type(subaddress_index.derive_type))
|
||||
{
|
||||
case AddressDeriveType::Carrot:
|
||||
make_carrot_subaddress_v1(keys.m_carrot_account_address.m_spend_public_key,
|
||||
keys.m_carrot_account_address.m_view_public_key,
|
||||
s_generate_address_dev,
|
||||
subaddress_index.index.major,
|
||||
subaddress_index.index.minor,
|
||||
addr);
|
||||
break;
|
||||
case AddressDeriveType::PreCarrot:
|
||||
cnaddr =
|
||||
keys.m_device->get_subaddress(keys, {subaddress_index.index.major, subaddress_index.index.minor});
|
||||
addr = CarrotDestinationV1{
|
||||
.address_spend_pubkey = cnaddr.m_spend_public_key,
|
||||
.address_view_pubkey = cnaddr.m_view_public_key,
|
||||
.is_subaddress = true,
|
||||
.payment_id = null_payment_id
|
||||
};
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("address derive type not recognized");
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
const std::unordered_map<crypto::public_key, cryptonote::subaddress_index> carrot_and_legacy_account::get_subaddress_map_cn() const
|
||||
{
|
||||
std::unordered_map<crypto::public_key, cryptonote::subaddress_index> res;
|
||||
for (const auto &p : subaddress_map)
|
||||
res.emplace(p.first, cryptonote::subaddress_index{p.second.index.major, p.second.index.minor});
|
||||
CHECK_AND_ASSERT_THROW_MES(!res.empty(),
|
||||
"carrot_and_legacy_account::get_subaddress_map: subaddress map does not contain subaddresses");
|
||||
return res;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
const std::unordered_map<crypto::public_key, subaddress_index_extended>& carrot_and_legacy_account::get_subaddress_map_ref() const {
|
||||
return subaddress_map;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
const std::unordered_map<crypto::public_key, return_output_info_t>&
|
||||
carrot_and_legacy_account::get_return_output_map_ref() const {
|
||||
return return_output_map;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
void carrot_and_legacy_account::opening_for_subaddress(const subaddress_index_extended &subaddress_index,
|
||||
crypto::secret_key &address_privkey_g_out,
|
||||
crypto::secret_key &address_privkey_t_out,
|
||||
crypto::public_key &address_spend_pubkey_out) const
|
||||
{
|
||||
const bool is_subaddress = subaddress_index.index.is_subaddress();
|
||||
const uint32_t major_index = subaddress_index.index.major;
|
||||
const uint32_t minor_index = subaddress_index.index.minor;
|
||||
|
||||
const cryptonote::account_keys &keys = get_keys();
|
||||
|
||||
crypto::secret_key address_index_generator;
|
||||
crypto::secret_key subaddress_scalar;
|
||||
crypto::secret_key subaddress_extension;
|
||||
|
||||
switch (resolve_derive_type(subaddress_index.derive_type))
|
||||
{
|
||||
case AddressDeriveType::Carrot:
|
||||
// s^j_gen = H_32[s_ga](j_major, j_minor)
|
||||
make_carrot_index_extension_generator(keys.s_generate_address, major_index, minor_index, address_index_generator);
|
||||
|
||||
if (is_subaddress)
|
||||
{
|
||||
// k^j_subscal = H_n(K_s, j_major, j_minor, s^j_gen)
|
||||
make_carrot_subaddress_scalar(keys.m_carrot_account_address.m_spend_public_key, address_index_generator, major_index, minor_index, subaddress_scalar);
|
||||
}
|
||||
else
|
||||
{
|
||||
// k^j_subscal = 1
|
||||
sc_1(to_bytes(subaddress_scalar));
|
||||
}
|
||||
|
||||
// k^g_a = k_gi * k^j_subscal
|
||||
sc_mul(to_bytes(address_privkey_g_out), to_bytes(keys.k_generate_image), to_bytes(subaddress_scalar));
|
||||
|
||||
// k^t_a = k_ps * k^j_subscal
|
||||
sc_mul(to_bytes(address_privkey_t_out), to_bytes(keys.k_prove_spend), to_bytes(subaddress_scalar));
|
||||
break;
|
||||
case AddressDeriveType::PreCarrot:
|
||||
// m = Hn(k_v || j_major || j_minor) if subaddress else 0
|
||||
subaddress_extension = is_subaddress
|
||||
? keys.get_device().get_subaddress_secret_key(keys.m_view_secret_key, {major_index, minor_index})
|
||||
: crypto::null_skey;
|
||||
|
||||
// k^g_a = k_s + m
|
||||
sc_add(to_bytes(address_privkey_g_out), to_bytes(keys.m_spend_secret_key), to_bytes(subaddress_extension));
|
||||
|
||||
// k^t_a = 0
|
||||
memset(address_privkey_t_out.data, 0, sizeof(address_privkey_t_out));
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("address derive type not recognized");
|
||||
}
|
||||
|
||||
// perform sanity check
|
||||
const CarrotDestinationV1 addr = subaddress(subaddress_index);
|
||||
rct::key recomputed_address_spend_pubkey;
|
||||
rct::addKeys2(recomputed_address_spend_pubkey,
|
||||
rct::sk2rct(address_privkey_g_out),
|
||||
rct::sk2rct(address_privkey_t_out),
|
||||
rct::pk2rct(crypto::get_T()));
|
||||
CHECK_AND_ASSERT_THROW_MES(rct::rct2pk(recomputed_address_spend_pubkey) == addr.address_spend_pubkey,
|
||||
"carrot and legacy account: opening for subaddress: failed sanity check");
|
||||
address_spend_pubkey_out = addr.address_spend_pubkey;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
bool carrot_and_legacy_account::try_searching_for_opening_for_subaddress(const crypto::public_key &address_spend_pubkey,
|
||||
crypto::secret_key &address_privkey_g_out,
|
||||
crypto::secret_key &address_privkey_t_out) const
|
||||
{
|
||||
const auto it = subaddress_map.find(address_spend_pubkey);
|
||||
if (it == subaddress_map.cend())
|
||||
return false;
|
||||
|
||||
crypto::public_key recomputed_address_spend_pubkey;
|
||||
opening_for_subaddress(it->second,
|
||||
address_privkey_g_out,
|
||||
address_privkey_t_out,
|
||||
recomputed_address_spend_pubkey);
|
||||
|
||||
return address_spend_pubkey == recomputed_address_spend_pubkey;
|
||||
}
|
||||
bool carrot_and_legacy_account::try_searching_for_opening_for_onetime_address(const crypto::public_key &address_spend_pubkey,
|
||||
const crypto::secret_key &sender_extension_g,
|
||||
const crypto::secret_key &sender_extension_t,
|
||||
crypto::secret_key &x_out,
|
||||
crypto::secret_key &y_out) const
|
||||
{
|
||||
// k^{j,g}_addr, k^{j,t}_addr
|
||||
crypto::secret_key address_privkey_g;
|
||||
crypto::secret_key address_privkey_t;
|
||||
if (!try_searching_for_opening_for_subaddress(address_spend_pubkey,
|
||||
address_privkey_g,
|
||||
address_privkey_t))
|
||||
return false;
|
||||
|
||||
// x = k^{j,g}_addr + k^g_o
|
||||
sc_add(to_bytes(x_out), to_bytes(address_privkey_g), to_bytes(sender_extension_g));
|
||||
|
||||
// y = k^{j,t}_addr + k^t_o
|
||||
sc_add(to_bytes(y_out), to_bytes(address_privkey_t), to_bytes(sender_extension_t));
|
||||
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
bool carrot_and_legacy_account::can_open_fcmp_onetime_address(const crypto::public_key &address_spend_pubkey,
|
||||
const crypto::secret_key &sender_extension_g,
|
||||
const crypto::secret_key &sender_extension_t,
|
||||
const crypto::public_key &onetime_address) const
|
||||
{
|
||||
crypto::secret_key x, y;
|
||||
if (!try_searching_for_opening_for_onetime_address(address_spend_pubkey,
|
||||
sender_extension_g,
|
||||
sender_extension_t,
|
||||
x,
|
||||
y))
|
||||
return false;
|
||||
|
||||
// O' = x G + y T
|
||||
rct::key recomputed_onetime_address;
|
||||
rct::addKeys2(recomputed_onetime_address,
|
||||
rct::sk2rct(x),
|
||||
rct::sk2rct(y),
|
||||
rct::pk2rct(crypto::get_T()));
|
||||
|
||||
// O' ?= O
|
||||
return 0 == memcmp(&recomputed_onetime_address, &onetime_address, sizeof(rct::key));
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
crypto::key_image carrot_and_legacy_account::derive_key_image(const crypto::public_key &address_spend_pubkey,
|
||||
const crypto::secret_key &sender_extension_g,
|
||||
const crypto::secret_key &sender_extension_t,
|
||||
const crypto::public_key &onetime_address) const
|
||||
{
|
||||
CHECK_AND_ASSERT_THROW_MES(can_open_fcmp_onetime_address(
|
||||
address_spend_pubkey,
|
||||
sender_extension_g,
|
||||
sender_extension_t,
|
||||
onetime_address),
|
||||
"carrot and legacy account: derive key image: cannot open onetime address");
|
||||
|
||||
crypto::secret_key x, y;
|
||||
try_searching_for_opening_for_onetime_address(address_spend_pubkey,
|
||||
sender_extension_g,
|
||||
sender_extension_t,
|
||||
x,
|
||||
y);
|
||||
|
||||
crypto::key_image L;
|
||||
crypto::generate_key_image(onetime_address, x, L);
|
||||
return L;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
crypto::key_image carrot_and_legacy_account::derive_key_image_view_only(const crypto::public_key &address_spend_pubkey,
|
||||
const crypto::secret_key &sender_extension_g,
|
||||
const crypto::secret_key &sender_extension_t,
|
||||
const crypto::public_key &onetime_address) const
|
||||
{
|
||||
const auto it = subaddress_map.find(address_spend_pubkey);
|
||||
CHECK_AND_ASSERT_THROW_MES(it != subaddress_map.cend(),
|
||||
"carrot and legacy account: derive key image view only: cannot find subaddress");
|
||||
|
||||
const bool is_subaddress = it->second.index.is_subaddress();
|
||||
const uint32_t major_index = it->second.index.major;
|
||||
const uint32_t minor_index = it->second.index.minor;
|
||||
|
||||
const cryptonote::account_keys &keys = get_keys();
|
||||
|
||||
crypto::secret_key address_index_generator;
|
||||
crypto::secret_key subaddress_scalar;
|
||||
crypto::secret_key subaddress_extension;
|
||||
crypto::secret_key address_privkey_g;
|
||||
crypto::secret_key x;
|
||||
|
||||
CHECK_AND_ASSERT_THROW_MES(it->second.derive_type == AddressDeriveType::Carrot,
|
||||
"carrot and legacy account: derive key image view only: not a Carrot address");
|
||||
|
||||
// s^j_gen = H_32[s_ga](j_major, j_minor)
|
||||
make_carrot_index_extension_generator(keys.s_generate_address, major_index, minor_index, address_index_generator);
|
||||
|
||||
if (is_subaddress)
|
||||
{
|
||||
// k^j_subscal = H_n(K_s, j_major, j_minor, s^j_gen)
|
||||
make_carrot_subaddress_scalar(keys.m_carrot_account_address.m_spend_public_key, address_index_generator, major_index, minor_index, subaddress_scalar);
|
||||
}
|
||||
else
|
||||
{
|
||||
// k^j_subscal = 1
|
||||
sc_1(to_bytes(subaddress_scalar));
|
||||
}
|
||||
|
||||
// k^g_a = k_gi * k^j_subscal
|
||||
sc_mul(to_bytes(address_privkey_g), to_bytes(keys.k_generate_image), to_bytes(subaddress_scalar));
|
||||
|
||||
// x = k^{j,g}_addr + k^g_o
|
||||
sc_add(to_bytes(x), to_bytes(address_privkey_g), to_bytes(sender_extension_g));
|
||||
|
||||
crypto::key_image L;
|
||||
crypto::generate_key_image(onetime_address, x, L);
|
||||
return L;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
void carrot_and_legacy_account::generate_subaddress_map(const std::pair<size_t, size_t>& lookahead_size)
|
||||
{
|
||||
const std::vector<AddressDeriveType> derive_types{AddressDeriveType::Carrot, AddressDeriveType::PreCarrot};
|
||||
|
||||
for (uint32_t major_index = 0; major_index <= lookahead_size.first; ++major_index)
|
||||
{
|
||||
for (uint32_t minor_index = 0; minor_index <= lookahead_size.second; ++minor_index)
|
||||
{
|
||||
for (const AddressDeriveType derive_type : derive_types)
|
||||
{
|
||||
const subaddress_index_extended subaddr_index{{major_index, minor_index}, derive_type, false};
|
||||
const CarrotDestinationV1 addr = subaddress(subaddr_index);
|
||||
subaddress_map.insert({addr.address_spend_pubkey, subaddr_index});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
crypto::secret_key carrot_and_legacy_account::generate(
|
||||
const crypto::secret_key& recovery_key,
|
||||
bool recover,
|
||||
bool two_random,
|
||||
const AddressDeriveType default_derive_type)
|
||||
{
|
||||
// generate the legacy keys
|
||||
crypto::secret_key retval = cryptonote::account_base::generate(recovery_key, recover, two_random);
|
||||
|
||||
// generate carrot keys
|
||||
set_carrot_keys(default_derive_type);
|
||||
|
||||
return retval;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
void carrot_and_legacy_account::set_keys(const cryptonote::account_keys& keys, bool copy_spend_secret_keys)
|
||||
{
|
||||
// CN keys
|
||||
m_keys.m_account_address = keys.m_account_address;
|
||||
if (copy_spend_secret_keys) m_keys.m_spend_secret_key = keys.m_spend_secret_key;
|
||||
m_keys.m_view_secret_key = keys.m_view_secret_key;
|
||||
if (copy_spend_secret_keys) m_keys.m_multisig_keys = keys.m_multisig_keys;
|
||||
m_keys.m_device = keys.m_device;
|
||||
m_keys.m_encryption_iv = keys.m_encryption_iv;
|
||||
|
||||
// Carrot keys
|
||||
if (copy_spend_secret_keys) m_keys.s_master = keys.s_master;
|
||||
if (copy_spend_secret_keys) m_keys.k_prove_spend = keys.k_prove_spend;
|
||||
m_keys.s_view_balance = keys.s_view_balance;
|
||||
m_keys.k_view_incoming = keys.k_view_incoming;
|
||||
m_keys.k_generate_image = keys.k_generate_image;
|
||||
m_keys.s_generate_address = keys.s_generate_address;
|
||||
m_keys.m_carrot_account_address = keys.m_carrot_account_address;
|
||||
m_keys.m_carrot_main_address = keys.m_carrot_main_address;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
void carrot_and_legacy_account::create_from_svb_key(const cryptonote::account_public_address& address, const crypto::secret_key& svb_key)
|
||||
{
|
||||
// top level keys
|
||||
m_keys.s_master = crypto::null_skey;
|
||||
make_carrot_provespend_key(m_keys.s_master, m_keys.k_prove_spend);
|
||||
m_keys.s_view_balance = svb_key;
|
||||
|
||||
// view balance keys
|
||||
make_carrot_viewincoming_key(m_keys.s_view_balance, m_keys.k_view_incoming);
|
||||
make_carrot_generateimage_key(m_keys.s_view_balance, m_keys.k_generate_image);
|
||||
make_carrot_generateaddress_secret(m_keys.s_view_balance, m_keys.s_generate_address);
|
||||
|
||||
// carrot account address - use the provided address spend pubkey
|
||||
m_keys.m_carrot_account_address = address;
|
||||
k_view_incoming_dev.view_key_scalar_mult_ed25519(m_keys.m_carrot_account_address.m_spend_public_key,
|
||||
m_keys.m_carrot_account_address.m_view_public_key
|
||||
);
|
||||
|
||||
// carrot main wallet address
|
||||
m_keys.m_carrot_main_address = address;
|
||||
k_view_incoming_dev.view_key_scalar_mult_ed25519(crypto::get_G(),
|
||||
m_keys.m_carrot_main_address.m_view_public_key
|
||||
);
|
||||
|
||||
// Store fields for Carrot
|
||||
m_keys.m_spend_secret_key = crypto::null_skey;
|
||||
m_keys.m_view_secret_key = crypto::null_skey;
|
||||
m_keys.m_account_address = {crypto::null_pkey, crypto::null_pkey, false};
|
||||
|
||||
// Update ALL addresses to be Carrot-only
|
||||
m_keys.m_carrot_account_address.m_is_carrot = true;
|
||||
m_keys.m_carrot_main_address.m_is_carrot = true;
|
||||
|
||||
// Set the default derive type for addresses
|
||||
this->default_derive_type = AddressDeriveType::Carrot;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
void carrot_and_legacy_account::set_carrot_keys(const AddressDeriveType default_derive_type)
|
||||
{
|
||||
// top level keys
|
||||
m_keys.s_master = m_keys.m_spend_secret_key;
|
||||
make_carrot_provespend_key(m_keys.s_master, m_keys.k_prove_spend);
|
||||
make_carrot_viewbalance_secret(m_keys.s_master, m_keys.s_view_balance);
|
||||
|
||||
// view balance keys
|
||||
make_carrot_viewincoming_key(m_keys.s_view_balance, m_keys.k_view_incoming);
|
||||
make_carrot_generateimage_key(m_keys.s_view_balance, m_keys.k_generate_image);
|
||||
make_carrot_generateaddress_secret(m_keys.s_view_balance, m_keys.s_generate_address);
|
||||
|
||||
// carrot account address
|
||||
make_carrot_spend_pubkey(m_keys.k_generate_image, m_keys.k_prove_spend, m_keys.m_carrot_account_address.m_spend_public_key);
|
||||
k_view_incoming_dev.view_key_scalar_mult_ed25519(
|
||||
m_keys.m_carrot_account_address.m_spend_public_key,
|
||||
m_keys.m_carrot_account_address.m_view_public_key
|
||||
);
|
||||
m_keys.m_carrot_account_address.m_is_carrot = true;
|
||||
|
||||
// carrot main wallet address
|
||||
m_keys.m_carrot_main_address.m_spend_public_key = m_keys.m_carrot_account_address.m_spend_public_key;
|
||||
k_view_incoming_dev.view_key_scalar_mult_ed25519(
|
||||
crypto::get_G(),
|
||||
m_keys.m_carrot_main_address.m_view_public_key
|
||||
);
|
||||
m_keys.m_carrot_main_address.m_is_carrot = true;
|
||||
|
||||
this->default_derive_type = default_derive_type;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
void carrot_and_legacy_account::insert_subaddresses(const std::unordered_map<crypto::public_key, subaddress_index_extended>& subaddress_map_cn)
|
||||
{
|
||||
for (const auto &p : subaddress_map_cn) {
|
||||
subaddress_map.insert({p.first, {{p.second.index.major, p.second.index.minor}, p.second.derive_type, p.second.is_return_spend_key}});
|
||||
if (p.second.derive_type == AddressDeriveType::PreCarrot) {
|
||||
// Create a matching Carrot address
|
||||
const subaddress_index_extended subaddr_index{{p.second.index.major, p.second.index.minor}, AddressDeriveType::Carrot, p.second.is_return_spend_key};
|
||||
const CarrotDestinationV1 addr = subaddress(subaddr_index);
|
||||
subaddress_map.insert({addr.address_spend_pubkey, subaddr_index});
|
||||
}
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
void carrot_and_legacy_account::insert_return_output_info(const std::unordered_map<crypto::public_key, return_output_info_t>& roi_map)
|
||||
{
|
||||
for (const auto &p : roi_map)
|
||||
return_output_map.insert({p.first, p.second});
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
AddressDeriveType carrot_and_legacy_account::resolve_derive_type(const AddressDeriveType derive_type) const
|
||||
{
|
||||
return derive_type == AddressDeriveType::Auto ? default_derive_type : derive_type;
|
||||
}
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
@@ -0,0 +1,242 @@
|
||||
// Copyright (c) 2025, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "account_secrets.h"
|
||||
#include "address_utils.h"
|
||||
#include "destination.h"
|
||||
#include "device_ram_borrowed.h"
|
||||
#include "enote_utils.h"
|
||||
#include "carrot_impl/subaddress_index.h"
|
||||
#include "cryptonote_basic/account.h"
|
||||
#include "cryptonote_basic/subaddress_index.h"
|
||||
|
||||
//----------------------------------------------------------------------------------------------------------------------
|
||||
static constexpr std::uint32_t MAX_SUBADDRESS_MAJOR_INDEX = 5;
|
||||
static constexpr std::uint32_t MAX_SUBADDRESS_MINOR_INDEX = 20;
|
||||
|
||||
namespace carrot
|
||||
{
|
||||
|
||||
struct return_output_info_t {
|
||||
input_context_t input_context;
|
||||
crypto::public_key K_o; // output onetime address
|
||||
crypto::public_key K_change; // change output onetime address
|
||||
crypto::public_key K_spend_pubkey; // change output spend pubkey
|
||||
crypto::key_image key_image;
|
||||
crypto::secret_key sum_g;
|
||||
crypto::secret_key sender_extension_t;
|
||||
|
||||
return_output_info_t() {
|
||||
// Default constructor for serialization
|
||||
input_context = input_context_t();
|
||||
K_o = crypto::public_key();
|
||||
K_change = crypto::public_key();
|
||||
K_spend_pubkey = crypto::public_key();
|
||||
key_image = crypto::key_image();
|
||||
sum_g = crypto::secret_key();
|
||||
sender_extension_t = crypto::secret_key();
|
||||
}
|
||||
|
||||
return_output_info_t(
|
||||
const input_context_t &input_context,
|
||||
const crypto::public_key &K_o,
|
||||
const crypto::public_key &K_change,
|
||||
const crypto::public_key &K_spend_pubkey,
|
||||
const crypto::key_image &key_image,
|
||||
const crypto::secret_key &sum_g,
|
||||
const crypto::secret_key &sender_extension_t):
|
||||
input_context(input_context),
|
||||
K_o(K_o),
|
||||
K_change(K_change),
|
||||
K_spend_pubkey(K_spend_pubkey),
|
||||
key_image(key_image),
|
||||
sum_g(sum_g),
|
||||
sender_extension_t(sender_extension_t) {}
|
||||
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
FIELD(input_context)
|
||||
FIELD(K_o)
|
||||
FIELD(K_change)
|
||||
FIELD(K_spend_pubkey)
|
||||
FIELD(key_image)
|
||||
FIELD(sum_g)
|
||||
FIELD(sender_extension_t)
|
||||
END_SERIALIZE()
|
||||
};
|
||||
|
||||
// Old return_output_info_t format (for deserializing version 2 wallet caches)
|
||||
struct return_output_info_retired_t {
|
||||
input_context_t input_context;
|
||||
crypto::public_key K_o;
|
||||
crypto::public_key K_change;
|
||||
crypto::key_image key_image;
|
||||
crypto::secret_key x;
|
||||
crypto::secret_key y;
|
||||
|
||||
return_output_info_retired_t() {
|
||||
input_context = input_context_t();
|
||||
K_o = crypto::public_key();
|
||||
K_change = crypto::public_key();
|
||||
key_image = crypto::key_image();
|
||||
x = crypto::secret_key();
|
||||
y = crypto::secret_key();
|
||||
}
|
||||
|
||||
BEGIN_SERIALIZE_OBJECT()
|
||||
FIELD(input_context)
|
||||
FIELD(K_o)
|
||||
FIELD(K_change)
|
||||
FIELD(key_image)
|
||||
FIELD(x)
|
||||
FIELD(y)
|
||||
END_SERIALIZE()
|
||||
};
|
||||
|
||||
|
||||
class carrot_and_legacy_account : public cryptonote::account_base
|
||||
{
|
||||
public:
|
||||
view_incoming_key_ram_borrowed_device k_view_incoming_dev;
|
||||
view_balance_secret_ram_borrowed_device s_view_balance_dev;
|
||||
generate_address_secret_ram_borrowed_device s_generate_address_dev;
|
||||
|
||||
AddressDeriveType default_derive_type;
|
||||
|
||||
carrot_and_legacy_account(): k_view_incoming_dev(get_keys().k_view_incoming),
|
||||
s_view_balance_dev(get_keys().s_view_balance),
|
||||
s_generate_address_dev(get_keys().s_generate_address)
|
||||
{}
|
||||
|
||||
void set_keys(const cryptonote::account_keys& keys, bool copy_spend_secret_keys);
|
||||
|
||||
carrot_and_legacy_account(const carrot_and_legacy_account &k) = delete;
|
||||
carrot_and_legacy_account(carrot_and_legacy_account&&) = delete;
|
||||
|
||||
carrot_and_legacy_account& operator=(const carrot_and_legacy_account&) = delete;
|
||||
carrot_and_legacy_account& operator=(carrot_and_legacy_account&&) = delete;
|
||||
|
||||
CarrotDestinationV1 cryptonote_address(const payment_id_t payment_id = null_payment_id,
|
||||
const AddressDeriveType derive_type = AddressDeriveType::Auto) const;
|
||||
|
||||
CarrotDestinationV1 subaddress(const subaddress_index_extended &subaddress_index) const;
|
||||
|
||||
const std::unordered_map<crypto::public_key, cryptonote::subaddress_index> get_subaddress_map_cn() const;
|
||||
const std::unordered_map<crypto::public_key, subaddress_index_extended>& get_subaddress_map_ref() const;
|
||||
const std::unordered_map<crypto::public_key, return_output_info_t>& get_return_output_map_ref() const;
|
||||
|
||||
// brief: opening_for_subaddress - return (k^g_a, k^t_a) for j s.t. K^j_s = (k^g_a * G + k^t_a * T)
|
||||
void opening_for_subaddress(const subaddress_index_extended &subaddress_index,
|
||||
crypto::secret_key &address_privkey_g_out,
|
||||
crypto::secret_key &address_privkey_t_out,
|
||||
crypto::public_key &address_spend_pubkey_out) const;
|
||||
|
||||
bool try_searching_for_opening_for_subaddress(const crypto::public_key &address_spend_pubkey,
|
||||
crypto::secret_key &address_privkey_g_out,
|
||||
crypto::secret_key &address_privkey_t_out) const;
|
||||
|
||||
bool try_searching_for_opening_for_onetime_address(const crypto::public_key &address_spend_pubkey,
|
||||
const crypto::secret_key &sender_extension_g,
|
||||
const crypto::secret_key &sender_extension_t,
|
||||
crypto::secret_key &x_out,
|
||||
crypto::secret_key &y_out) const;
|
||||
|
||||
bool can_open_fcmp_onetime_address(const crypto::public_key &address_spend_pubkey,
|
||||
const crypto::secret_key &sender_extension_g,
|
||||
const crypto::secret_key &sender_extension_t,
|
||||
const crypto::public_key &onetime_address) const;
|
||||
|
||||
crypto::key_image derive_key_image(const crypto::public_key &address_spend_pubkey,
|
||||
const crypto::secret_key &sender_extension_g,
|
||||
const crypto::secret_key &sender_extension_t,
|
||||
const crypto::public_key &onetime_address) const;
|
||||
|
||||
crypto::key_image derive_key_image_view_only(const crypto::public_key &address_spend_pubkey,
|
||||
const crypto::secret_key &sender_extension_g,
|
||||
const crypto::secret_key &sender_extension_t,
|
||||
const crypto::public_key &onetime_address) const;
|
||||
|
||||
void generate_subaddress_map(const std::pair<size_t, size_t>& lookahead_size);
|
||||
|
||||
crypto::secret_key generate(
|
||||
const crypto::secret_key& recovery_key = crypto::secret_key(),
|
||||
bool recover = false,
|
||||
bool two_random = false,
|
||||
const AddressDeriveType default_derive_type = AddressDeriveType::Carrot
|
||||
);
|
||||
|
||||
void create_from_svb_key(const cryptonote::account_public_address& address, const crypto::secret_key& svb_key);
|
||||
void set_carrot_keys(const AddressDeriveType default_derive_type = AddressDeriveType::Carrot);
|
||||
void insert_subaddresses(const std::unordered_map<crypto::public_key, subaddress_index_extended>& subaddress_map);
|
||||
void insert_return_output_info(
|
||||
const std::unordered_map<crypto::public_key, return_output_info_t>& input_context_map
|
||||
);
|
||||
|
||||
AddressDeriveType resolve_derive_type(const AddressDeriveType derive_type) const;
|
||||
|
||||
private:
|
||||
std::unordered_map<crypto::public_key, subaddress_index_extended> subaddress_map;
|
||||
// Kr -> return_output_info
|
||||
std::unordered_map<crypto::public_key, return_output_info_t> return_output_map;
|
||||
};
|
||||
}
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace serialization
|
||||
{
|
||||
template <class Archive>
|
||||
inline typename std::enable_if<!Archive::is_loading::value, void>::type initialize_transfer_details(Archive &a, carrot::return_output_info_t &x, const boost::serialization::version_type ver)
|
||||
{
|
||||
}
|
||||
template <class Archive>
|
||||
inline typename std::enable_if<Archive::is_loading::value, void>::type initialize_transfer_details(Archive &a, carrot::return_output_info_t &x, const boost::serialization::version_type ver)
|
||||
{
|
||||
x.input_context = carrot::input_context_t();
|
||||
x.K_o = crypto::public_key();
|
||||
x.K_change = crypto::public_key();
|
||||
x.K_spend_pubkey = crypto::public_key();
|
||||
x.key_image = crypto::key_image();
|
||||
x.sum_g = crypto::secret_key();
|
||||
x.sender_extension_t = crypto::secret_key();
|
||||
}
|
||||
|
||||
template <class Archive>
|
||||
inline void serialize(Archive &a, carrot::return_output_info_t &x, const boost::serialization::version_type ver)
|
||||
{
|
||||
a & x.input_context;
|
||||
a & x.K_o;
|
||||
a & x.K_change;
|
||||
a & x.K_spend_pubkey;
|
||||
a & x.key_image;
|
||||
a & x.sum_g;
|
||||
a & x.sender_extension_t;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
// Copyright (c) 2024, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
//paired header
|
||||
#include "account_secrets.h"
|
||||
|
||||
//local headers
|
||||
#include "config.h"
|
||||
#include "crypto/generators.h"
|
||||
#include "hash_functions.h"
|
||||
#include "ringct/rctOps.h"
|
||||
#include "transcript_fixed.h"
|
||||
|
||||
//third party headers
|
||||
|
||||
//standard headers
|
||||
|
||||
#undef MONERO_DEFAULT_LOG_CATEGORY
|
||||
#define MONERO_DEFAULT_LOG_CATEGORY "carrot"
|
||||
|
||||
namespace carrot
|
||||
{
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void make_carrot_provespend_key(const crypto::secret_key &s_master,
|
||||
crypto::secret_key &k_prove_spend_out)
|
||||
{
|
||||
// k_ps = H_n(s_m)
|
||||
const auto transcript = sp::make_fixed_transcript<CARROT_DOMAIN_SEP_PROVE_SPEND_KEY>();
|
||||
derive_scalar(transcript.data(), transcript.size(), &s_master, to_bytes(k_prove_spend_out));
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void make_carrot_viewbalance_secret(const crypto::secret_key &s_master,
|
||||
crypto::secret_key &s_view_balance_out)
|
||||
{
|
||||
// s_vb = H_32(s_m)
|
||||
const auto transcript = sp::make_fixed_transcript<CARROT_DOMAIN_SEP_VIEW_BALANCE_SECRET>();
|
||||
derive_bytes_32(transcript.data(), transcript.size(), &s_master, to_bytes(s_view_balance_out));
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void make_carrot_generateimage_key(const crypto::secret_key &s_view_balance,
|
||||
crypto::secret_key &k_generate_image_out)
|
||||
{
|
||||
// k_gi = H_n(s_vb)
|
||||
const auto transcript = sp::make_fixed_transcript<CARROT_DOMAIN_SEP_GENERATE_IMAGE_KEY>();
|
||||
derive_scalar(transcript.data(), transcript.size(), &s_view_balance, to_bytes(k_generate_image_out));
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void make_carrot_viewincoming_key(const crypto::secret_key &s_view_balance,
|
||||
crypto::secret_key &k_view_out)
|
||||
{
|
||||
// k_v = H_n(s_vb)
|
||||
const auto transcript = sp::make_fixed_transcript<CARROT_DOMAIN_SEP_INCOMING_VIEW_KEY>();
|
||||
derive_scalar(transcript.data(), transcript.size(), &s_view_balance, to_bytes(k_view_out));
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void make_carrot_generateaddress_secret(const crypto::secret_key &s_view_balance,
|
||||
crypto::secret_key &s_generate_address_out)
|
||||
{
|
||||
// s_ga = H_32(s_vb)
|
||||
const auto transcript = sp::make_fixed_transcript<CARROT_DOMAIN_SEP_GENERATE_ADDRESS_SECRET>();
|
||||
derive_bytes_32(transcript.data(), transcript.size(), &s_view_balance, to_bytes(s_generate_address_out));
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void make_carrot_spend_pubkey(const crypto::secret_key &k_generate_image,
|
||||
const crypto::secret_key &k_prove_spend,
|
||||
crypto::public_key &spend_pubkey_out)
|
||||
{
|
||||
// k_ps T
|
||||
rct::key tmp;
|
||||
rct::scalarmultKey(tmp, rct::pk2rct(crypto::get_T()), rct::sk2rct(k_prove_spend));
|
||||
|
||||
// K_s = k_gi G + k_ps T
|
||||
rct::addKeys1(tmp, rct::sk2rct(k_generate_image), tmp);
|
||||
spend_pubkey_out = rct::rct2pk(tmp);
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
} //namespace carrot
|
||||
@@ -0,0 +1,103 @@
|
||||
// Copyright (c) 2024, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
////
|
||||
// Core implementation details for making Carrot privkeys, secrets, and pubkeys.
|
||||
// - Carrot is a specification for FCMP-RingCT compatible addressing
|
||||
//
|
||||
// references:
|
||||
// * https://github.com/jeffro256/carrot/blob/master/carrot.md
|
||||
///
|
||||
|
||||
#pragma once
|
||||
|
||||
//local headers
|
||||
#include "crypto/crypto.h"
|
||||
|
||||
//third party headers
|
||||
|
||||
//standard headers
|
||||
|
||||
//forward declarations
|
||||
|
||||
|
||||
namespace carrot
|
||||
{
|
||||
|
||||
/**
|
||||
* brief: make_carrot_provespend_key - prove-spend key, for signing input proofs to spend enotes
|
||||
* k_ps = H_n(s_m)
|
||||
* param: s_master - s_m
|
||||
* outparam: k_prove_spend_out - k_ps
|
||||
*/
|
||||
void make_carrot_provespend_key(const crypto::secret_key &s_master,
|
||||
crypto::secret_key &k_prove_spend_out);
|
||||
/**
|
||||
* brief: make_carrot_viewbalance_secret - view-balance secret, for viewing all balance information
|
||||
* s_vb = H_n(s_m)
|
||||
* param: s_master - s_m
|
||||
* outparam: s_view_balance_out - s_vb
|
||||
*/
|
||||
void make_carrot_viewbalance_secret(const crypto::secret_key &s_master,
|
||||
crypto::secret_key &s_view_balance_out);
|
||||
/**
|
||||
* brief: make_carrot_generateimage_key - generate-image key, for identifying enote spends
|
||||
* k_gi = H_n(s_vb)
|
||||
* param: s_view_balance - s_vb
|
||||
* outparam: k_generate_image_out - k_gi
|
||||
*/
|
||||
void make_carrot_generateimage_key(const crypto::secret_key &s_view_balance,
|
||||
crypto::secret_key &k_generate_image_out);
|
||||
/**
|
||||
* brief: make_carrot_viewincoming_key - view-incoming key, for identifying received external enotes
|
||||
* k_v = H_n(s_vb)
|
||||
* param: s_view_balance - s_vb
|
||||
* outparam: k_view_out - k_v
|
||||
*/
|
||||
void make_carrot_viewincoming_key(const crypto::secret_key &s_view_balance,
|
||||
crypto::secret_key &k_view_out);
|
||||
/**
|
||||
* brief: make_carrot_generateaddress_secret - generate-address secret, for generating addresses
|
||||
* s_ga = H_32(s_vb)
|
||||
* param: s_view_balance - s_vb
|
||||
* outparam: s_generate_address_out - s_ga
|
||||
*/
|
||||
void make_carrot_generateaddress_secret(const crypto::secret_key &s_view_balance,
|
||||
crypto::secret_key &s_generate_address_out);
|
||||
/**
|
||||
* brief: make_carrot_spend_pubkey - base public spendkey for rerandomizable RingCT
|
||||
* K_s = k_gi G + k_ps T
|
||||
* param: k_generate_image - k_gi
|
||||
* param: k_prove_spend - k_ps
|
||||
* outparam: spend_pubkey_out - K_s
|
||||
*/
|
||||
void make_carrot_spend_pubkey(const crypto::secret_key &k_generate_image,
|
||||
const crypto::secret_key &k_prove_spend,
|
||||
crypto::public_key &spend_pubkey_out);
|
||||
|
||||
} //namespace carrot
|
||||
@@ -0,0 +1,85 @@
|
||||
// Copyright (c) 2024, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
//paired header
|
||||
#include "address_utils.h"
|
||||
|
||||
//local headers
|
||||
#include "config.h"
|
||||
#include "hash_functions.h"
|
||||
#include "ringct/rctOps.h"
|
||||
#include "transcript_fixed.h"
|
||||
|
||||
//third party headers
|
||||
|
||||
//standard headers
|
||||
|
||||
#undef MONERO_DEFAULT_LOG_CATEGORY
|
||||
#define MONERO_DEFAULT_LOG_CATEGORY "carrot"
|
||||
|
||||
namespace carrot
|
||||
{
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void make_carrot_index_extension_generator(const crypto::secret_key &s_generate_address,
|
||||
const std::uint32_t j_major,
|
||||
const std::uint32_t j_minor,
|
||||
crypto::secret_key &address_generator_out)
|
||||
{
|
||||
// s^j_gen = H_32[s_ga](j_major, j_minor)
|
||||
const auto transcript = sp::make_fixed_transcript<CARROT_DOMAIN_SEP_ADDRESS_INDEX_GEN>(j_major, j_minor);
|
||||
derive_bytes_32(transcript.data(), transcript.size(), &s_generate_address, &address_generator_out);
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void make_carrot_subaddress_scalar(const crypto::public_key &account_spend_pubkey,
|
||||
const crypto::secret_key &s_address_generator,
|
||||
const std::uint32_t j_major,
|
||||
const std::uint32_t j_minor,
|
||||
crypto::secret_key &subaddress_scalar_out)
|
||||
{
|
||||
// k^j_subscal = H_n(K_s, j_major, j_minor, s^j_gen)
|
||||
const auto transcript = sp::make_fixed_transcript<CARROT_DOMAIN_SEP_SUBADDRESS_SCALAR>(
|
||||
account_spend_pubkey, j_major, j_minor);
|
||||
derive_scalar(transcript.data(), transcript.size(), &s_address_generator, subaddress_scalar_out.data);
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void make_carrot_address_spend_pubkey(const crypto::public_key &account_spend_pubkey,
|
||||
const crypto::secret_key &s_generate_address,
|
||||
const std::uint32_t j_major,
|
||||
const std::uint32_t j_minor,
|
||||
crypto::public_key &address_spend_pubkey_out)
|
||||
{
|
||||
// k^j_subscal = H_n(K_s, j_major, j_minor, s^j_gen)
|
||||
crypto::secret_key subaddress_scalar;
|
||||
make_carrot_subaddress_scalar(account_spend_pubkey, s_generate_address, j_major, j_minor, subaddress_scalar);
|
||||
|
||||
// K^j_s = k^j_subscal * K_s
|
||||
address_spend_pubkey_out = rct::rct2pk(rct::scalarmultKey(
|
||||
rct::pk2rct(account_spend_pubkey), rct::sk2rct(subaddress_scalar)));
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
} //namespace carrot
|
||||
@@ -0,0 +1,95 @@
|
||||
// Copyright (c) 2024, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Utilities for building carrot addresses.
|
||||
|
||||
#pragma once
|
||||
|
||||
//local headers
|
||||
#include "crypto/crypto.h"
|
||||
|
||||
//third party headers
|
||||
|
||||
//standard headers
|
||||
|
||||
//forward declarations
|
||||
|
||||
|
||||
namespace carrot
|
||||
{
|
||||
|
||||
/**
|
||||
* brief: is_main_address_index - determine whether j=(j_major, j_minor) represents the main address
|
||||
*/
|
||||
static constexpr bool is_main_address_index(const std::uint32_t j_major, const std::uint32_t j_minor)
|
||||
{
|
||||
return !(j_major || j_minor);
|
||||
}
|
||||
|
||||
/**
|
||||
* brief: make_carrot_index_extension_generator - s^j_gen
|
||||
* s^j_gen = H_32[s_ga](j_major, j_minor)
|
||||
* param: s_generate_address - s_ga
|
||||
* param: j_major -
|
||||
* param: j_minor -
|
||||
* outparam: address_generator_out - s^j_gen
|
||||
*/
|
||||
void make_carrot_index_extension_generator(const crypto::secret_key &s_generate_address,
|
||||
const std::uint32_t j_major,
|
||||
const std::uint32_t j_minor,
|
||||
crypto::secret_key &address_generator_out);
|
||||
/**
|
||||
* brief: make_carrot_address_privkey - d^j_a
|
||||
* k^j_subscal = H_n(K_s, j_major, j_minor, s^j_gen)
|
||||
* param: account_spend_pubkey - K_s = k_vb X + k_m U
|
||||
* param: s_address_generator - s^j_gen
|
||||
* param: j_major -
|
||||
* param: j_minor -
|
||||
* outparam: subaddress_scalar_out - k^j_subscal
|
||||
*/
|
||||
void make_carrot_subaddress_scalar(const crypto::public_key &account_spend_pubkey,
|
||||
const crypto::secret_key &s_address_generator,
|
||||
const std::uint32_t j_major,
|
||||
const std::uint32_t j_minor,
|
||||
crypto::secret_key &subaddress_scalar_out);
|
||||
/**
|
||||
* brief: make_carrot_address_spend_pubkey - K^j_s
|
||||
* K^j_s = k^j_subscal * K_s
|
||||
* param: account_spend_pubkey - K_s = k_gi G + k_ps U
|
||||
* param: s_generate_address - s_ga
|
||||
* param: j_major -
|
||||
* param: j_minor -
|
||||
* outparam: address_spend_pubkey_out - K^j_s
|
||||
*/
|
||||
void make_carrot_address_spend_pubkey(const crypto::public_key &account_spend_pubkey,
|
||||
const crypto::secret_key &s_generate_address,
|
||||
const std::uint32_t j_major,
|
||||
const std::uint32_t j_minor,
|
||||
crypto::public_key &address_spend_pubkey_out);
|
||||
|
||||
} //namespace carrot
|
||||
@@ -0,0 +1,75 @@
|
||||
// Copyright (c) 2024, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Utilities for scanning carrot enotes
|
||||
|
||||
//paired header
|
||||
#include "carrot_enote_types.h"
|
||||
|
||||
//local headers
|
||||
|
||||
//third party headers
|
||||
|
||||
//standard headers
|
||||
|
||||
/*
|
||||
onetime address
|
||||
// - amount commitment
|
||||
// - encrypted amount
|
||||
// - encrypted janus anchor
|
||||
// - view tag
|
||||
// - ephemeral pubkey
|
||||
// - tx first key image*/
|
||||
|
||||
namespace carrot
|
||||
{
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
bool operator==(const CarrotEnoteV1 &a, const CarrotEnoteV1 &b)
|
||||
{
|
||||
return a.onetime_address == b.onetime_address &&
|
||||
a.amount_commitment == b.amount_commitment &&
|
||||
a.amount_enc == b.amount_enc &&
|
||||
a.anchor_enc == b.anchor_enc &&
|
||||
a.view_tag == b.view_tag &&
|
||||
a.tx_first_key_image == b.tx_first_key_image &&
|
||||
a.return_enc == b.return_enc &&
|
||||
a.asset_type == b.asset_type &&
|
||||
memcmp(a.enote_ephemeral_pubkey.data, b.enote_ephemeral_pubkey.data, sizeof(mx25519_pubkey)) == 0;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
bool operator==(const CarrotCoinbaseEnoteV1 &a, const CarrotCoinbaseEnoteV1 &b)
|
||||
{
|
||||
return a.onetime_address == b.onetime_address &&
|
||||
a.amount == b.amount &&
|
||||
a.anchor_enc == b.anchor_enc &&
|
||||
a.view_tag == b.view_tag &&
|
||||
a.block_index == b.block_index &&
|
||||
memcmp(a.enote_ephemeral_pubkey.data, b.enote_ephemeral_pubkey.data, sizeof(mx25519_pubkey)) == 0;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
} //namespace carrot
|
||||
@@ -0,0 +1,117 @@
|
||||
// Copyright (c) 2024, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Seraphis core types.
|
||||
|
||||
#pragma once
|
||||
|
||||
//local headers
|
||||
#include "core_types.h"
|
||||
#include "mx25519.h"
|
||||
#include "ringct/rctTypes.h"
|
||||
|
||||
//third party headers
|
||||
|
||||
//standard headers
|
||||
|
||||
//forward declarations
|
||||
|
||||
|
||||
namespace carrot
|
||||
{
|
||||
|
||||
////
|
||||
// CarrotEnoteV1
|
||||
// - onetime address
|
||||
// - amount commitment
|
||||
// - encrypted amount
|
||||
// - encrypted janus anchor
|
||||
// - view tag
|
||||
// - ephemeral pubkey
|
||||
// - tx first key image
|
||||
///
|
||||
struct CarrotEnoteV1 final
|
||||
{
|
||||
/// K_o
|
||||
crypto::public_key onetime_address;
|
||||
/// C_a
|
||||
rct::key amount_commitment;
|
||||
/// asset type
|
||||
std::string asset_type;
|
||||
/// a_enc
|
||||
encrypted_amount_t amount_enc;
|
||||
/// anchor_enc
|
||||
encrypted_janus_anchor_t anchor_enc;
|
||||
/// return_enc
|
||||
encrypted_return_pubkey_t return_enc;
|
||||
/// view_tag
|
||||
view_tag_t view_tag;
|
||||
/// D_e
|
||||
mx25519_pubkey enote_ephemeral_pubkey;
|
||||
/// L_0
|
||||
crypto::key_image tx_first_key_image;
|
||||
// transaction output keys
|
||||
std::vector<crypto::public_key> tx_output_keys;
|
||||
};
|
||||
|
||||
/// equality operators
|
||||
bool operator==(const CarrotEnoteV1 &a, const CarrotEnoteV1 &b);
|
||||
static inline bool operator!=(const CarrotEnoteV1 &a, const CarrotEnoteV1 &b) { return !(a == b); }
|
||||
|
||||
////
|
||||
// CarrotCoinbaseEnoteV1
|
||||
// - onetime address
|
||||
// - cleartext amount
|
||||
// - encrypted janus anchor
|
||||
// - view tag
|
||||
// - ephemeral pubkey
|
||||
// - block index
|
||||
///
|
||||
struct CarrotCoinbaseEnoteV1 final
|
||||
{
|
||||
/// K_o
|
||||
crypto::public_key onetime_address;
|
||||
/// a
|
||||
rct::xmr_amount amount;
|
||||
/// asset type
|
||||
std::string asset_type;
|
||||
/// anchor_enc
|
||||
encrypted_janus_anchor_t anchor_enc;
|
||||
/// view_tag
|
||||
view_tag_t view_tag;
|
||||
/// D_e
|
||||
mx25519_pubkey enote_ephemeral_pubkey;
|
||||
/// block_index
|
||||
std::uint64_t block_index;
|
||||
};
|
||||
|
||||
/// equality operators
|
||||
bool operator==(const CarrotCoinbaseEnoteV1 &a, const CarrotCoinbaseEnoteV1 &b);
|
||||
static inline bool operator!=(const CarrotCoinbaseEnoteV1 &a, const CarrotCoinbaseEnoteV1 &b) { return !(a == b); }
|
||||
|
||||
} //namespace carrot
|
||||
@@ -0,0 +1,80 @@
|
||||
// Copyright (c) 2024, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
//! @file Constants used in Carrot
|
||||
|
||||
#pragma once
|
||||
|
||||
//local headers
|
||||
|
||||
//third party headers
|
||||
|
||||
//standard headers
|
||||
|
||||
//forward declarations
|
||||
|
||||
namespace carrot
|
||||
{
|
||||
|
||||
// Carrot addressing protocol domain separators
|
||||
static constexpr const unsigned char CARROT_DOMAIN_SEP_AMOUNT_BLINDING_FACTOR[] = "Carrot commitment mask";
|
||||
static constexpr const unsigned char CARROT_DOMAIN_SEP_ONETIME_EXTENSION_G[] = "Carrot key extension G";
|
||||
static constexpr const unsigned char CARROT_DOMAIN_SEP_ONETIME_EXTENSION_T[] = "Carrot key extension T";
|
||||
static constexpr const unsigned char CARROT_DOMAIN_SEP_ENCRYPTION_MASK_ANCHOR[] = "Carrot encryption mask anchor";
|
||||
static constexpr const unsigned char CARROT_DOMAIN_SEP_ENCRYPTION_MASK_AMOUNT[] = "Carrot encryption mask a";
|
||||
static constexpr const unsigned char CARROT_DOMAIN_SEP_ENCRYPTION_MASK_PAYMENT_ID[] = "Carrot encryption mask pid";
|
||||
static constexpr const unsigned char CARROT_DOMAIN_SEP_JANUS_ANCHOR_SPECIAL[] = "Carrot janus anchor special";
|
||||
static constexpr const unsigned char CARROT_DOMAIN_SEP_EPHEMERAL_PRIVKEY[] = "Carrot sending key normal";
|
||||
static constexpr const unsigned char CARROT_DOMAIN_SEP_VIEW_TAG[] = "Carrot view tag";
|
||||
static constexpr const unsigned char CARROT_DOMAIN_SEP_SENDER_RECEIVER_SECRET[] = "Carrot sender-receiver secret";
|
||||
static constexpr const unsigned char CARROT_DOMAIN_SEP_INPUT_CONTEXT_COINBASE = 'C';
|
||||
static constexpr const unsigned char CARROT_DOMAIN_SEP_INPUT_CONTEXT_RINGCT = 'R';
|
||||
|
||||
// Carrot account secret domain separators
|
||||
static constexpr const unsigned char CARROT_DOMAIN_SEP_PROVE_SPEND_KEY[] = "Carrot prove-spend key";
|
||||
static constexpr const unsigned char CARROT_DOMAIN_SEP_VIEW_BALANCE_SECRET[] = "Carrot view-balance secret";
|
||||
static constexpr const unsigned char CARROT_DOMAIN_SEP_GENERATE_IMAGE_KEY[] = "Carrot generate-image key";
|
||||
static constexpr const unsigned char CARROT_DOMAIN_SEP_INCOMING_VIEW_KEY[] = "Carrot incoming view key";
|
||||
static constexpr const unsigned char CARROT_DOMAIN_SEP_GENERATE_ADDRESS_SECRET[] = "Carrot generate-address secret";
|
||||
|
||||
// Carrot address domain separators
|
||||
static constexpr const unsigned char CARROT_DOMAIN_SEP_ADDRESS_INDEX_GEN[] = "Carrot address index generator";
|
||||
static constexpr const unsigned char CARROT_DOMAIN_SEP_SUBADDRESS_SCALAR[] = "Carrot subaddress scalar";
|
||||
|
||||
// Carrot misc constants
|
||||
static constexpr const unsigned int CARROT_MIN_TX_OUTPUTS = 2;
|
||||
static constexpr const unsigned int CARROT_MAX_TX_OUTPUTS = 8;
|
||||
static constexpr const unsigned int CARROT_MIN_TX_INPUTS = 1;
|
||||
static constexpr const unsigned int CARROT_MAX_TX_INPUTS = 64;
|
||||
|
||||
// SPARC addressing protocol domain separators
|
||||
static constexpr const unsigned char SPARC_DOMAIN_SEP_RETURN_PUBKEY_ENCRYPTION_MASK[] = "SPARC return pubkey encryption mask";
|
||||
static constexpr const unsigned char SPARC_DOMAIN_SEP_RETURN_ADDRESS_SCALAR[] = "SPARC return address scalar";
|
||||
static constexpr const unsigned char SPARC_DOMAIN_SEP_RETURN_INDEX_SCALAR[] = "SPARC return index scalar";
|
||||
|
||||
} //namespace carrot
|
||||
@@ -0,0 +1,172 @@
|
||||
// Copyright (c) 2024, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
//paired header
|
||||
#include "core_types.h"
|
||||
|
||||
//local headers
|
||||
#include "crypto/crypto.h"
|
||||
extern "C"
|
||||
{
|
||||
#include "crypto/crypto-ops.h"
|
||||
}
|
||||
|
||||
//third party headers
|
||||
#include <cstring>
|
||||
|
||||
//standard headers
|
||||
|
||||
namespace carrot
|
||||
{
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
template <std::size_t Sz>
|
||||
static void xor_bytes(const unsigned char(&a)[Sz], const unsigned char(&b)[Sz], unsigned char(&c_out)[Sz])
|
||||
{
|
||||
for (std::size_t i{0}; i < Sz; ++i)
|
||||
c_out[i] = a[i] ^ b[i];
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
static T xor_bytes(const T &a, const T &b)
|
||||
{
|
||||
T temp;
|
||||
xor_bytes(a.bytes, b.bytes, temp.bytes);
|
||||
return temp;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
bool operator==(const janus_anchor_t &a, const janus_anchor_t &b)
|
||||
{
|
||||
return memcmp(&a, &b, sizeof(janus_anchor_t)) == 0;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
janus_anchor_t operator^(const janus_anchor_t &a, const janus_anchor_t &b)
|
||||
{
|
||||
return xor_bytes(a, b);
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
bool operator==(const encrypted_amount_t &a, const encrypted_amount_t &b)
|
||||
{
|
||||
return memcmp(&a, &b, sizeof(encrypted_amount_t)) == 0;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
encrypted_amount_t operator^(const encrypted_amount_t &a, const encrypted_amount_t &b)
|
||||
{
|
||||
return xor_bytes(a, b);
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
bool operator==(const encrypted_return_pubkey_t &a, const encrypted_return_pubkey_t &b)
|
||||
{
|
||||
return memcmp(&a, &b, sizeof(encrypted_return_pubkey_t)) == 0;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
encrypted_return_pubkey_t operator^(const encrypted_return_pubkey_t &a, const encrypted_return_pubkey_t &b)
|
||||
{
|
||||
return xor_bytes(a, b);
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
bool operator==(const payment_id_t &a, const payment_id_t &b)
|
||||
{
|
||||
return memcmp(&a, &b, sizeof(payment_id_t)) == 0;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
payment_id_t operator^(const payment_id_t &a, const payment_id_t &b)
|
||||
{
|
||||
return xor_bytes(a, b);
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
bool operator==(const encrypted_payment_id_t &a, const encrypted_payment_id_t &b)
|
||||
{
|
||||
return memcmp(&a, &b, sizeof(encrypted_payment_id_t)) == 0;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
encrypted_payment_id_t operator^(const encrypted_payment_id_t &a, const encrypted_payment_id_t &b)
|
||||
{
|
||||
return xor_bytes(a, b);
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
bool operator==(const input_context_t &a, const input_context_t &b)
|
||||
{
|
||||
return memcmp(&a, &b, sizeof(input_context_t)) == 0;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
bool operator==(const view_tag_t &a, const view_tag_t &b)
|
||||
{
|
||||
return memcmp(&a, &b, sizeof(view_tag_t)) == 0;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
bool operator==(const rollup_binding_tag_t &a, const rollup_binding_tag_t &b)
|
||||
{
|
||||
return memcmp(&a, &b, sizeof(rollup_binding_tag_t)) == 0;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
janus_anchor_t gen_janus_anchor()
|
||||
{
|
||||
return crypto::rand<janus_anchor_t>();
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
payment_id_t gen_payment_id()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
const payment_id_t res = crypto::rand<payment_id_t>();
|
||||
if (res != null_payment_id)
|
||||
return res;
|
||||
}
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
encrypted_payment_id_t gen_encrypted_payment_id()
|
||||
{
|
||||
return crypto::rand<encrypted_payment_id_t>();
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
view_tag_t gen_view_tag()
|
||||
{
|
||||
return crypto::rand<view_tag_t>();
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
input_context_t gen_input_context()
|
||||
{
|
||||
return crypto::rand<input_context_t>();
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
mx25519_pubkey gen_x25519_pubkey()
|
||||
{
|
||||
unsigned char sc64[64];
|
||||
crypto::rand(sizeof(sc64), sc64);
|
||||
sc_reduce(sc64);
|
||||
ge_p3 P;
|
||||
ge_scalarmult_base(&P, sc64);
|
||||
mx25519_pubkey P_x25519;
|
||||
ge_p3_to_x25519(P_x25519.data, &P);
|
||||
return P_x25519;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
} //namespace carrot
|
||||
@@ -0,0 +1,166 @@
|
||||
// Copyright (c) 2024, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
//! @file Supporting types for Carrot (anchor, view tag, etc.).
|
||||
|
||||
#pragma once
|
||||
|
||||
//local headers
|
||||
#include "mx25519.h"
|
||||
|
||||
//third party headers
|
||||
|
||||
//standard headers
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
|
||||
//forward declarations
|
||||
|
||||
namespace carrot
|
||||
{
|
||||
|
||||
constexpr std::size_t JANUS_ANCHOR_BYTES{16};
|
||||
|
||||
/// either encodes randomness the private key of, or an HMAC of, the ephemeral pubkey
|
||||
struct janus_anchor_t final
|
||||
{
|
||||
unsigned char bytes[JANUS_ANCHOR_BYTES];
|
||||
};
|
||||
|
||||
/// carrot janus anchor XORd with a user-defined secret
|
||||
using encrypted_janus_anchor_t = janus_anchor_t;
|
||||
|
||||
/// carrot enote types
|
||||
enum class CarrotEnoteType : unsigned char
|
||||
{
|
||||
PAYMENT = 0,
|
||||
CHANGE = 1
|
||||
};
|
||||
|
||||
/// carrot encrypted amount
|
||||
constexpr std::size_t ENCRYPTED_AMOUNT_BYTES{8};
|
||||
struct encrypted_amount_t final
|
||||
{
|
||||
unsigned char bytes[ENCRYPTED_AMOUNT_BYTES];
|
||||
};
|
||||
|
||||
/// legacy payment ID
|
||||
constexpr std::size_t PAYMENT_ID_BYTES{8};
|
||||
struct payment_id_t final
|
||||
{
|
||||
unsigned char bytes[PAYMENT_ID_BYTES];
|
||||
};
|
||||
static constexpr payment_id_t null_payment_id{{0}};
|
||||
|
||||
/// legacy encrypted payment ID
|
||||
struct encrypted_payment_id_t final
|
||||
{
|
||||
unsigned char bytes[PAYMENT_ID_BYTES];
|
||||
};
|
||||
|
||||
/// carrot view tags
|
||||
constexpr std::size_t VIEW_TAG_BYTES{3};
|
||||
struct view_tag_t final
|
||||
{
|
||||
unsigned char bytes[VIEW_TAG_BYTES];
|
||||
};
|
||||
|
||||
static_assert(sizeof(view_tag_t) < 32, "uint8_t cannot index all view tag bits");
|
||||
|
||||
/// carrot input context
|
||||
constexpr std::size_t INPUT_CONTEXT_BYTES{1 + 32};
|
||||
struct input_context_t final
|
||||
{
|
||||
unsigned char bytes[INPUT_CONTEXT_BYTES];
|
||||
};
|
||||
|
||||
// SPARC encrypted return public key
|
||||
constexpr std::size_t ENCRYPTED_RETURN_PUBKEY_BYTES{32};
|
||||
struct encrypted_return_pubkey_t final
|
||||
{
|
||||
unsigned char bytes[ENCRYPTED_RETURN_PUBKEY_BYTES];
|
||||
};
|
||||
|
||||
/// Salvium rollup binding tag
|
||||
constexpr std::size_t ROLLUP_BINDING_TAG_BYTES{8};
|
||||
struct rollup_binding_tag_t final
|
||||
{
|
||||
unsigned char bytes[ROLLUP_BINDING_TAG_BYTES];
|
||||
};
|
||||
|
||||
/// overloaded operators: address tag
|
||||
bool operator==(const janus_anchor_t &a, const janus_anchor_t &b);
|
||||
static inline bool operator!=(const janus_anchor_t &a, const janus_anchor_t &b) { return !(a == b); }
|
||||
janus_anchor_t operator^(const janus_anchor_t &a, const janus_anchor_t &b);
|
||||
|
||||
/// overloaded operators: encrypted amount
|
||||
bool operator==(const encrypted_amount_t &a, const encrypted_amount_t &b);
|
||||
static inline bool operator!=(const encrypted_amount_t &a, const encrypted_amount_t &b) { return !(a == b); }
|
||||
encrypted_amount_t operator^(const encrypted_amount_t &a, const encrypted_amount_t &b);
|
||||
|
||||
/// overloaded operators: payment ID
|
||||
bool operator==(const payment_id_t &a, const payment_id_t &b);
|
||||
static inline bool operator!=(const payment_id_t &a, const payment_id_t &b) { return !(a == b); }
|
||||
payment_id_t operator^(const payment_id_t &a, const payment_id_t &b);
|
||||
|
||||
/// overloaded operators: encrypted payment ID
|
||||
bool operator==(const encrypted_payment_id_t &a, const encrypted_payment_id_t &b);
|
||||
static inline bool operator!=(const encrypted_payment_id_t &a, const encrypted_payment_id_t &b) { return !(a == b); }
|
||||
encrypted_payment_id_t operator^(const encrypted_payment_id_t &a, const encrypted_payment_id_t &b);
|
||||
|
||||
/// overloaded operators: input context
|
||||
bool operator==(const input_context_t &a, const input_context_t &b);
|
||||
static inline bool operator!=(const input_context_t &a, const input_context_t &b) { return !(a == b); }
|
||||
|
||||
/// overloaded operators: view tag
|
||||
bool operator==(const view_tag_t &a, const view_tag_t &b);
|
||||
static inline bool operator!=(const view_tag_t &a, const view_tag_t &b) { return !(a == b); }
|
||||
|
||||
/// overloaded operators: encrypted return pubkey
|
||||
bool operator==(const encrypted_return_pubkey_t &a, const encrypted_return_pubkey_t &b);
|
||||
static inline bool operator!=(const encrypted_return_pubkey_t &a, const encrypted_return_pubkey_t &b) { return !(a == b); }
|
||||
encrypted_return_pubkey_t operator^(const encrypted_return_pubkey_t &a, const encrypted_return_pubkey_t &b);
|
||||
|
||||
/// overloaded operators: rollup binding tag
|
||||
bool operator==(const rollup_binding_tag_t &a, const rollup_binding_tag_t &b);
|
||||
static inline bool operator!=(const rollup_binding_tag_t &a, const rollup_binding_tag_t &b) { return !(a == b); }
|
||||
|
||||
/// generate a random janus anchor
|
||||
janus_anchor_t gen_janus_anchor();
|
||||
/// generate a random (non-null) payment ID
|
||||
payment_id_t gen_payment_id();
|
||||
/// generate a random encrypted payment ID
|
||||
encrypted_payment_id_t gen_encrypted_payment_id();
|
||||
/// generate a random view tag
|
||||
view_tag_t gen_view_tag();
|
||||
/// generate a random input context
|
||||
input_context_t gen_input_context();
|
||||
/// generate a random X25519 pubkey (unclamped)
|
||||
mx25519_pubkey gen_x25519_pubkey();
|
||||
|
||||
} //namespace carrot
|
||||
@@ -0,0 +1,150 @@
|
||||
// Copyright (c) 2024, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
//paired header
|
||||
#include "destination.h"
|
||||
|
||||
//local headers
|
||||
#include "address_utils.h"
|
||||
#include "exceptions.h"
|
||||
#include "misc_log_ex.h"
|
||||
#include "ringct/rctOps.h"
|
||||
|
||||
//third party headers
|
||||
|
||||
//standard headers
|
||||
|
||||
#undef MONERO_DEFAULT_LOG_CATEGORY
|
||||
#define MONERO_DEFAULT_LOG_CATEGORY "carrot.dest"
|
||||
|
||||
namespace carrot
|
||||
{
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
bool operator==(const CarrotDestinationV1 &a, const CarrotDestinationV1 &b)
|
||||
{
|
||||
return a.address_spend_pubkey == b.address_spend_pubkey &&
|
||||
a.address_view_pubkey == b.address_view_pubkey &&
|
||||
a.is_subaddress == b.is_subaddress &&
|
||||
a.payment_id == b.payment_id;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void make_carrot_main_address_v1(const crypto::public_key &account_spend_pubkey,
|
||||
const crypto::public_key &primary_address_view_pubkey,
|
||||
CarrotDestinationV1 &destination_out)
|
||||
{
|
||||
destination_out = CarrotDestinationV1{
|
||||
.address_spend_pubkey = account_spend_pubkey,
|
||||
.address_view_pubkey = primary_address_view_pubkey,
|
||||
.is_subaddress = false,
|
||||
.payment_id = null_payment_id
|
||||
};
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void make_carrot_subaddress_v1(const crypto::public_key &account_spend_pubkey,
|
||||
const crypto::public_key &account_view_pubkey,
|
||||
const generate_address_secret_device &s_generate_address_dev,
|
||||
const std::uint32_t j_major,
|
||||
const std::uint32_t j_minor,
|
||||
CarrotDestinationV1 &destination_out)
|
||||
{
|
||||
CARROT_CHECK_AND_THROW(j_major || j_minor,
|
||||
bad_address_type, "j cannot be 0 for a subaddress, only for main addresses");
|
||||
|
||||
// s^j_gen = H_32[s_ga](j_major, j_minor)
|
||||
crypto::secret_key address_index_generator;
|
||||
s_generate_address_dev.make_index_extension_generator(j_major, j_minor, address_index_generator);
|
||||
|
||||
// k^j_subscal = H_n(K_s, j_major, j_minor, s^j_gen)
|
||||
crypto::secret_key subaddress_scalar;
|
||||
make_carrot_subaddress_scalar(account_spend_pubkey, address_index_generator, j_major, j_minor, subaddress_scalar);
|
||||
|
||||
// K^j_s = k^j_subscal * K_s
|
||||
const rct::key address_spend_pubkey =
|
||||
rct::scalarmultKey(rct::pk2rct(account_spend_pubkey), rct::sk2rct(subaddress_scalar));
|
||||
|
||||
// K^j_v = k^j_subscal * K_v
|
||||
const rct::key address_view_pubkey =
|
||||
rct::scalarmultKey(rct::pk2rct(account_view_pubkey), rct::sk2rct(subaddress_scalar));
|
||||
|
||||
destination_out = CarrotDestinationV1{
|
||||
.address_spend_pubkey = rct::rct2pk(address_spend_pubkey),
|
||||
.address_view_pubkey = rct::rct2pk(address_view_pubkey),
|
||||
.is_subaddress = true,
|
||||
.payment_id = null_payment_id
|
||||
};
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void make_carrot_integrated_address_v1(const crypto::public_key &account_spend_pubkey,
|
||||
const crypto::public_key &primary_address_view_pubkey,
|
||||
const payment_id_t payment_id,
|
||||
CarrotDestinationV1 &destination_out)
|
||||
{
|
||||
destination_out = CarrotDestinationV1{
|
||||
.address_spend_pubkey = account_spend_pubkey,
|
||||
.address_view_pubkey = primary_address_view_pubkey,
|
||||
.is_subaddress = false,
|
||||
.payment_id = payment_id
|
||||
};
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
CarrotDestinationV1 gen_carrot_main_address_v1()
|
||||
{
|
||||
return CarrotDestinationV1{
|
||||
.address_spend_pubkey = rct::rct2pk(rct::pkGen()),
|
||||
.address_view_pubkey = rct::rct2pk(rct::pkGen()),
|
||||
.is_subaddress = false,
|
||||
.payment_id = null_payment_id
|
||||
};
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
CarrotDestinationV1 gen_carrot_subaddress_v1()
|
||||
{
|
||||
return CarrotDestinationV1{
|
||||
.address_spend_pubkey = rct::rct2pk(rct::pkGen()),
|
||||
.address_view_pubkey = rct::rct2pk(rct::pkGen()),
|
||||
.is_subaddress = true,
|
||||
.payment_id = null_payment_id
|
||||
};
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
CarrotDestinationV1 gen_carrot_integrated_address_v1()
|
||||
{
|
||||
// force generate non-zero payment id
|
||||
payment_id_t payment_id{gen_payment_id()};
|
||||
while (payment_id == null_payment_id)
|
||||
payment_id = gen_payment_id();
|
||||
|
||||
return CarrotDestinationV1{
|
||||
.address_spend_pubkey = rct::rct2pk(rct::pkGen()),
|
||||
.address_view_pubkey = rct::rct2pk(rct::pkGen()),
|
||||
.is_subaddress = false,
|
||||
.payment_id = payment_id
|
||||
};
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
} //namespace carrot
|
||||
@@ -0,0 +1,117 @@
|
||||
// Copyright (c) 2024, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// A 'payment proposal' is a proposal to make an enote sending funds to a Carrot address.
|
||||
// Carrot: Cryptonote Address For Rerandomizable-RingCT-Output Transactions
|
||||
|
||||
#pragma once
|
||||
|
||||
//local headers
|
||||
#include "core_types.h"
|
||||
#include "crypto/crypto.h"
|
||||
#include "device.h"
|
||||
|
||||
//third party headers
|
||||
|
||||
//standard headers
|
||||
|
||||
//forward declarations
|
||||
|
||||
|
||||
namespace carrot
|
||||
{
|
||||
|
||||
////
|
||||
// CarrotDestinationV1
|
||||
// - for creating an output proposal to send an amount to someone
|
||||
///
|
||||
struct CarrotDestinationV1 final
|
||||
{
|
||||
/// K^j_s
|
||||
crypto::public_key address_spend_pubkey;
|
||||
/// K^j_v
|
||||
crypto::public_key address_view_pubkey;
|
||||
/// is a subaddress?
|
||||
bool is_subaddress;
|
||||
/// legacy payment id pid: null for main addresses and subaddresses
|
||||
payment_id_t payment_id;
|
||||
};
|
||||
|
||||
/// equality operators
|
||||
bool operator==(const CarrotDestinationV1 &a, const CarrotDestinationV1 &b);
|
||||
static inline bool operator!=(const CarrotDestinationV1 &a, const CarrotDestinationV1 &b) { return !(a == b); }
|
||||
|
||||
/**
|
||||
* brief: make_carrot_main_address_v1 - make a destination address
|
||||
* param: account_spend_pubkey - K_s
|
||||
* param: primary_address_view_pubkey - K^0_v = k_v G
|
||||
* outparam: destination_out - the full main address
|
||||
*/
|
||||
void make_carrot_main_address_v1(const crypto::public_key &account_spend_pubkey,
|
||||
const crypto::public_key &primary_address_view_pubkey,
|
||||
CarrotDestinationV1 &destination_out);
|
||||
/**
|
||||
* brief: make_carrot_subaddress_v1 - make a destination address
|
||||
* param: account_spend_pubkey - K_s
|
||||
* param: account_view_pubkey - K_v = k_v K_s
|
||||
* param: s_generate_address_dev - device for s_ga
|
||||
* param: j_major -
|
||||
* param: j_minor -
|
||||
* outparam: destination_out - the full subaddress
|
||||
*/
|
||||
void make_carrot_subaddress_v1(const crypto::public_key &account_spend_pubkey,
|
||||
const crypto::public_key &account_view_pubkey,
|
||||
const generate_address_secret_device &s_generate_address_dev,
|
||||
const std::uint32_t j_major,
|
||||
const std::uint32_t j_minor,
|
||||
CarrotDestinationV1 &destination_out);
|
||||
/**
|
||||
* brief: make_carrot_integrated_address_v1 - make a destination address
|
||||
* param: account_spend_pubkey - K_s
|
||||
* param: primary_address_view_pubkey - K^0_v = k_v G
|
||||
* param: payment_id - pid
|
||||
* outparam: destination_out - the full main address
|
||||
*/
|
||||
void make_carrot_integrated_address_v1(const crypto::public_key &account_spend_pubkey,
|
||||
const crypto::public_key &primary_address_view_pubkey,
|
||||
const payment_id_t payment_id,
|
||||
CarrotDestinationV1 &destination_out);
|
||||
/**
|
||||
* brief: gen_carrot_main_address_v1 - generate a random main address
|
||||
*/
|
||||
CarrotDestinationV1 gen_carrot_main_address_v1();
|
||||
/**
|
||||
* brief: gen_carrot_main_address_v1 - generate a random subaddress
|
||||
*/
|
||||
CarrotDestinationV1 gen_carrot_subaddress_v1();
|
||||
/**
|
||||
* brief: gen_carrot_main_address_v1 - generate a random integrated address
|
||||
*/
|
||||
CarrotDestinationV1 gen_carrot_integrated_address_v1();
|
||||
|
||||
} //namespace carrot
|
||||
@@ -0,0 +1,198 @@
|
||||
// Copyright (c) 2024, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
//! @file Abstract interfaces for performing scanning without revealing account keys
|
||||
|
||||
#pragma once
|
||||
|
||||
//local headers
|
||||
#include "core_types.h"
|
||||
#include "crypto/crypto.h"
|
||||
#include "mx25519.h"
|
||||
|
||||
//third party headers
|
||||
|
||||
//standard headers
|
||||
#include <cstdio>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
//forward declarations
|
||||
|
||||
|
||||
/**
|
||||
* These device interfaces were written primarily to be as lean as possible, for ease of the
|
||||
* implementor, so long as account keys don't leak. As such, the interfaces do not shield
|
||||
* sender-receiver secrets, and thus temporary access to this device interface can expose
|
||||
* transaction content permanently in a provable manner. The device interface currently used in
|
||||
* Monero (hw::device) also exposes transaction content, which can be saved permanently, but it
|
||||
* wouldn't necessarily be provable. Thus, in the case of a breach, the original user has some
|
||||
* plausible deniability with (hw::device), which cannot be said of the interfaces in this file.
|
||||
* It's not impossible to make carrot scanning happen completely on-device, but it is significantly
|
||||
* more involved.
|
||||
*/
|
||||
|
||||
namespace carrot
|
||||
{
|
||||
/**
|
||||
* brief: base exception type for reporting carrot device errors.
|
||||
* note: devices should only throw this exception or derived classes
|
||||
*/
|
||||
struct device_error: public std::runtime_error
|
||||
{
|
||||
/**
|
||||
* param: dev_make - e.g. "Trezor", "Ledger"
|
||||
* param: dev_model - e.g. "Model T", "Nano X"
|
||||
* param: func_called - verbatim device interface method name, e.g. "view_key_scalar_mult_x25519"
|
||||
* param: msg - arbitrary error message
|
||||
* param: code - arbitrary error code
|
||||
*/
|
||||
device_error(std::string &&dev_make,
|
||||
std::string &&dev_model,
|
||||
std::string &&func_called,
|
||||
std::string &&msg,
|
||||
const int code)
|
||||
: std::runtime_error(make_formatted_message(dev_make, dev_model, func_called, msg, code)),
|
||||
dev_make(dev_make), dev_model(dev_model), func_called(func_called), msg(msg), code(code)
|
||||
{}
|
||||
|
||||
static std::string make_formatted_message(const std::string &dev_make,
|
||||
const std::string &dev_model,
|
||||
const std::string &func_called,
|
||||
const std::string &msg,
|
||||
const int code)
|
||||
{
|
||||
char buf[384];
|
||||
snprintf(buf, sizeof(buf),
|
||||
"%s %s device error (%d), at %s(): %s",
|
||||
dev_make.c_str(), dev_model.c_str(), code, func_called.c_str(), msg.c_str());
|
||||
return {buf};
|
||||
}
|
||||
|
||||
const std::string dev_make;
|
||||
const std::string dev_model;
|
||||
const std::string func_called;
|
||||
const std::string msg;
|
||||
const int code;
|
||||
};
|
||||
|
||||
struct view_incoming_key_device
|
||||
{
|
||||
/**
|
||||
* brief: view_key_scalar_mult_ed25519 - do an Ed25519 scalar mult against the incoming view key
|
||||
* kvP = k_v * P
|
||||
* param: P - Ed25519 base point
|
||||
* outparam: kvP
|
||||
* return: true on success, false on failure (e.g. unable to decompress point)
|
||||
*/
|
||||
virtual bool view_key_scalar_mult_ed25519(const crypto::public_key &P, crypto::public_key &kvP) const = 0;
|
||||
|
||||
/**
|
||||
* brief: view_key_scalar_mult_x25519 - do an X25519 scalar mult and cofactor clear against the incoming view key
|
||||
* kvD = k_v * D
|
||||
* param: D - X25519 base point
|
||||
* outparam: kvD
|
||||
* return: true on success, false on failure (e.g. unable to decompress point)
|
||||
*/
|
||||
virtual bool view_key_scalar_mult_x25519(const mx25519_pubkey &D, mx25519_pubkey &kvD) const = 0;
|
||||
|
||||
/**
|
||||
* brief: make_janus_anchor_special - make a janus anchor for "special" enotes
|
||||
* anchor_sp = H_16(D_e, input_context, Ko, k_v)
|
||||
* param: enote_ephemeral_pubkey - D_e
|
||||
* param: input_context - input_context
|
||||
* param: account_spend_pubkey - K_s
|
||||
* outparam: anchor_special_out - anchor_sp
|
||||
*/
|
||||
virtual void make_janus_anchor_special(const mx25519_pubkey &enote_ephemeral_pubkey,
|
||||
const input_context_t &input_context,
|
||||
const crypto::public_key &onetime_address,
|
||||
janus_anchor_t &anchor_special_out) const = 0;
|
||||
|
||||
virtual void make_internal_return_privkey(const input_context_t &input_context,
|
||||
const crypto::public_key &onetime_address,
|
||||
crypto::secret_key &return_privkey_out) const = 0;
|
||||
|
||||
virtual ~view_incoming_key_device() = default;
|
||||
};
|
||||
|
||||
struct view_balance_secret_device
|
||||
{
|
||||
/**
|
||||
* brief: make_internal_view_tag - make an internal view tag, given non-secret data
|
||||
* vt = H_3(s_vb || input_context || Ko)
|
||||
* param: input_context - input_context
|
||||
* param: onetime_address - Ko
|
||||
* outparam: view_tag_out - vt
|
||||
*/
|
||||
virtual void make_internal_view_tag(const input_context_t &input_context,
|
||||
const crypto::public_key &onetime_address,
|
||||
view_tag_t &view_tag_out) const = 0;
|
||||
|
||||
/**
|
||||
* brief: make_internal_sender_receiver_secret - make internal sender-receiver secret, given non-secret data
|
||||
* s^ctx_sr = H_32(s_sr, D_e, input_context)
|
||||
* param: enote_ephemeral_pubkey - D_e
|
||||
* param: input_context - input_context
|
||||
* outparam: s_sender_receiver_out - s^ctx_sr
|
||||
*/
|
||||
virtual void make_internal_sender_receiver_secret(const mx25519_pubkey &enote_ephemeral_pubkey,
|
||||
const input_context_t &input_context,
|
||||
crypto::hash &s_sender_receiver_out) const = 0;
|
||||
|
||||
/**
|
||||
* brief: make_internal_return_privkey - make internal return private key, given non-secret data
|
||||
* k_return = H_32(s_vb || input_context || Ko)
|
||||
* param: input_context - input_context
|
||||
* param: onetime_address - Ko
|
||||
* outparam: return_privkey_out - k_return
|
||||
*/
|
||||
virtual void make_internal_return_privkey(const input_context_t &input_context,
|
||||
const crypto::public_key &onetime_address,
|
||||
crypto::secret_key &return_privkey_out) const = 0;
|
||||
|
||||
virtual ~view_balance_secret_device() = default;
|
||||
};
|
||||
|
||||
struct generate_address_secret_device
|
||||
{
|
||||
/**
|
||||
* brief: make_index_extension_generator - make carrot index extension generator s^j_gen
|
||||
* s^j_gen = H_32[s_ga](j_major, j_minor)
|
||||
* param: major_index - j_major
|
||||
* param: minor_index - j_minor
|
||||
* outparam: address_generator_out - s^j_gen
|
||||
*/
|
||||
virtual void make_index_extension_generator(const std::uint32_t major_index,
|
||||
const std::uint32_t minor_index,
|
||||
crypto::secret_key &address_generator_out) const = 0;
|
||||
|
||||
virtual ~generate_address_secret_device() = default;
|
||||
};
|
||||
|
||||
} //namespace carrot
|
||||
@@ -0,0 +1,111 @@
|
||||
// Copyright (c) 2024, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
//pair header
|
||||
#include "device_ram_borrowed.h"
|
||||
|
||||
//local headers
|
||||
#include "address_utils.h"
|
||||
#include "enote_utils.h"
|
||||
#include "ringct/rctOps.h"
|
||||
|
||||
//third party headers
|
||||
|
||||
//standard headers
|
||||
|
||||
|
||||
namespace carrot
|
||||
{
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
bool view_incoming_key_ram_borrowed_device::view_key_scalar_mult_ed25519(const crypto::public_key &P,
|
||||
crypto::public_key &kvP) const
|
||||
{
|
||||
kvP = rct::rct2pk(rct::scalarmultKey(rct::pk2rct(P), rct::sk2rct(m_k_view_incoming)));
|
||||
return true;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
bool view_incoming_key_ram_borrowed_device::view_key_scalar_mult_x25519(const mx25519_pubkey &D,
|
||||
mx25519_pubkey &kvD) const
|
||||
{
|
||||
return make_carrot_uncontextualized_shared_key_receiver(m_k_view_incoming, D, kvD);
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void view_incoming_key_ram_borrowed_device::make_internal_return_privkey(const input_context_t &input_context,
|
||||
const crypto::public_key &onetime_address,
|
||||
crypto::secret_key &return_privkey_out) const
|
||||
{
|
||||
make_sparc_return_privkey(to_bytes(m_k_view_incoming), input_context, onetime_address, return_privkey_out);
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void view_incoming_key_ram_borrowed_device::make_janus_anchor_special(
|
||||
const mx25519_pubkey &enote_ephemeral_pubkey,
|
||||
const input_context_t &input_context,
|
||||
const crypto::public_key &onetime_address,
|
||||
janus_anchor_t &anchor_special_out) const
|
||||
{
|
||||
return make_carrot_janus_anchor_special(enote_ephemeral_pubkey,
|
||||
input_context,
|
||||
onetime_address,
|
||||
m_k_view_incoming,
|
||||
anchor_special_out);
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void view_balance_secret_ram_borrowed_device::make_internal_view_tag(const input_context_t &input_context,
|
||||
const crypto::public_key &onetime_address,
|
||||
view_tag_t &view_tag_out) const
|
||||
{
|
||||
make_carrot_view_tag(to_bytes(m_s_view_balance), input_context, onetime_address, view_tag_out);
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void view_balance_secret_ram_borrowed_device::make_internal_sender_receiver_secret(
|
||||
const mx25519_pubkey &enote_ephemeral_pubkey,
|
||||
const input_context_t &input_context,
|
||||
crypto::hash &s_sender_receiver_out) const
|
||||
{
|
||||
make_carrot_sender_receiver_secret(to_bytes(m_s_view_balance),
|
||||
enote_ephemeral_pubkey,
|
||||
input_context,
|
||||
s_sender_receiver_out);
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void view_balance_secret_ram_borrowed_device::make_internal_return_privkey(const input_context_t &input_context,
|
||||
const crypto::public_key &onetime_address,
|
||||
crypto::secret_key &return_privkey_out) const
|
||||
{
|
||||
make_sparc_return_privkey(to_bytes(m_s_view_balance), input_context, onetime_address, return_privkey_out);
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void generate_address_secret_ram_borrowed_device::make_index_extension_generator(
|
||||
const std::uint32_t major_index,
|
||||
const std::uint32_t minor_index,
|
||||
crypto::secret_key &address_generator_out) const
|
||||
{
|
||||
make_carrot_index_extension_generator(m_s_generate_address, major_index, minor_index, address_generator_out);
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
} //namespace carrot
|
||||
@@ -0,0 +1,107 @@
|
||||
// Copyright (c) 2024, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
//! @file Carrot device implementations for in-memory keys & secrets
|
||||
|
||||
#pragma once
|
||||
|
||||
//local headers
|
||||
#include "device.h"
|
||||
|
||||
//third party headers
|
||||
|
||||
//standard headers
|
||||
|
||||
//forward declarations
|
||||
|
||||
|
||||
namespace carrot
|
||||
{
|
||||
|
||||
class view_incoming_key_ram_borrowed_device: virtual public view_incoming_key_device
|
||||
{
|
||||
public:
|
||||
view_incoming_key_ram_borrowed_device(const crypto::secret_key &k_view_incoming):
|
||||
m_k_view_incoming(k_view_incoming) {}
|
||||
|
||||
bool view_key_scalar_mult_ed25519(const crypto::public_key &P,
|
||||
crypto::public_key &kvP) const override;
|
||||
|
||||
bool view_key_scalar_mult_x25519(const mx25519_pubkey &D,
|
||||
mx25519_pubkey &kvD) const override;
|
||||
|
||||
void make_janus_anchor_special(const mx25519_pubkey &enote_ephemeral_pubkey,
|
||||
const input_context_t &input_context,
|
||||
const crypto::public_key &onetime_address,
|
||||
janus_anchor_t &anchor_special_out) const override;
|
||||
|
||||
void make_internal_return_privkey(const input_context_t &input_context,
|
||||
const crypto::public_key &onetime_address,
|
||||
crypto::secret_key &return_privkey_out) const override;
|
||||
|
||||
protected:
|
||||
const crypto::secret_key &m_k_view_incoming;
|
||||
};
|
||||
|
||||
class view_balance_secret_ram_borrowed_device: public view_balance_secret_device
|
||||
{
|
||||
public:
|
||||
view_balance_secret_ram_borrowed_device(const crypto::secret_key &s_view_balance):
|
||||
m_s_view_balance(s_view_balance) {}
|
||||
|
||||
void make_internal_view_tag(const input_context_t &input_context,
|
||||
const crypto::public_key &onetime_address,
|
||||
view_tag_t &view_tag_out) const override;
|
||||
|
||||
void make_internal_sender_receiver_secret(const mx25519_pubkey &enote_ephemeral_pubkey,
|
||||
const input_context_t &input_context,
|
||||
crypto::hash &s_sender_receiver_out) const override;
|
||||
|
||||
void make_internal_return_privkey(const input_context_t &input_context,
|
||||
const crypto::public_key &onetime_address,
|
||||
crypto::secret_key &return_privkey_out) const override;
|
||||
|
||||
protected:
|
||||
const crypto::secret_key &m_s_view_balance;
|
||||
};
|
||||
|
||||
class generate_address_secret_ram_borrowed_device: public generate_address_secret_device
|
||||
{
|
||||
public:
|
||||
generate_address_secret_ram_borrowed_device(const crypto::secret_key &s_generate_address):
|
||||
m_s_generate_address(s_generate_address) {}
|
||||
|
||||
void make_index_extension_generator(const std::uint32_t major_index,
|
||||
const std::uint32_t minor_index,
|
||||
crypto::secret_key &address_generator_out) const override;
|
||||
|
||||
protected:
|
||||
const crypto::secret_key &m_s_generate_address;
|
||||
};
|
||||
|
||||
} //namespace carrot
|
||||
@@ -0,0 +1,604 @@
|
||||
// Copyright (c) 2024, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
//paired header
|
||||
#include "enote_utils.h"
|
||||
|
||||
//local headers
|
||||
#include "config.h"
|
||||
extern "C"
|
||||
{
|
||||
#include "crypto/crypto-ops.h"
|
||||
}
|
||||
#include "crypto/generators.h"
|
||||
#include "crypto/wallet/crypto.h"
|
||||
#include "hash_functions.h"
|
||||
#include "int-util.h"
|
||||
#include "string_tools.h"
|
||||
#include "misc_language.h"
|
||||
#include "ringct/rctOps.h"
|
||||
#include "transcript_fixed.h"
|
||||
|
||||
//third party headers
|
||||
|
||||
//standard headers
|
||||
#include <mutex>
|
||||
|
||||
#undef MONERO_DEFAULT_LOG_CATEGORY
|
||||
#define MONERO_DEFAULT_LOG_CATEGORY "carrot"
|
||||
|
||||
namespace carrot
|
||||
{
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
static const mx25519_impl* get_mx25519_impl()
|
||||
{
|
||||
static std::once_flag of;
|
||||
static const mx25519_impl *impl;
|
||||
std::call_once(of, [&](){ impl = mx25519_select_impl(MX25519_TYPE_AUTO); });
|
||||
if (impl == nullptr)
|
||||
throw std::runtime_error("failed to obtain a mx25519 implementation");
|
||||
return impl;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
static encrypted_amount_t enc_amount(const rct::xmr_amount amount, const encrypted_amount_t &mask)
|
||||
{
|
||||
static_assert(sizeof(rct::xmr_amount) == sizeof(encrypted_amount_t), "");
|
||||
|
||||
// little_endian(amount) XOR H_8(q, Ko)
|
||||
encrypted_amount_t amount_LE;
|
||||
memcpy_swap64le(amount_LE.bytes, &amount, 1);
|
||||
return amount_LE ^ mask;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
static rct::xmr_amount dec_amount(const encrypted_amount_t &encrypted_amount, const encrypted_amount_t &mask)
|
||||
{
|
||||
static_assert(sizeof(rct::xmr_amount) == sizeof(encrypted_amount_t), "");
|
||||
|
||||
// system_endian(encrypted_amount XOR H_8(q, Ko))
|
||||
const encrypted_amount_t decryptd_amount{encrypted_amount ^ mask};
|
||||
rct::xmr_amount amount;
|
||||
memcpy_swap64le(&amount, &decryptd_amount, 1);
|
||||
return amount;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
template <typename Pid,
|
||||
typename OtherPid = std::conditional_t<std::is_same_v<Pid, payment_id_t>, encrypted_payment_id_t, payment_id_t>>
|
||||
static OtherPid convert_payment_id(const Pid &v)
|
||||
{
|
||||
static_assert(sizeof(Pid) == PAYMENT_ID_BYTES);
|
||||
OtherPid conv;
|
||||
memcpy(&conv, &v, PAYMENT_ID_BYTES);
|
||||
return conv;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void make_carrot_enote_ephemeral_privkey(const janus_anchor_t &anchor_norm,
|
||||
const input_context_t &input_context,
|
||||
const crypto::public_key &address_spend_pubkey,
|
||||
const payment_id_t payment_id,
|
||||
crypto::secret_key &enote_ephemeral_privkey_out)
|
||||
{
|
||||
// k_e = (H_64(anchor_norm, input_context, K^j_s, pid)) mod l
|
||||
const auto transcript = sp::make_fixed_transcript<CARROT_DOMAIN_SEP_EPHEMERAL_PRIVKEY>(
|
||||
anchor_norm, input_context, address_spend_pubkey, payment_id);
|
||||
derive_scalar(transcript.data(), transcript.size(), nullptr, &enote_ephemeral_privkey_out);
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void make_carrot_enote_ephemeral_pubkey_cryptonote(const crypto::secret_key &enote_ephemeral_privkey,
|
||||
mx25519_pubkey &enote_ephemeral_pubkey_out)
|
||||
{
|
||||
// D_e = d_e B
|
||||
mx25519_scmul_base(get_mx25519_impl(),
|
||||
&enote_ephemeral_pubkey_out,
|
||||
reinterpret_cast<const mx25519_privkey*>(&enote_ephemeral_privkey));
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void make_carrot_enote_ephemeral_pubkey_subaddress(const crypto::secret_key &enote_ephemeral_privkey,
|
||||
const crypto::public_key &address_spend_pubkey,
|
||||
mx25519_pubkey &enote_ephemeral_pubkey_out)
|
||||
{
|
||||
// deserialize K^j_s
|
||||
ge_p3 address_spend_pubkey_p3;
|
||||
ge_frombytes_vartime(&address_spend_pubkey_p3, to_bytes(address_spend_pubkey));
|
||||
|
||||
// K_e = d_e K^j_s
|
||||
ge_p3 D_e_in_ed25519;
|
||||
ge_scalarmult_p3(&D_e_in_ed25519, to_bytes(enote_ephemeral_privkey), &address_spend_pubkey_p3);
|
||||
|
||||
// D_e = ConvertPointE(K_e)
|
||||
ge_p3_to_x25519(enote_ephemeral_pubkey_out.data, &D_e_in_ed25519);
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void make_carrot_enote_ephemeral_pubkey(const crypto::secret_key &enote_ephemeral_privkey,
|
||||
const crypto::public_key &address_spend_pubkey,
|
||||
const bool is_subaddress,
|
||||
mx25519_pubkey &enote_ephemeral_pubkey_out)
|
||||
{
|
||||
if (is_subaddress)
|
||||
{
|
||||
// D_e = d_e ConvertPointE(K^j_s)
|
||||
make_carrot_enote_ephemeral_pubkey_subaddress(enote_ephemeral_privkey,
|
||||
address_spend_pubkey,
|
||||
enote_ephemeral_pubkey_out);
|
||||
}
|
||||
else // !is_subaddress
|
||||
{
|
||||
// D_e = d_e B
|
||||
make_carrot_enote_ephemeral_pubkey_cryptonote(enote_ephemeral_privkey, enote_ephemeral_pubkey_out);
|
||||
}
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
bool make_carrot_uncontextualized_shared_key_receiver(const crypto::secret_key &k_view,
|
||||
const mx25519_pubkey &enote_ephemeral_pubkey,
|
||||
mx25519_pubkey &s_sender_receiver_unctx_out)
|
||||
{
|
||||
// s_sr = k_v D_e
|
||||
mx25519_scmul_key(get_mx25519_impl(),
|
||||
&s_sender_receiver_unctx_out,
|
||||
reinterpret_cast<const mx25519_privkey*>(&k_view),
|
||||
&enote_ephemeral_pubkey);
|
||||
|
||||
return true;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
bool make_carrot_uncontextualized_shared_key_sender(const crypto::secret_key &enote_ephemeral_privkey,
|
||||
const crypto::public_key &address_view_pubkey,
|
||||
mx25519_pubkey &s_sender_receiver_unctx_out)
|
||||
{
|
||||
// if K^j_v not in prime order subgroup, then FAIL
|
||||
ge_p3 address_view_pubkey_p3;
|
||||
if (!rct::toPointCheckOrder(&address_view_pubkey_p3, to_bytes(address_view_pubkey)))
|
||||
return false;
|
||||
|
||||
// D^j_v = ConvertPointE(K^j_v)
|
||||
mx25519_pubkey address_view_pubkey_x25519;
|
||||
ge_p3_to_x25519(address_view_pubkey_x25519.data, &address_view_pubkey_p3);
|
||||
|
||||
// s_sr = d_e D^j_v
|
||||
mx25519_scmul_key(get_mx25519_impl(),
|
||||
&s_sender_receiver_unctx_out,
|
||||
reinterpret_cast<const mx25519_privkey*>(&enote_ephemeral_privkey),
|
||||
&address_view_pubkey_x25519);
|
||||
|
||||
return true;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void make_carrot_view_tag(const unsigned char s_sender_receiver_unctx[32],
|
||||
const input_context_t &input_context,
|
||||
const crypto::public_key &onetime_address,
|
||||
view_tag_t &view_tag_out)
|
||||
{
|
||||
// vt = H_3(s_sr || input_context || Ko)
|
||||
const auto transcript = sp::make_fixed_transcript<CARROT_DOMAIN_SEP_VIEW_TAG>(input_context, onetime_address);
|
||||
derive_bytes_3(transcript.data(), transcript.size(), s_sender_receiver_unctx, &view_tag_out);
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void make_sparc_return_privkey(const unsigned char s_sender_receiver_unctx[32],
|
||||
const input_context_t &input_context,
|
||||
const crypto::public_key &onetime_address,
|
||||
crypto::secret_key &return_privkey_out)
|
||||
{
|
||||
// k_return = H_32(s_sr || input_context || Ko)
|
||||
const auto transcript = sp::make_fixed_transcript<SPARC_DOMAIN_SEP_RETURN_ADDRESS_SCALAR>(input_context, onetime_address);
|
||||
derive_scalar(transcript.data(), transcript.size(), s_sender_receiver_unctx, &return_privkey_out);
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void make_sparc_return_index(const unsigned char s_sender_receiver_unctx[32],
|
||||
const input_context_t &input_context,
|
||||
const crypto::public_key &onetime_address,
|
||||
const uint64_t idx,
|
||||
crypto::secret_key &return_index_out)
|
||||
{
|
||||
// k_idx = H_32(s_sr || input_context || Ko || idx)
|
||||
const auto transcript = sp::make_fixed_transcript<SPARC_DOMAIN_SEP_RETURN_INDEX_SCALAR>(input_context, onetime_address, idx);
|
||||
derive_scalar(transcript.data(), transcript.size(), s_sender_receiver_unctx, &return_index_out);
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void make_sparc_return_pubkey_encryption_mask(const unsigned char s_sender_receiver_unctx[32],
|
||||
const input_context_t &input_context,
|
||||
const crypto::public_key &onetime_address,
|
||||
encrypted_return_pubkey_t &return_pubkey_mask_out)
|
||||
{
|
||||
// m_return = H_32(s_sr || input_context || Ko)
|
||||
const auto transcript = sp::make_fixed_transcript<SPARC_DOMAIN_SEP_RETURN_PUBKEY_ENCRYPTION_MASK>(input_context, onetime_address);
|
||||
derive_bytes_32(transcript.data(), transcript.size(), s_sender_receiver_unctx, &return_pubkey_mask_out);
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void make_sparc_return_pubkey(const unsigned char s_sender_receiver_unctx[32],
|
||||
const input_context_t &input_context,
|
||||
const view_balance_secret_device *s_view_balance_dev,
|
||||
const crypto::public_key &onetime_address,
|
||||
const uint64_t idx,
|
||||
encrypted_return_pubkey_t &return_pubkey_out)
|
||||
{
|
||||
// compute k_return
|
||||
crypto::secret_key k_return;
|
||||
s_view_balance_dev->make_internal_return_privkey(input_context, onetime_address, k_return);
|
||||
|
||||
// compute k_idx
|
||||
crypto::secret_key k_idx;
|
||||
make_sparc_return_index(s_sender_receiver_unctx, input_context, onetime_address, idx, k_idx);
|
||||
|
||||
// compute m_return
|
||||
encrypted_return_pubkey_t m_return;
|
||||
make_sparc_return_pubkey_encryption_mask(s_sender_receiver_unctx,
|
||||
input_context,
|
||||
onetime_address,
|
||||
m_return);
|
||||
|
||||
#if 1
|
||||
// compute SPARC K_return = k_return * G
|
||||
crypto::public_key K_return;
|
||||
crypto::secret_key_to_public_key(k_return, K_return);
|
||||
|
||||
// compute return_enc
|
||||
encrypted_return_pubkey_t return_pub;
|
||||
static_assert(sizeof(K_return.data) == sizeof(return_pub.bytes), "Size mismatch");
|
||||
memcpy(return_pub.bytes, K_return.data, sizeof(encrypted_return_pubkey_t));
|
||||
#else
|
||||
// compute SPARC K_return = k_return * G + k_idx * T
|
||||
rct::key K_return;
|
||||
rct::addKeys2(K_return,
|
||||
rct::sk2rct(k_return),
|
||||
rct::sk2rct(k_idx),
|
||||
rct::pk2rct(crypto::get_T()));
|
||||
|
||||
// compute return_enc
|
||||
encrypted_return_pubkey_t return_pub;
|
||||
static_assert(sizeof(K_return.bytes) == sizeof(return_pub.bytes), "Size mismatch");
|
||||
memcpy(return_pub.bytes, K_return.bytes, sizeof(encrypted_return_pubkey_t));
|
||||
#endif
|
||||
return_pubkey_out = return_pub ^ m_return;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
input_context_t make_carrot_input_context_coinbase(const std::uint64_t block_index)
|
||||
{
|
||||
// input_context = "C" || IntToBytes256(block_index)
|
||||
input_context_t input_context{};
|
||||
input_context.bytes[0] = CARROT_DOMAIN_SEP_INPUT_CONTEXT_COINBASE;
|
||||
memcpy_swap64le(input_context.bytes + 1, &block_index, 1);
|
||||
return input_context;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
input_context_t make_carrot_input_context(const crypto::key_image &first_rct_key_image)
|
||||
{
|
||||
// input_context = "R" || KI_1
|
||||
input_context_t input_context{};
|
||||
input_context.bytes[0] = CARROT_DOMAIN_SEP_INPUT_CONTEXT_RINGCT;
|
||||
memcpy(input_context.bytes + 1, first_rct_key_image.data, sizeof(crypto::key_image));
|
||||
return input_context;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void make_carrot_sender_receiver_secret(const unsigned char s_sender_receiver_unctx[32],
|
||||
const mx25519_pubkey &enote_ephemeral_pubkey,
|
||||
const input_context_t &input_context,
|
||||
crypto::hash &s_sender_receiver_out)
|
||||
{
|
||||
// s^ctx_sr = H_32(s_sr, D_e, input_context)
|
||||
const auto transcript = sp::make_fixed_transcript<CARROT_DOMAIN_SEP_SENDER_RECEIVER_SECRET>(
|
||||
enote_ephemeral_pubkey, input_context);
|
||||
derive_bytes_32(transcript.data(), transcript.size(), s_sender_receiver_unctx, &s_sender_receiver_out);
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void make_carrot_onetime_address_extension_g(const crypto::hash &s_sender_receiver,
|
||||
const rct::key &amount_commitment,
|
||||
crypto::secret_key &sender_extension_out)
|
||||
{
|
||||
// k^o_g = H_n("..g..", s^ctx_sr, C_a)
|
||||
const auto transcript = sp::make_fixed_transcript<CARROT_DOMAIN_SEP_ONETIME_EXTENSION_G>(amount_commitment);
|
||||
derive_scalar(transcript.data(), transcript.size(), &s_sender_receiver, &sender_extension_out);
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void make_carrot_onetime_address_extension_t(const crypto::hash &s_sender_receiver,
|
||||
const rct::key &amount_commitment,
|
||||
crypto::secret_key &sender_extension_out)
|
||||
{
|
||||
// k^o_t = H_n("..t..", s^ctx_sr, C_a)
|
||||
const auto transcript = sp::make_fixed_transcript<CARROT_DOMAIN_SEP_ONETIME_EXTENSION_T>(amount_commitment);
|
||||
derive_scalar(transcript.data(), transcript.size(), &s_sender_receiver, &sender_extension_out);
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void make_carrot_onetime_address_extension_pubkey(const crypto::hash &s_sender_receiver,
|
||||
const rct::key &amount_commitment,
|
||||
crypto::public_key &sender_extension_pubkey_out)
|
||||
{
|
||||
// k^o_g = H_n("..g..", s^ctx_sr, C_a)
|
||||
crypto::secret_key sender_extension_g;
|
||||
make_carrot_onetime_address_extension_g(s_sender_receiver, amount_commitment, sender_extension_g);
|
||||
|
||||
// k^o_t = H_n("..t..", s^ctx_sr, C_a)
|
||||
crypto::secret_key sender_extension_t;
|
||||
make_carrot_onetime_address_extension_t(s_sender_receiver, amount_commitment, sender_extension_t);
|
||||
|
||||
// K^o_ext = k^o_g G + k^o_t T
|
||||
rct::key sender_extension_pubkey_tmp;
|
||||
rct::addKeys2(sender_extension_pubkey_tmp,
|
||||
rct::sk2rct(sender_extension_g),
|
||||
rct::sk2rct(sender_extension_t),
|
||||
rct::pk2rct(crypto::get_T()));
|
||||
|
||||
sender_extension_pubkey_out = rct::rct2pk(sender_extension_pubkey_tmp);
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void make_carrot_onetime_address(const crypto::public_key &address_spend_pubkey,
|
||||
const crypto::hash &s_sender_receiver,
|
||||
const rct::key &amount_commitment,
|
||||
crypto::public_key &onetime_address_out)
|
||||
{
|
||||
// K^o_ext = k^o_g G + k^o_t T
|
||||
crypto::public_key sender_extension_pubkey;
|
||||
make_carrot_onetime_address_extension_pubkey(s_sender_receiver, amount_commitment, sender_extension_pubkey);
|
||||
|
||||
// Ko = K^j_s + K^o_ext
|
||||
onetime_address_out = rct::rct2pk(rct::addKeys(
|
||||
rct::pk2rct(address_spend_pubkey), rct::pk2rct(sender_extension_pubkey)));
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void make_carrot_amount_blinding_factor(const crypto::hash &s_sender_receiver,
|
||||
const rct::xmr_amount amount,
|
||||
const crypto::public_key &address_spend_pubkey,
|
||||
const CarrotEnoteType enote_type,
|
||||
crypto::secret_key &amount_blinding_factor_out)
|
||||
{
|
||||
// k_a = H_n(s^ctx_sr, a, K^j_s, enote_type)
|
||||
const auto transcript = sp::make_fixed_transcript<CARROT_DOMAIN_SEP_AMOUNT_BLINDING_FACTOR>(
|
||||
amount, address_spend_pubkey, static_cast<unsigned char>(enote_type));
|
||||
derive_scalar(transcript.data(), transcript.size(), &s_sender_receiver, &amount_blinding_factor_out);
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void make_carrot_anchor_encryption_mask(const crypto::hash &s_sender_receiver,
|
||||
const crypto::public_key &onetime_address,
|
||||
encrypted_janus_anchor_t &anchor_encryption_mask_out)
|
||||
{
|
||||
// m_anchor = H_16(s^ctx_sr, Ko)
|
||||
const auto transcript = sp::make_fixed_transcript<CARROT_DOMAIN_SEP_ENCRYPTION_MASK_ANCHOR>(onetime_address);
|
||||
derive_bytes_16(transcript.data(), transcript.size(), &s_sender_receiver, &anchor_encryption_mask_out);
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
encrypted_janus_anchor_t encrypt_carrot_anchor(const janus_anchor_t &anchor,
|
||||
const crypto::hash &s_sender_receiver,
|
||||
const crypto::public_key &onetime_address)
|
||||
{
|
||||
// m_anchor = H_16(s^ctx_sr, Ko)
|
||||
encrypted_janus_anchor_t mask;
|
||||
make_carrot_anchor_encryption_mask(s_sender_receiver, onetime_address, mask);
|
||||
|
||||
// anchor_enc = anchor XOR m_anchor
|
||||
return anchor ^ mask;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
janus_anchor_t decrypt_carrot_anchor(const encrypted_janus_anchor_t &encrypted_anchor,
|
||||
const crypto::hash &s_sender_receiver,
|
||||
const crypto::public_key &onetime_address)
|
||||
{
|
||||
// m_anchor = H_16(s^ctx_sr, Ko)
|
||||
encrypted_janus_anchor_t mask;
|
||||
make_carrot_anchor_encryption_mask(s_sender_receiver, onetime_address, mask);
|
||||
|
||||
// anchor = anchor_enc XOR m_anchor
|
||||
return encrypted_anchor ^ mask;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void make_carrot_amount_encryption_mask(const crypto::hash &s_sender_receiver,
|
||||
const crypto::public_key &onetime_address,
|
||||
encrypted_amount_t &amount_encryption_mask_out)
|
||||
{
|
||||
// m_a = H_8(s^ctx_sr, Ko)
|
||||
const auto transcript = sp::make_fixed_transcript<CARROT_DOMAIN_SEP_ENCRYPTION_MASK_AMOUNT>(onetime_address);
|
||||
derive_bytes_8(transcript.data(), transcript.size(), &s_sender_receiver, &amount_encryption_mask_out);
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
encrypted_amount_t encrypt_carrot_amount(const rct::xmr_amount amount,
|
||||
const crypto::hash &s_sender_receiver,
|
||||
const crypto::public_key &onetime_address)
|
||||
{
|
||||
// m_a = H_8(s^ctx_sr, Ko)
|
||||
encrypted_amount_t mask;
|
||||
make_carrot_amount_encryption_mask(s_sender_receiver, onetime_address, mask);
|
||||
|
||||
// a_enc = a XOR m_a [paying attention to system endianness]
|
||||
return enc_amount(amount, mask);
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
rct::xmr_amount decrypt_carrot_amount(const encrypted_amount_t encrypted_amount,
|
||||
const crypto::hash &s_sender_receiver,
|
||||
const crypto::public_key &onetime_address)
|
||||
{
|
||||
// m_a = H_8(s^ctx_sr, Ko)
|
||||
encrypted_amount_t mask;
|
||||
make_carrot_amount_encryption_mask(s_sender_receiver, onetime_address, mask);
|
||||
|
||||
// a = a_enc XOR m_a [paying attention to system endianness]
|
||||
return dec_amount(encrypted_amount, mask);
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void make_carrot_payment_id_encryption_mask(const crypto::hash &s_sender_receiver,
|
||||
const crypto::public_key &onetime_address,
|
||||
encrypted_payment_id_t &payment_id_encryption_mask_out)
|
||||
{
|
||||
// m_pid = H_8(s^ctx_sr, Ko)
|
||||
const auto transcript = sp::make_fixed_transcript<CARROT_DOMAIN_SEP_ENCRYPTION_MASK_PAYMENT_ID>(onetime_address);
|
||||
derive_bytes_8(transcript.data(), transcript.size(), &s_sender_receiver, &payment_id_encryption_mask_out);
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
encrypted_payment_id_t encrypt_legacy_payment_id(const payment_id_t payment_id,
|
||||
const crypto::hash &s_sender_receiver,
|
||||
const crypto::public_key &onetime_address)
|
||||
{
|
||||
// m_pid = H_8(s^ctx_sr, Ko)
|
||||
encrypted_payment_id_t mask;
|
||||
make_carrot_payment_id_encryption_mask(s_sender_receiver, onetime_address, mask);
|
||||
|
||||
// pid_enc = pid XOR m_pid
|
||||
return convert_payment_id(payment_id) ^ mask;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
payment_id_t decrypt_legacy_payment_id(const encrypted_payment_id_t encrypted_payment_id,
|
||||
const crypto::hash &s_sender_receiver,
|
||||
const crypto::public_key &onetime_address)
|
||||
{
|
||||
// m_pid = H_8(s^ctx_sr, Ko)
|
||||
encrypted_payment_id_t mask;
|
||||
make_carrot_payment_id_encryption_mask(s_sender_receiver, onetime_address, mask);
|
||||
|
||||
// pid = pid_enc XOR m_pid
|
||||
return convert_payment_id(encrypted_payment_id ^ mask);
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void make_carrot_janus_anchor_special(const mx25519_pubkey &enote_ephemeral_pubkey,
|
||||
const input_context_t &input_context,
|
||||
const crypto::public_key &onetime_address,
|
||||
const crypto::secret_key &k_view,
|
||||
janus_anchor_t &anchor_special_out)
|
||||
{
|
||||
// anchor_sp = H_16(D_e, input_context, Ko, k_v)
|
||||
const auto transcript = sp::make_fixed_transcript<CARROT_DOMAIN_SEP_JANUS_ANCHOR_SPECIAL>(
|
||||
enote_ephemeral_pubkey, input_context, onetime_address);
|
||||
derive_bytes_16(transcript.data(), transcript.size(), &k_view, &anchor_special_out);
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
void recover_address_spend_pubkey(const crypto::public_key &onetime_address,
|
||||
const crypto::hash &s_sender_receiver,
|
||||
const rct::key &amount_commitment,
|
||||
crypto::public_key &address_spend_key_out)
|
||||
{
|
||||
// K^o_ext = k^o_g G + k^o_t T
|
||||
crypto::public_key sender_extension_pubkey;
|
||||
make_carrot_onetime_address_extension_pubkey(s_sender_receiver, amount_commitment, sender_extension_pubkey);
|
||||
|
||||
// K^j_s = Ko - K^o_ext
|
||||
rct::key res_tmp;
|
||||
rct::subKeys(res_tmp, rct::pk2rct(onetime_address), rct::pk2rct(sender_extension_pubkey));
|
||||
address_spend_key_out = rct::rct2pk(res_tmp);
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
bool test_carrot_view_tag(const unsigned char s_sender_receiver_unctx[32],
|
||||
const input_context_t input_context,
|
||||
const crypto::public_key &onetime_address,
|
||||
const view_tag_t view_tag)
|
||||
{
|
||||
// vt' = H_3(s_sr || input_context || Ko)
|
||||
view_tag_t nominal_view_tag;
|
||||
make_carrot_view_tag(s_sender_receiver_unctx, input_context, onetime_address, nominal_view_tag);
|
||||
// vt' ?= vt
|
||||
return nominal_view_tag == view_tag;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
bool try_recompute_carrot_amount_commitment(const crypto::hash &s_sender_receiver,
|
||||
const rct::xmr_amount nominal_amount,
|
||||
const crypto::public_key &nominal_address_spend_pubkey,
|
||||
const CarrotEnoteType nominal_enote_type,
|
||||
const rct::key &amount_commitment,
|
||||
crypto::secret_key &amount_blinding_factor_out)
|
||||
{
|
||||
// k_a' = H_n(s^ctx_sr, a', K^j_s', enote_type')
|
||||
make_carrot_amount_blinding_factor(s_sender_receiver,
|
||||
nominal_amount,
|
||||
nominal_address_spend_pubkey,
|
||||
nominal_enote_type,
|
||||
amount_blinding_factor_out);
|
||||
|
||||
// C_a' = k_a' G + a' H
|
||||
const rct::key nominal_amount_commitment = rct::commit(nominal_amount, rct::sk2rct(amount_blinding_factor_out));
|
||||
|
||||
// C_a' ?= C_a
|
||||
return nominal_amount_commitment == amount_commitment;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
bool try_get_carrot_amount(const crypto::hash &s_sender_receiver,
|
||||
const encrypted_amount_t &encrypted_amount,
|
||||
const crypto::public_key &onetime_address,
|
||||
const crypto::public_key &address_spend_pubkey,
|
||||
const rct::key &amount_commitment,
|
||||
CarrotEnoteType &enote_type_out,
|
||||
rct::xmr_amount &amount_out,
|
||||
crypto::secret_key &amount_blinding_factor_out)
|
||||
{
|
||||
// a' = a_enc XOR m_a
|
||||
amount_out = decrypt_carrot_amount(encrypted_amount, s_sender_receiver, onetime_address);
|
||||
|
||||
// set enote_type <- "payment"
|
||||
enote_type_out = CarrotEnoteType::PAYMENT;
|
||||
|
||||
// if C_a ?= k_a' G + a' H, then PASS
|
||||
if (try_recompute_carrot_amount_commitment(s_sender_receiver,
|
||||
amount_out,
|
||||
address_spend_pubkey,
|
||||
enote_type_out,
|
||||
amount_commitment,
|
||||
amount_blinding_factor_out))
|
||||
return true;
|
||||
|
||||
// set enote_type <- "change"
|
||||
enote_type_out = CarrotEnoteType::CHANGE;
|
||||
|
||||
// if C_a ?= k_a' G + a' H, then PASS
|
||||
if (try_recompute_carrot_amount_commitment(s_sender_receiver,
|
||||
amount_out,
|
||||
address_spend_pubkey,
|
||||
enote_type_out,
|
||||
amount_commitment,
|
||||
amount_blinding_factor_out))
|
||||
return true;
|
||||
|
||||
// neither attempt at recomputing passed: so FAIL
|
||||
return false;
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
bool verify_carrot_normal_janus_protection(const janus_anchor_t &nominal_anchor,
|
||||
const input_context_t &input_context,
|
||||
const crypto::public_key &nominal_address_spend_pubkey,
|
||||
const bool is_subaddress,
|
||||
const payment_id_t nominal_payment_id,
|
||||
const mx25519_pubkey &enote_ephemeral_pubkey)
|
||||
{
|
||||
// d_e' = H_n(anchor_norm, input_context, K^j_s, pid))
|
||||
crypto::secret_key nominal_enote_ephemeral_privkey;
|
||||
make_carrot_enote_ephemeral_privkey(nominal_anchor,
|
||||
input_context,
|
||||
nominal_address_spend_pubkey,
|
||||
nominal_payment_id,
|
||||
nominal_enote_ephemeral_privkey);
|
||||
|
||||
// recompute D_e' for d_e' and address type
|
||||
mx25519_pubkey nominal_enote_ephemeral_pubkey;
|
||||
make_carrot_enote_ephemeral_pubkey(nominal_enote_ephemeral_privkey,
|
||||
nominal_address_spend_pubkey,
|
||||
is_subaddress,
|
||||
nominal_enote_ephemeral_pubkey);
|
||||
|
||||
// D_e' ?= D_e
|
||||
return 0 == memcmp(&nominal_enote_ephemeral_pubkey, &enote_ephemeral_pubkey, sizeof(mx25519_pubkey));
|
||||
}
|
||||
//-------------------------------------------------------------------------------------------------------------------
|
||||
} //namespace carrot
|
||||
@@ -0,0 +1,453 @@
|
||||
// Copyright (c) 2024, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// @file Utilities for making and handling enotes with carrot.
|
||||
|
||||
#pragma once
|
||||
|
||||
//local headers
|
||||
#include "crypto/crypto.h"
|
||||
#include "core_types.h"
|
||||
#include "mx25519.h"
|
||||
#include "ringct/rctTypes.h"
|
||||
#include "device.h"
|
||||
|
||||
//third party headers
|
||||
|
||||
//standard headers
|
||||
|
||||
//forward declarations
|
||||
|
||||
namespace carrot
|
||||
{
|
||||
|
||||
/**
|
||||
* brief: make_carrot_enote_ephemeral_privkey - enote ephemeral privkey k_e for Carrot enotes
|
||||
* d_e = H_n(anchor_norm, input_context, K^j_s, pid))
|
||||
* param: anchor_norm - anchor_norm
|
||||
* param: input_context - input_context
|
||||
* param: address_spend_pubkey - K^j_s
|
||||
* param: payment_id - pid
|
||||
* outparam: enote_ephemeral_privkey_out - k_e
|
||||
*/
|
||||
void make_carrot_enote_ephemeral_privkey(const janus_anchor_t &anchor_norm,
|
||||
const input_context_t &input_context,
|
||||
const crypto::public_key &address_spend_pubkey,
|
||||
const payment_id_t payment_id,
|
||||
crypto::secret_key &enote_ephemeral_privkey_out);
|
||||
/**
|
||||
* brief: make_carrot_enote_ephemeral_pubkey_main - make enote ephemeral pubkey D_e for a main address
|
||||
* D_e = d_e B
|
||||
* param: enote_ephemeral_privkey - d_e
|
||||
* outparam: enote_ephemeral_pubkey_out - D_e
|
||||
*/
|
||||
void make_carrot_enote_ephemeral_pubkey_cryptonote(const crypto::secret_key &enote_ephemeral_privkey,
|
||||
mx25519_pubkey &enote_ephemeral_pubkey_out);
|
||||
/**
|
||||
* brief: make_carrot_enote_ephemeral_pubkey_subaddress - make enote ephemeral pubkey D_e for a subaddress
|
||||
* D_e = d_e ConvertPointE(K^j_s)
|
||||
* param: enote_ephemeral_privkey - d_e
|
||||
* param: address_spend_pubkey - K^j_s
|
||||
* outparam: enote_ephemeral_pubkey_out - D_e
|
||||
*/
|
||||
void make_carrot_enote_ephemeral_pubkey_subaddress(const crypto::secret_key &enote_ephemeral_privkey,
|
||||
const crypto::public_key &address_spend_pubkey,
|
||||
mx25519_pubkey &enote_ephemeral_pubkey_out);
|
||||
/**
|
||||
* brief: make_carrot_enote_ephemeral_pubkey - make enote ephemeral pubkey D_e for either either address type
|
||||
* [is_subaddress]: D_e = d_e ConvertPointE(K^j_s)
|
||||
* [!is_subaddress]: D_e = d_e B
|
||||
* param: enote_ephemeral_privkey - d_e
|
||||
* param: address_spend_pubkey - K^j_s
|
||||
* param: is_subaddress -
|
||||
* outparam: enote_ephemeral_pubkey_out - D_e
|
||||
*/
|
||||
void make_carrot_enote_ephemeral_pubkey(const crypto::secret_key &enote_ephemeral_privkey,
|
||||
const crypto::public_key &address_spend_pubkey,
|
||||
const bool is_subaddress,
|
||||
mx25519_pubkey &enote_ephemeral_pubkey_out);
|
||||
/**
|
||||
* brief: make_carrot_uncontextualized_shared_key_receiver - perform the receiver-side ECDH exchange for Carrot enotes
|
||||
* s_sr = k_v D_e
|
||||
* param: k_view - k_v
|
||||
* param: enote_ephemeral_pubkey - D_e
|
||||
* outparam: s_sender_receiver_unctx_out - s_sr
|
||||
* return: true if successful, false if a failure occurred in point decompression
|
||||
*/
|
||||
bool make_carrot_uncontextualized_shared_key_receiver(const crypto::secret_key &k_view,
|
||||
const mx25519_pubkey &enote_ephemeral_pubkey,
|
||||
mx25519_pubkey &s_sender_receiver_unctx_out);
|
||||
/**
|
||||
* brief: make_carrot_uncontextualized_shared_key_sender - perform the sender-side ECDH exchange for Carrot enotes
|
||||
* s_sr = d_e ConvertPointE(K^j_v)
|
||||
* param: enote_ephemeral_privkey - d_e
|
||||
* param: address_view_pubkey - K^j_v
|
||||
* outparam: s_sender_receiver_unctx_out - s_sr
|
||||
* return: true if successful, false if a failure occurred in point decompression
|
||||
*/
|
||||
bool make_carrot_uncontextualized_shared_key_sender(const crypto::secret_key &enote_ephemeral_privkey,
|
||||
const crypto::public_key &address_view_pubkey,
|
||||
mx25519_pubkey &s_sender_receiver_unctx_out);
|
||||
/**
|
||||
* brief: make_carrot_view_tag - used for optimized identification of enotes
|
||||
* vt = H_3(s_sr || input_context || Ko)
|
||||
* param: s_sender_receiver_unctx - s_sr
|
||||
* param: input_context - input_context
|
||||
* param: onetime_address - Ko
|
||||
* outparam: view_tag_out - vt
|
||||
*/
|
||||
void make_carrot_view_tag(const unsigned char s_sender_receiver_unctx[32],
|
||||
const input_context_t &input_context,
|
||||
const crypto::public_key &onetime_address,
|
||||
view_tag_t &view_tag_out);
|
||||
/**
|
||||
* brief: make_sparc_return_privkey - return private key, given non-secret data
|
||||
* k_return = H_32(s_sr || input_context || Ko)
|
||||
* param: s_sender_receiver_unctx - s_sr
|
||||
* param: input_context - input_context
|
||||
* param: onetime_address - Ko
|
||||
* outparam: return_privkey_out - k_return
|
||||
*/
|
||||
void make_sparc_return_privkey(const unsigned char s_sender_receiver_unctx[32],
|
||||
const input_context_t &input_context,
|
||||
const crypto::public_key &onetime_address,
|
||||
crypto::secret_key &return_privkey_out);
|
||||
/**
|
||||
* brief: make_sparc_return_index - return index, given non-secret data
|
||||
* m_return = H_32(s_sr || input_context || Ko || idx)
|
||||
* param: s_sender_receiver_unctx - s_sr
|
||||
* param: input_context - input_context
|
||||
* param: onetime_address - Ko
|
||||
* param: idx - idx
|
||||
* outparam: return_index_out - m_return
|
||||
*/
|
||||
void make_sparc_return_index(const unsigned char s_sender_receiver_unctx[32],
|
||||
const input_context_t &input_context,
|
||||
const crypto::public_key &onetime_address,
|
||||
const uint64_t idx,
|
||||
crypto::secret_key &return_index_out);
|
||||
/**
|
||||
* brief: make_sparc_return_pubkey_encryption_mask - used for hiding return pubkey
|
||||
* m_return = H_32(s_sr || input_context || Ko)
|
||||
* param: s_sender_receiver_unctx - s_sr
|
||||
* param: input_context - input_context
|
||||
* param: onetime_address - Ko
|
||||
* outparam: return_pubkey_mask_out - m_return
|
||||
*/
|
||||
void make_sparc_return_pubkey_encryption_mask(const unsigned char s_sender_receiver_unctx[32],
|
||||
const input_context_t &input_context,
|
||||
const crypto::public_key &onetime_address,
|
||||
encrypted_return_pubkey_t &return_pubkey_mask_out);
|
||||
|
||||
/**
|
||||
* brief: make_sparc_return_pubkey - construct the return pubkey
|
||||
* param: s_sender_receiver_unctx - s_sr
|
||||
* param: input_context - input_context
|
||||
* param: s_view_balance_dev - s_vb
|
||||
* param: onetime_address - Ko
|
||||
* outparam: return_pubkey_mask_out - K_return
|
||||
*/
|
||||
void make_sparc_return_pubkey(const unsigned char s_sender_receiver_unctx[32],
|
||||
const input_context_t &input_context,
|
||||
const view_balance_secret_device *s_view_balance_dev,
|
||||
const crypto::public_key &onetime_address,
|
||||
const uint64_t idx,
|
||||
encrypted_return_pubkey_t &return_pubkey_out);
|
||||
/**
|
||||
* brief: make_carrot_input_context_coinbase - input context for a sender-receiver secret (coinbase txs)
|
||||
* input_context = "C" || IntToBytes256(block_index)
|
||||
* param: block_index - block index of the coinbase tx
|
||||
* return: input_context
|
||||
*/
|
||||
input_context_t make_carrot_input_context_coinbase(const std::uint64_t block_index);
|
||||
/**
|
||||
* brief: make_carrot_input_context - input context for a sender-receiver secret (standard RingCT txs)
|
||||
* input_context = "R" || KI_1
|
||||
* param: first_rct_key_image - KI_1, the first spent RingCT key image in a tx
|
||||
* return: input_context
|
||||
*/
|
||||
input_context_t make_carrot_input_context(const crypto::key_image &first_rct_key_image);
|
||||
/**
|
||||
* brief: make_carrot_sender_receiver_secret - contextualized sender-receiver secret s^ctx_sr
|
||||
* s^ctx_sr = H_32(s_sr, D_e, input_context)
|
||||
* param: s_sender_receiver_unctx - s_sr
|
||||
* param: enote_ephemeral_pubkey - D_e
|
||||
* param: input_context - [standard: KI_1] [coinbase: block index]
|
||||
* outparam: s_sender_receiver_out - s^ctx_sr
|
||||
* - note: this is 'crypto::hash' instead of 'crypto::secret_key' for better performance in multithreaded environments
|
||||
*/
|
||||
void make_carrot_sender_receiver_secret(const unsigned char s_sender_receiver_unctx[32],
|
||||
const mx25519_pubkey &enote_ephemeral_pubkey,
|
||||
const input_context_t &input_context,
|
||||
crypto::hash &s_sender_receiver_out);
|
||||
/**
|
||||
* brief: make_carrot_onetime_address_extension_g - extension for transforming a receiver's spendkey into an
|
||||
* enote one-time address
|
||||
* k^o_g = H_n("..g..", s^ctx_sr, C_a)
|
||||
* param: s_sender_receiver - s^ctx_sr
|
||||
* param: amount_commitment - C_a
|
||||
* outparam: sender_extension_out - k^o_g
|
||||
*/
|
||||
void make_carrot_onetime_address_extension_g(const crypto::hash &s_sender_receiver,
|
||||
const rct::key &amount_commitment,
|
||||
crypto::secret_key &sender_extension_out);
|
||||
/**
|
||||
* brief: make_carrot_onetime_address_extension_t - extension for transforming a receiver's spendkey into an
|
||||
* enote one-time address
|
||||
* k^o_t = H_n("..t..", s^ctx_sr, C_a)
|
||||
* param: s_sender_receiver - s^ctx_sr
|
||||
* param: amount_commitment - C_a
|
||||
* outparam: sender_extension_out - k^o_t
|
||||
*/
|
||||
void make_carrot_onetime_address_extension_t(const crypto::hash &s_sender_receiver,
|
||||
const rct::key &amount_commitment,
|
||||
crypto::secret_key &sender_extension_out);
|
||||
/**
|
||||
* brief: make_carrot_onetime_address_extension_pubkey - create a FCMP++ onetime address extension pubkey
|
||||
* K^o_ext = k^o_g G + k^o_t T
|
||||
* param: s_sender_receiver - s^ctx_sr
|
||||
* param: amount_commitment - C_a
|
||||
* outparam: sender_extension_pubkey_out - K^o_ext
|
||||
*/
|
||||
void make_carrot_onetime_address_extension_pubkey(const crypto::hash &s_sender_receiver,
|
||||
const rct::key &amount_commitment,
|
||||
crypto::public_key &sender_extension_pubkey_out);
|
||||
/**
|
||||
* brief: make_carrot_onetime_address - create a FCMP++ onetime address
|
||||
* Ko = K^j_s + K^o_ext = K^j_s + (k^o_g G + k^o_t T)
|
||||
* param: address_spend_pubkey - K^j_s
|
||||
* param: s_sender_receiver - s^ctx_sr
|
||||
* param: amount_commitment - C_a
|
||||
* outparam: onetime_address_out - Ko
|
||||
*/
|
||||
void make_carrot_onetime_address(const crypto::public_key &address_spend_pubkey,
|
||||
const crypto::hash &s_sender_receiver,
|
||||
const rct::key &amount_commitment,
|
||||
crypto::public_key &onetime_address_out);
|
||||
/**
|
||||
* brief: make_carrot_amount_blinding_factor - create blinding factor for enote's amount commitment C_a
|
||||
* k_a = H_n(s^ctx_sr, a, K^j_s, enote_type)
|
||||
* param: s_sender_receiver - s^ctx_sr
|
||||
* param: amount - a
|
||||
* param: address_spend_pubkey - K^j_s
|
||||
* param: enote_type - enote_type
|
||||
* outparam: amount_blinding_factor_out - k_a
|
||||
*/
|
||||
void make_carrot_amount_blinding_factor(const crypto::hash &s_sender_receiver,
|
||||
const rct::xmr_amount amount,
|
||||
const crypto::public_key &address_spend_pubkey,
|
||||
const CarrotEnoteType enote_type,
|
||||
crypto::secret_key &amount_blinding_factor_out);
|
||||
/**
|
||||
* brief: make_carrot_anchor_encryption_mask - create XOR encryption mask for enote's anchor
|
||||
* m_anchor = H_16(s^ctx_sr, Ko)
|
||||
* param: s_sender_receiver - s^ctx_sr
|
||||
* param: onetime_address - Ko
|
||||
* outparam: anchor_encryption_mask_out - m_anchor
|
||||
*/
|
||||
void make_carrot_anchor_encryption_mask(const crypto::hash &s_sender_receiver,
|
||||
const crypto::public_key &onetime_address,
|
||||
encrypted_janus_anchor_t &anchor_encryption_mask_out);
|
||||
/**
|
||||
* brief: encrypt_carrot_anchor - encrypt a Janus anchor for an enote
|
||||
* anchor_enc = anchor XOR m_anchor
|
||||
* param: anchor -
|
||||
* param: s_sender_receiver - s^ctx_sr
|
||||
* param: onetime_address - Ko
|
||||
* return: anchor_enc
|
||||
*/
|
||||
encrypted_janus_anchor_t encrypt_carrot_anchor(const janus_anchor_t &anchor,
|
||||
const crypto::hash &s_sender_receiver,
|
||||
const crypto::public_key &onetime_address);
|
||||
/**
|
||||
* brief: decrypt_carrot_address_tag - decrypt a Janus anchor from an enote
|
||||
* anchor = anchor_enc XOR m_anchor
|
||||
* param: encrypted_anchor - anchor_enc
|
||||
* param: s_sender_receiver - s^ctx_sr
|
||||
* param: onetime_address - Ko
|
||||
* return: anchor
|
||||
*/
|
||||
janus_anchor_t decrypt_carrot_anchor(const encrypted_janus_anchor_t &encrypted_anchor,
|
||||
const crypto::hash &s_sender_receiver,
|
||||
const crypto::public_key &onetime_address);
|
||||
/**
|
||||
* brief: make_carrot_amount_encryption_mask - create XOR encryption mask for enote's amount
|
||||
* m_a = H_8(s^ctx_sr, Ko)
|
||||
* param: s_sender_receiver - s^ctx_sr
|
||||
* param: onetime_address - Ko
|
||||
* outparam: amount_encryption_mask_out - m_a
|
||||
*/
|
||||
void make_carrot_amount_encryption_mask(const crypto::hash &s_sender_receiver,
|
||||
const crypto::public_key &onetime_address,
|
||||
encrypted_amount_t &amount_encryption_mask_out);
|
||||
/**
|
||||
* brief: encrypt_carrot_amount - encrypt an amount for an enote
|
||||
* a_enc = a XOR m_a
|
||||
* param: amount - a
|
||||
* param: s_sender_receiver - s^ctx_sr
|
||||
* param: onetime_address - Ko
|
||||
* return: a_enc
|
||||
*/
|
||||
encrypted_amount_t encrypt_carrot_amount(const rct::xmr_amount amount,
|
||||
const crypto::hash &s_sender_receiver,
|
||||
const crypto::public_key &onetime_address);
|
||||
/**
|
||||
* brief: decrypt_carrot_amount - decrypt an amount from an enote
|
||||
* a = a_enc XOR m_a
|
||||
* param: encrypted_amount - a_enc
|
||||
* param: s_sender_receiver - s^ctx_sr
|
||||
* param: onetime_address - Ko
|
||||
* return: a
|
||||
*/
|
||||
rct::xmr_amount decrypt_carrot_amount(const encrypted_amount_t encrypted_amount,
|
||||
const crypto::hash &s_sender_receiver,
|
||||
const crypto::public_key &onetime_address);
|
||||
/**
|
||||
* brief: make_carrot_payment_id_encryption_mask - create XOR encryption mask for enote's payment ID
|
||||
* m_pid = H_8(s^ctx_sr, Ko)
|
||||
* param: s_sender_receiver - s^ctx_sr
|
||||
* param: onetime_address - Ko
|
||||
* outparam: payment_id_encryption_mask_out - m_pid
|
||||
*/
|
||||
void make_carrot_payment_id_encryption_mask(const crypto::hash &s_sender_receiver,
|
||||
const crypto::public_key &onetime_address,
|
||||
encrypted_payment_id_t &payment_id_encryption_mask_out);
|
||||
/**
|
||||
* brief: encrypt_legacy_payment_id - encrypt a payment ID from an enote
|
||||
* pid_enc = pid XOR m_pid
|
||||
* param: payment_id - pid
|
||||
* param: s_sender_receiver - s^ctx_sr
|
||||
* param: onetime_address - Ko
|
||||
* return: pid_enc
|
||||
*/
|
||||
encrypted_payment_id_t encrypt_legacy_payment_id(const payment_id_t payment_id,
|
||||
const crypto::hash &s_sender_receiver,
|
||||
const crypto::public_key &onetime_address);
|
||||
/**
|
||||
* brief: decrypt_legacy_payment_id - decrypt a payment ID from an enote
|
||||
* pid = pid_enc XOR m_pid
|
||||
* param: encrypted_payment_id - pid_enc
|
||||
* param: s_sender_receiver - s^ctx_sr
|
||||
* param: onetime_address - Ko
|
||||
* return: pid
|
||||
*/
|
||||
payment_id_t decrypt_legacy_payment_id(const encrypted_payment_id_t encrypted_payment_id,
|
||||
const crypto::hash &s_sender_receiver,
|
||||
const crypto::public_key &onetime_address);
|
||||
/**
|
||||
* brief: make_carrot_janus_anchor_special - make a janus anchor for "special" enotes
|
||||
* anchor_sp = H_16(D_e, input_context, Ko, k_v)
|
||||
* param: enote_ephemeral_pubkey - D_e
|
||||
* param: input_context -
|
||||
* param: onetime_address - Ko
|
||||
* param: k_view - k_v
|
||||
* outparam: anchor_special_out - anchor_sp
|
||||
*/
|
||||
void make_carrot_janus_anchor_special(const mx25519_pubkey &enote_ephemeral_pubkey,
|
||||
const input_context_t &input_context,
|
||||
const crypto::public_key &onetime_address,
|
||||
const crypto::secret_key &k_view,
|
||||
janus_anchor_t &anchor_special_out);
|
||||
/**
|
||||
* brief: recover_address_spend_pubkey - get the receiver's spend key for which this RingCT onetime address
|
||||
* can be reconstructed as 'owned' by
|
||||
* K^j_s = Ko - K^o_ext = Ko - (k^o_g G + k^o_t U)
|
||||
* param: onetime_address - Ko
|
||||
* param: s_sender_receiver - s^ctx_sr
|
||||
* param: amount_commitment - C_a
|
||||
* outparam: address_spend_key_out: - K^j_s
|
||||
*/
|
||||
void recover_address_spend_pubkey(const crypto::public_key &onetime_address,
|
||||
const crypto::hash &s_sender_receiver,
|
||||
const rct::key &amount_commitment,
|
||||
crypto::public_key &address_spend_key_out);
|
||||
/**
|
||||
* brief: test_carrot_view_tag - test carrot view tag
|
||||
* param: s_sender_receiver_unctx - s_sr
|
||||
* param: input_context -
|
||||
* param: onetime_address - Ko
|
||||
* param: view_tag - vt
|
||||
* return: true if successfully recomputed the view tag
|
||||
*/
|
||||
bool test_carrot_view_tag(const unsigned char s_sender_receiver_unctx[32],
|
||||
const input_context_t input_context,
|
||||
const crypto::public_key &onetime_address,
|
||||
const view_tag_t view_tag);
|
||||
/**
|
||||
* brief: try_recompute_carrot_amount_commitment - test recreating the amount commitment for given enote_type and amount
|
||||
* param: s_sender_receiver - s^ctx_sr
|
||||
* param: nominal_amount - a'
|
||||
* param: nominal_address_spend_pubkey - K^j_s'
|
||||
* param: nominal_enote_type - enote_type'
|
||||
* param: amount_commitment - C_a
|
||||
* outparam: amount_blinding_factor_out - k_a' = H_n(s^ctx_sr, enote_type')
|
||||
* return: true if successfully recomputed the amount commitment (C_a ?= k_a' G + a' H)
|
||||
*/
|
||||
bool try_recompute_carrot_amount_commitment(const crypto::hash &s_sender_receiver,
|
||||
const rct::xmr_amount nominal_amount,
|
||||
const crypto::public_key &nominal_address_spend_pubkey,
|
||||
const CarrotEnoteType nominal_enote_type,
|
||||
const rct::key &amount_commitment,
|
||||
crypto::secret_key &amount_blinding_factor_out);
|
||||
/**
|
||||
* brief: try_get_amount - test decrypting the amount and recomputing the amount commitment
|
||||
* param: s_sender_receiver - s^ctx_sr
|
||||
* param: encrypted_amount - a_enc
|
||||
* param: onetime_address - Ko
|
||||
* param: address_spend_pubkey - K^j_s
|
||||
* param: amount_commitment - C_a
|
||||
* outparam: enote_type_out - enote_type'
|
||||
* outparam: amount_out - a' = a_enc XOR m_a
|
||||
* outparam: amount_blinding_factor_out - k_a' = H_n(s^ctx_sr, enote_type')
|
||||
* return: true if successfully recomputed the amount commitment (C_a ?= k_a' G + a' H)
|
||||
*/
|
||||
bool try_get_carrot_amount(const crypto::hash &s_sender_receiver,
|
||||
const encrypted_amount_t &encrypted_amount,
|
||||
const crypto::public_key &onetime_address,
|
||||
const crypto::public_key &address_spend_pubkey,
|
||||
const rct::key &amount_commitment,
|
||||
CarrotEnoteType &enote_type_out,
|
||||
rct::xmr_amount &amount_out,
|
||||
crypto::secret_key &amount_blinding_factor_out);
|
||||
/**
|
||||
* brief: verify_carrot_normal_janus_protection - check normal external enote is Janus safe (i.e. can recompute D_e)
|
||||
* param: nominal_anchor - anchor'
|
||||
* param: input_context -
|
||||
* param: nominal_address_spend_pubkey - K^j_s'
|
||||
* param: is_subaddress -
|
||||
* param: nominal_payment_id - pid'
|
||||
* param: enote_ephemeral_pubkey - D_e
|
||||
* return: true if this normal external enote is safe from Janus attacks
|
||||
*/
|
||||
bool verify_carrot_normal_janus_protection(const janus_anchor_t &nominal_anchor,
|
||||
const input_context_t &input_context,
|
||||
const crypto::public_key &nominal_address_spend_pubkey,
|
||||
const bool is_subaddress,
|
||||
const payment_id_t nominal_payment_id,
|
||||
const mx25519_pubkey &enote_ephemeral_pubkey);
|
||||
} //namespace carrot
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user