diff --git a/.docker/Dockerfile.ci-container b/.docker/Dockerfile.ci-container index c56e686888..77f68f166b 100644 --- a/.docker/Dockerfile.ci-container +++ b/.docker/Dockerfile.ci-container @@ -1,4 +1,4 @@ -FROM docker.io/debian:buster-slim +FROM docker.io/debian:bullseye-slim MAINTAINER Onur Özkan diff --git a/.github/workflows/dev-build.yml b/.github/workflows/dev-build.yml index 0849cca89a..8fb32b9c73 100644 --- a/.github/workflows/dev-build.yml +++ b/.github/workflows/dev-build.yml @@ -115,6 +115,12 @@ jobs: - name: Build run: cargo build --release --target x86_64-apple-darwin + - name: Upload build for next job + uses: actions/upload-artifact@v4 + with: + name: x86_64-apple-darwin-release-kdf + path: target/x86_64-apple-darwin/release/kdf + - name: Compress kdf build output env: AVAILABLE: ${{ secrets.FILE_SERVER_KEY }} @@ -167,6 +173,12 @@ jobs: - name: Build run: cargo build --release --target aarch64-apple-darwin + - name: Upload build for next job + uses: actions/upload-artifact@v4 + with: + name: aarch64-apple-darwin-release-kdf + path: target/aarch64-apple-darwin/release/kdf + - name: Compress kdf build output env: AVAILABLE: ${{ secrets.FILE_SERVER_KEY }} @@ -189,6 +201,70 @@ jobs: SAFE_BRANCH_NAME=$(echo "$BRANCH_NAME" | tr '/' '-') python3 ./scripts/ci/upload_artifact.py "$SAFE_BRANCH_NAME" "/uploads/$SAFE_BRANCH_NAME" + mac-universal: + timeout-minutes: 60 + runs-on: macos-latest + needs: [mac-x86-64, mac-arm64] + steps: + - uses: actions/checkout@v3 + + - name: Install build deps + uses: ./.github/actions/deps-install + with: + deps: ('protoc', 'python3', 'paramiko') + + - name: Calculate build tag (commit hash) for PR commit + if: github.event_name == 'pull_request' + run: echo "KDF_BUILD_TAG=$(git rev-parse --short=7 ${{ github.event.pull_request.head.sha }})" >> $GITHUB_ENV + + - name: Calculate build tag (commit hash) for merge commit + if: github.event_name != 'pull_request' + run: echo "KDF_BUILD_TAG=$(git rev-parse --short=7 HEAD)" >> $GITHUB_ENV + + - name: Download macos x86_64 build + uses: actions/download-artifact@v5 + with: + name: x86_64-apple-darwin-release-kdf + path: target/x86_64-apple-darwin/release + + - name: Download macos aarch64 build + uses: actions/download-artifact@v5 + with: + name: aarch64-apple-darwin-release-kdf + path: target/aarch64-apple-darwin/release + + - name: Make universal kdf build output + run: | + AARCH64_BIN="target/aarch64-apple-darwin/release/kdf" + X86_64_BIN="target/x86_64-apple-darwin/release/kdf" + OUT_DIR="target/universal-apple-darwin/release" + OUT_BIN="$OUT_DIR/kdf" + mkdir -p "$OUT_DIR" + lipo -create "$AARCH64_BIN" "$X86_64_BIN" -output "$OUT_BIN" + lipo -info "$OUT_BIN" + + - name: Compress kdf build output + env: + AVAILABLE: ${{ secrets.FILE_SERVER_KEY }} + if: ${{ env.AVAILABLE != '' }} + run: | + NAME="kdf_$KDF_BUILD_TAG-mac-universal.zip" + zip $NAME target/universal-apple-darwin/release/kdf -j + SAFE_DIR_NAME=$(echo "$BRANCH_NAME" | tr '/' '-') + mkdir $SAFE_DIR_NAME + mv $NAME ./$SAFE_DIR_NAME/ + + - name: Upload build artifact + env: + FILE_SERVER_HOST: ${{ secrets.FILE_SERVER_HOST }} + FILE_SERVER_USERNAME: ${{ secrets.FILE_SERVER_USERNAME }} + FILE_SERVER_PORT: ${{ secrets.FILE_SERVER_PORT }} + FILE_SERVER_KEY: ${{ secrets.FILE_SERVER_KEY }} + if: ${{ env.FILE_SERVER_KEY != '' }} + run: | + SAFE_BRANCH_NAME=$(echo "$BRANCH_NAME" | tr '/' '-') + python3 ./scripts/ci/upload_artifact.py "$SAFE_BRANCH_NAME" "/uploads/$SAFE_BRANCH_NAME" + win-x86-64: timeout-minutes: 60 runs-on: windows-latest diff --git a/.github/workflows/release-build.yml b/.github/workflows/release-build.yml index 75e9262b55..077ffb37b8 100644 --- a/.github/workflows/release-build.yml +++ b/.github/workflows/release-build.yml @@ -89,6 +89,7 @@ jobs: run: | rustup toolchain install nightly-2023-06-01 --no-self-update --profile=minimal rustup default nightly-2023-06-01 + rustup target add x86_64-apple-darwin - name: Install build deps uses: ./.github/actions/deps-install @@ -109,6 +110,12 @@ jobs: - name: Build run: cargo build --release --target x86_64-apple-darwin + - name: Upload build for next job + uses: actions/upload-artifact@v4 + with: + name: x86_64-apple-darwin-release-kdf + path: target/x86_64-apple-darwin/release/kdf + - name: Compress kdf build output run: | NAME="kdf_$KDF_BUILD_TAG-mac-x86-64.zip" @@ -158,6 +165,12 @@ jobs: - name: Build run: cargo build --release --target aarch64-apple-darwin + - name: Upload build for next job + uses: actions/upload-artifact@v4 + with: + name: aarch64-apple-darwin-release-kdf + path: target/aarch64-apple-darwin/release/kdf + - name: Compress kdf build output run: | NAME="kdf_$KDF_BUILD_TAG-mac-arm64.zip" @@ -177,6 +190,70 @@ jobs: SAFE_BRANCH_NAME=$(echo "$BRANCH_NAME" | tr '/' '-') python3 ./scripts/ci/upload_artifact.py "$SAFE_BRANCH_NAME" "/uploads/$SAFE_BRANCH_NAME" + mac-universal: + timeout-minutes: 60 + runs-on: macos-latest + needs: [mac-x86-64, mac-arm64] + steps: + - uses: actions/checkout@v3 + + - name: Install build deps + uses: ./.github/actions/deps-install + with: + deps: ('protoc', 'python3', 'paramiko') + + - name: Calculate build tag (commit hash) for PR commit + if: github.event_name == 'pull_request' + run: echo "KDF_BUILD_TAG=$(git rev-parse --short=7 ${{ github.event.pull_request.head.sha }})" >> $GITHUB_ENV + + - name: Calculate build tag (commit hash) for merge commit + if: github.event_name != 'pull_request' + run: echo "KDF_BUILD_TAG=$(git rev-parse --short=7 HEAD)" >> $GITHUB_ENV + + - name: Download macos x86_64 build + uses: actions/download-artifact@v5 + with: + name: x86_64-apple-darwin-release-kdf + path: target/x86_64-apple-darwin/release + + - name: Download macos aarch64 build + uses: actions/download-artifact@v5 + with: + name: aarch64-apple-darwin-release-kdf + path: target/aarch64-apple-darwin/release + + - name: Make universal kdf build output + run: | + AARCH64_BIN="target/aarch64-apple-darwin/release/kdf" + X86_64_BIN="target/x86_64-apple-darwin/release/kdf" + OUT_DIR="target/universal-apple-darwin/release" + OUT_BIN="$OUT_DIR/kdf" + mkdir -p "$OUT_DIR" + lipo -create "$AARCH64_BIN" "$X86_64_BIN" -output "$OUT_BIN" + lipo -info "$OUT_BIN" + + - name: Compress kdf build output + env: + AVAILABLE: ${{ secrets.FILE_SERVER_KEY }} + if: ${{ env.AVAILABLE != '' }} + run: | + NAME="kdf_$KDF_BUILD_TAG-mac-universal.zip" + zip $NAME target/universal-apple-darwin/release/kdf -j + SAFE_DIR_NAME=$(echo "$BRANCH_NAME" | tr '/' '-') + mkdir $SAFE_DIR_NAME + mv $NAME ./$SAFE_DIR_NAME/ + + - name: Upload build artifact + env: + FILE_SERVER_HOST: ${{ secrets.FILE_SERVER_HOST }} + FILE_SERVER_USERNAME: ${{ secrets.FILE_SERVER_USERNAME }} + FILE_SERVER_PORT: ${{ secrets.FILE_SERVER_PORT }} + FILE_SERVER_KEY: ${{ secrets.FILE_SERVER_KEY }} + if: ${{ env.FILE_SERVER_KEY != '' }} + run: | + SAFE_BRANCH_NAME=$(echo "$BRANCH_NAME" | tr '/' '-') + python3 ./scripts/ci/upload_artifact.py "$SAFE_BRANCH_NAME" "/uploads/$SAFE_BRANCH_NAME" + win-x86-64: timeout-minutes: 60 runs-on: windows-latest diff --git a/CHANGELOG.md b/CHANGELOG.md index 831bc7bc68..7cea925f22 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,33 @@ +## v2.5.2-beta - 2025-10-10 + +### Enhancements/Fixes: + +**Swap Stats DB**: +- Swap status broadcasting was enabled for privacy coins with the persistent pubkey hidden (set to zeros) to maintain user privacy. [#2648](https://github.com/KomodoPlatform/komodo-defi-framework/pull/2648) +- Stats database now correctly stores persistent pubkeys for both maker and taker instead of incorrectly storing htlc pubkeys in some cases. [#2648](https://github.com/KomodoPlatform/komodo-defi-framework/pull/2648) + +**ARRR/Pirate**: +- The `get_nullifiers` function for Zcoin WASM build is now aligned with its sqlite counterpart to return nullifiers for both unspent notes and notes with unconfirmed spends, fixing the `spent_by_me` field in transaction history and balance calculations. [#2651](https://github.com/KomodoPlatform/komodo-defi-framework/pull/2651) + +**Metrics**: +- The `memory_db` size metric that relied on `parity-util-mem::malloc_size` was removed because it intermittently segfaulted on Linux due to allocator conflicts. [#2632](https://github.com/KomodoPlatform/komodo-defi-framework/pull/2632) + +**Build and Dependency Management**: +- A CI job was added to build macOS Universal2 artifacts for KDF, this combines `x86_64-apple-darwin` and `aarch64-apple-darwin` binaries via `lipo` to produce a single binary that runs natively on both Intel and Apple Silicon. The universal binary is uploaded as `kdf_-mac-universal.zip`. [#2628](https://github.com/KomodoPlatform/komodo-defi-framework/pull/2628) +- The `parity-util-mem` dependency was removed. [#2632](https://github.com/KomodoPlatform/komodo-defi-framework/pull/2632) +- CI container base image was bumped to `debian:bullseye-slim` [#2534](https://github.com/KomodoPlatform/komodo-defi-framework/pull/2534) [#2641](https://github.com/KomodoPlatform/komodo-defi-framework/pull/2641) + +--- + +## v2.5.1-beta - 2025-07-28 + +### Enhancements/Fixes: + +**Wallet**: +- A comprehensive `get_private_keys` RPC was implemented to export private keys, public keys, and addresses for any configured coin without requiring activation. HD and Iguana modes with protocol-specific logic for UTXO, EVM, Tendermint, and ZHTLC coins were supported, enabling offline recovery workflows (implemented by Devin AI). [#2542](https://github.com/KomodoPlatform/komodo-defi-framework/pull/2542) + +--- + ## v2.5.0-beta - 2025-07-04 ### Features: diff --git a/Cargo.lock b/Cargo.lock index 1f2c56f66f..b3062ee23c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2406,15 +2406,6 @@ dependencies = [ "crunchy", ] -[[package]] -name = "hashbrown" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" -dependencies = [ - "ahash 0.7.6", -] - [[package]] name = "hashbrown" version = "0.12.1" @@ -3290,7 +3281,7 @@ dependencies = [ "libp2p-identity", "libp2p-swarm", "log", - "lru 0.10.1", + "lru", "quick-protobuf", "quick-protobuf-codec", "smallvec 1.6.1", @@ -3678,15 +3669,6 @@ dependencies = [ "value-bag", ] -[[package]] -name = "lru" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32613e41de4c47ab04970c348ca7ae7382cf116625755af070b008a15516a889" -dependencies = [ - "hashbrown 0.11.2", -] - [[package]] name = "lru" version = "0.10.1" @@ -3875,7 +3857,7 @@ dependencies = [ [[package]] name = "mm2_bin_lib" -version = "2.5.1-beta" +version = "2.5.2-beta" dependencies = [ "chrono", "common", @@ -4113,7 +4095,6 @@ dependencies = [ "mm2_test_helpers", "mocktopus", "num-traits", - "parity-util-mem", "parking_lot", "primitive-types", "primitives", @@ -4701,14 +4682,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c32561d248d352148124f036cac253a644685a21dc9fea383eb4907d7bd35a8f" dependencies = [ "cfg-if 1.0.0", - "ethereum-types", "hashbrown 0.12.1", "impl-trait-for-tuples", - "lru 0.7.5", "parity-util-mem-derive", - "parking_lot", "primitive-types", - "smallvec 1.6.1", "winapi", ] diff --git a/Cargo.toml b/Cargo.toml index dd317f0d87..b7e7e2ae7c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -141,7 +141,6 @@ mocktopus = "0.8.0" nom = "6.1.2" num-bigint = { version = "0.4", features = ["serde", "std"] } num-rational = { version = "0.4", features = ["serde"] } -parity-util-mem = "0.11" num-traits = "0.2" pairing_api = { git = "https://github.com/komodoplatform/walletconnectrust", tag = "k-0.1.3" } parking_lot = { version = "0.12.0", default-features = false } diff --git a/LEGAL/THIRDPARTY-LICENSES b/LEGAL/THIRDPARTY-LICENSES index 96ae454e1f..fa1af2ddac 100755 --- a/LEGAL/THIRDPARTY-LICENSES +++ b/LEGAL/THIRDPARTY-LICENSES @@ -6,7 +6,7 @@ Apache-2.0 AND BSD-2-Clause OR MIT (2): crossbeam-channel, crossbeam-queue Apache-2.0 OR Apache-2.0 WITH LLVM-exception OR MIT (2): wasi, wasi Apache-2.0 OR BSL-1.0 (1): ryu Apache-2.0 OR ISC OR MIT (4): ct-logs, hyper-rustls, rustls, sct -Apache-2.0 OR MIT (343): addr2line, aead, aes, aes-gcm, ahash, ahash, ahash, ahash, anyhow, arc-swap, arrayvec, arrayvec, arrayvec, async-std, async-task, async-trait, atomic, atomic-shim, autocfg, autocfg, backtrace, base64, base64, base64, base64, bigdecimal, bimap, bitflags, blake2, block-buffer, block-buffer, block-padding, blocking, bs58, bumpalo, byte-tools, cache-padded, cc, cfg-if, cfg-if, chacha20, chacha20poly1305, chrono, cipher, concurrent-queue, console_error_panic_hook, const-random, const-random-macro, cpufeatures, cpuid-bool, crc, crc32fast, crossbeam, crossbeam-deque, crossbeam-epoch, crossbeam-utils, crypto-mac, crypto-mac, ctr, debug_stub_derive, derivative, digest, digest, dirs, dtoa, ed25519, either, enum-as-inner, env_logger, error-chain, ethabi, ethbloom, ethereum-types, fake-simd, fallible-iterator, fallible-streaming-iterator, fastrand, findshlibs, fixed-hash, fixedbitset, flate2, fnv, futures, futures, futures-channel, futures-core, futures-cpupool, futures-executor, futures-io, futures-macro, futures-rustls, futures-sink, futures-task, futures-timer, futures-util, getrandom, getrandom, ghash, gimli, gloo-timers, groestl, hashbrown, hashbrown, hashbrown, hashbrown, hashlink, hdrhistogram, hdrhistogram, heck, hermit-abi, hex, hex, hex-literal, hmac, hmac, http, http, httparse, httpdate, humantime, humantime, idna, idna, impl-codec, impl-rlp, impl-serde, impl-trait-for-tuples, indexmap, iovec, ipconfig, ipnet, itertools, itertools, itertools, itoa, js-sys, kv-log-macro, lazy_static, libc, libz-sys, linked-hash-map, lock_api, lock_api, lock_api, log, log, log-mdc, log4rs, lru-cache, match_cfg, maybe-uninit, miow, multimap, nodrop, nohash-hasher, ntapi, num, num-bigint, num-bigint, num-complex, num-derive, num-integer, num-iter, num-rational, num-rational, num-traits, num-traits, num_cpus, object, once_cell, opaque-debug, opaque-debug, parity-send-wrapper, parity-util-mem, parking, parking_lot, parking_lot, parking_lot, parking_lot, parking_lot_core, parking_lot_core, parking_lot_core, parking_lot_core, paste, percent-encoding, percent-encoding, pest, petgraph, pin-project, pin-project, pin-project-internal, pin-project-internal, pin-project-lite, pin-project-lite, pin-utils, pkg-config, poly1305, polyval, ppv-lite86, primitive-types, proc-macro-crate, proc-macro-crate, proc-macro-error, proc-macro-error-attr, proc-macro-hack, proc-macro-nested, proc-macro2, quick-error, quicksink, quote, quote, rand, rand, rand, rand, rand, rand_chacha, rand_chacha, rand_chacha, rand_core, rand_core, rand_core, rand_core, rand_hc, rand_hc, rand_hc, rand_isaac, rand_jitter, rand_os, rand_pcg, rand_pcg, rand_xorshift, rand_xoshiro, ref-cast, ref-cast-impl, regex, regex-syntax, remove_dir_all, resolv-conf, ripemd160, ripemd160, rlp, rlp, rust-argon2, rustc-demangle, rustc-hex, rustc-hex, rustc_version, rustc_version, scoped-tls, scopeguard, scopeguard, secrecy, semver, semver, semver-parser, semver-parser, send_wrapper, send_wrapper, serde, serde_bytes, serde_bytes, serde_derive, serde_json, serde_repr, serde_yaml, sha-1, sha-1, sha2, sha2, sha3, signal-hook, signal-hook-mio, signal-hook-registry, signature, siphasher, smallvec, smallvec, smol, snow, socket2, socket2, soketto, stable_deref_trait, static_assertions, syn, syn, synom, tc_cli_client, tc_coblox_bitcoincore, tc_core, tc_dynamodb_local, tc_elasticmq, tc_generic, tc_parity_parity, tc_postgres, tc_redis, tc_trufflesuite_ganachecli, tempfile, testcontainers, thiserror, thiserror-impl, thread-id, time, tokio-rustls, tokio-timer, toml, traitobject, trust-dns-proto, trust-dns-resolver, typenum, ucd-trie, uint, uint, unicode-bidi, unicode-normalization, unicode-segmentation, unicode-xid, unicode-xid, universal-hash, url, url, uuid, vcpkg, version_check, waker-fn, wasm-bindgen, wasm-bindgen-backend, wasm-bindgen-futures, wasm-bindgen-macro, wasm-bindgen-macro-support, wasm-bindgen-shared, wasm-bindgen-test, wasm-bindgen-test-macro, web-sys, widestring, winapi, winapi-i686-pc-windows-gnu, winapi-x86_64-pc-windows-gnu, yaml-rust, yamux, zeroize, zeroize_derive +Apache-2.0 OR MIT (343): addr2line, aead, aes, aes-gcm, ahash, ahash, ahash, ahash, anyhow, arc-swap, arrayvec, arrayvec, arrayvec, async-std, async-task, async-trait, atomic, atomic-shim, autocfg, autocfg, backtrace, base64, base64, base64, base64, bigdecimal, bimap, bitflags, blake2, block-buffer, block-buffer, block-padding, blocking, bs58, bumpalo, byte-tools, cache-padded, cc, cfg-if, cfg-if, chacha20, chacha20poly1305, chrono, cipher, concurrent-queue, console_error_panic_hook, const-random, const-random-macro, cpufeatures, cpuid-bool, crc, crc32fast, crossbeam, crossbeam-deque, crossbeam-epoch, crossbeam-utils, crypto-mac, crypto-mac, ctr, debug_stub_derive, derivative, digest, digest, dirs, dtoa, ed25519, either, enum-as-inner, env_logger, error-chain, ethabi, ethbloom, ethereum-types, fake-simd, fallible-iterator, fallible-streaming-iterator, fastrand, findshlibs, fixed-hash, fixedbitset, flate2, fnv, futures, futures, futures-channel, futures-core, futures-cpupool, futures-executor, futures-io, futures-macro, futures-rustls, futures-sink, futures-task, futures-timer, futures-util, getrandom, getrandom, ghash, gimli, gloo-timers, groestl, hashbrown, hashbrown, hashbrown, hashbrown, hashlink, hdrhistogram, hdrhistogram, heck, hermit-abi, hex, hex, hex-literal, hmac, hmac, http, http, httparse, httpdate, humantime, humantime, idna, idna, impl-codec, impl-rlp, impl-serde, impl-trait-for-tuples, indexmap, iovec, ipconfig, ipnet, itertools, itertools, itertools, itoa, js-sys, kv-log-macro, lazy_static, libc, libz-sys, linked-hash-map, lock_api, lock_api, lock_api, log, log, log-mdc, log4rs, lru-cache, match_cfg, maybe-uninit, miow, multimap, nodrop, nohash-hasher, ntapi, num, num-bigint, num-bigint, num-complex, num-derive, num-integer, num-iter, num-rational, num-rational, num-traits, num-traits, num_cpus, object, once_cell, opaque-debug, opaque-debug, parity-send-wrapper, parking, parking_lot, parking_lot, parking_lot, parking_lot, parking_lot_core, parking_lot_core, parking_lot_core, parking_lot_core, paste, percent-encoding, percent-encoding, pest, petgraph, pin-project, pin-project, pin-project-internal, pin-project-internal, pin-project-lite, pin-project-lite, pin-utils, pkg-config, poly1305, polyval, ppv-lite86, primitive-types, proc-macro-crate, proc-macro-crate, proc-macro-error, proc-macro-error-attr, proc-macro-hack, proc-macro-nested, proc-macro2, quick-error, quicksink, quote, quote, rand, rand, rand, rand, rand, rand_chacha, rand_chacha, rand_chacha, rand_core, rand_core, rand_core, rand_core, rand_hc, rand_hc, rand_hc, rand_isaac, rand_jitter, rand_os, rand_pcg, rand_pcg, rand_xorshift, rand_xoshiro, ref-cast, ref-cast-impl, regex, regex-syntax, remove_dir_all, resolv-conf, ripemd160, ripemd160, rlp, rlp, rust-argon2, rustc-demangle, rustc-hex, rustc-hex, rustc_version, rustc_version, scoped-tls, scopeguard, scopeguard, secrecy, semver, semver, semver-parser, semver-parser, send_wrapper, send_wrapper, serde, serde_bytes, serde_bytes, serde_derive, serde_json, serde_repr, serde_yaml, sha-1, sha-1, sha2, sha2, sha3, signal-hook, signal-hook-mio, signal-hook-registry, signature, siphasher, smallvec, smallvec, smol, snow, socket2, socket2, soketto, stable_deref_trait, static_assertions, syn, syn, synom, tc_cli_client, tc_coblox_bitcoincore, tc_core, tc_dynamodb_local, tc_elasticmq, tc_generic, tc_parity_parity, tc_postgres, tc_redis, tc_trufflesuite_ganachecli, tempfile, testcontainers, thiserror, thiserror-impl, thread-id, time, tokio-rustls, tokio-timer, toml, traitobject, trust-dns-proto, trust-dns-resolver, typenum, ucd-trie, uint, uint, unicode-bidi, unicode-normalization, unicode-segmentation, unicode-xid, unicode-xid, universal-hash, url, url, uuid, vcpkg, version_check, waker-fn, wasm-bindgen, wasm-bindgen-backend, wasm-bindgen-futures, wasm-bindgen-macro, wasm-bindgen-macro-support, wasm-bindgen-shared, wasm-bindgen-test, wasm-bindgen-test-macro, web-sys, widestring, winapi, winapi-i686-pc-windows-gnu, winapi-x86_64-pc-windows-gnu, yaml-rust, yamux, zeroize, zeroize_derive Apache-2.0 OR MIT OR Zlib (2): tinyvec, tinyvec_macros BSD-2-Clause (4): Inflector, arrayref, cloudabi, cloudabi BSD-2-Clause OR MIT (1): asn1_der @@ -16,7 +16,7 @@ BlueOak-1.0.0 (2): minicbor, minicbor-derive CC0-1.0 (6): constant_time_eq, keccak, secp256k1, secp256k1-sys, tiny-keccak, tiny-keccak GPL-3.0 (10): keccak-hash, bitcrypto, chain, keys, primitives, rpc, script, serialization, serialization_derive, unexpected ISC (2): rdrand, untrusted -MIT (117): asynchronous-codec, atomicdex-gossipsub, atty, base58, bech32, bitcoin-cash, bitcoin-cash-base, bitcoin-cash-script-macro, bitcoin-cash-slp, bitvec, blake2b_simd, build_const, byte-slice-cast, bytes, bytes, bytes, crossterm, crossterm_winapi, crunchy, crunchy, cuckoofilter, cuckoofilter, data-encoding, derive_more, enum-primitive-derive, ethbloom, ethereum-types, ethereum-types-serialize, fixed-hash, fomat-macros, fomat-macros, funty, futures_codec, generic-array, generic-array, gstuff, h2, hostname, http-body, http-body, hyper, jsonrpc-core, libp2p, libp2p-core, libp2p-dns, libp2p-floodsub, libp2p-floodsub, libp2p-mplex, libp2p-noise, libp2p-ping, libp2p-plaintext, libp2p-request-response, libp2p-swarm, libp2p-swarm-derive, libp2p-tcp, libp2p-wasm-ext, libp2p-websocket, libp2p-yamux, libsqlite3-sys, lru, lru, matches, memoffset, metrics, metrics-core, metrics-observer-prometheus, metrics-runtime, metrics-util, miniz_oxide, miniz_oxide, mio, mocktopus, mocktopus_macros, multiaddr, multihash, multihash-derive, multistream-select, ordered-float, owning_ref, parity-util-mem-derive, quanta, radium, redox_syscall, redox_users, rmp, rmp-serde, rusqlite, rust-ini, rw-stream-sink, serde-value, serde_bencode, slab, slab, spin, sql-builder, synstructure, tap, tokio, tokio-buf, tokio-macros, tokio-util, toolchain_find, tower-service, tracing, tracing-core, try-lock, typemap, unsafe-any, unsigned-varint, unsigned-varint, void, want, wasm-timer, web3, which, winreg, wyz +MIT (117): asynchronous-codec, atomicdex-gossipsub, atty, base58, bech32, bitcoin-cash, bitcoin-cash-base, bitcoin-cash-script-macro, bitcoin-cash-slp, bitvec, blake2b_simd, build_const, byte-slice-cast, bytes, bytes, bytes, crossterm, crossterm_winapi, crunchy, crunchy, cuckoofilter, cuckoofilter, data-encoding, derive_more, enum-primitive-derive, ethbloom, ethereum-types, ethereum-types-serialize, fixed-hash, fomat-macros, fomat-macros, funty, futures_codec, generic-array, generic-array, gstuff, h2, hostname, http-body, http-body, hyper, jsonrpc-core, libp2p, libp2p-core, libp2p-dns, libp2p-floodsub, libp2p-floodsub, libp2p-mplex, libp2p-noise, libp2p-ping, libp2p-plaintext, libp2p-request-response, libp2p-swarm, libp2p-swarm-derive, libp2p-tcp, libp2p-wasm-ext, libp2p-websocket, libp2p-yamux, libsqlite3-sys, lru, lru, matches, memoffset, metrics, metrics-core, metrics-observer-prometheus, metrics-runtime, metrics-util, miniz_oxide, miniz_oxide, mio, mocktopus, mocktopus_macros, multiaddr, multihash, multihash-derive, multistream-select, ordered-float, owning_ref, quanta, radium, redox_syscall, redox_users, rmp, rmp-serde, rusqlite, rust-ini, rw-stream-sink, serde-value, serde_bencode, slab, slab, spin, sql-builder, synstructure, tap, tokio, tokio-buf, tokio-macros, tokio-util, toolchain_find, tower-service, tracing, tracing-core, try-lock, typemap, unsafe-any, unsigned-varint, unsigned-varint, void, want, wasm-timer, web3, which, winreg, wyz MIT OR Unlicense (9): aho-corasick, byteorder, byteorder, memchr, quickcheck, same-file, termcolor, walkdir, winapi-util MPL-2.0 (3): webpki-roots, webpki-roots, wepoll-sys-stjepang MPL-2.0+ (3): bitmaps, im, sized-chunks diff --git a/mm2src/coins/z_coin/storage/walletdb/wasm/storage.rs b/mm2src/coins/z_coin/storage/walletdb/wasm/storage.rs index 78d8a6fbaa..5713e8bcf3 100644 --- a/mm2src/coins/z_coin/storage/walletdb/wasm/storage.rs +++ b/mm2src/coins/z_coin/storage/walletdb/wasm/storage.rs @@ -1079,21 +1079,23 @@ impl WalletRead for WalletIndexedDb { let mut nullifiers = vec![]; for (_, note) in maybe_notes { - let matching_tx = maybe_txs.iter().find(|(id_tx, _tx)| id_tx.to_bigint() == note.spent); - - if let Some((_, tx)) = matching_tx { - if tx.block.is_some() { - nullifiers.push(( - AccountId( - note.account - .to_u32() - .ok_or_else(|| ZcoinStorageError::GetFromStorageError("Invalid amount".to_string()))?, - ), - Nullifier::from_slice(¬e.nf.clone().ok_or_else(|| { - ZcoinStorageError::GetFromStorageError("Error while putting tx_meta".to_string()) - })?) - .unwrap(), - )); + let maybe_spending_tx = maybe_txs.iter().find(|(id_tx, _tx)| id_tx.to_bigint() == note.spent); + let add_nullifier = match maybe_spending_tx { + Some((_, tx)) if tx.block.is_none() => true, + None => true, + _ => false, + }; + if add_nullifier { + if let Some(ref nf_bytes) = note.nf { + let account_id = AccountId( + note.account + .to_u32() + .ok_or_else(|| ZcoinStorageError::GetFromStorageError("Invalid account id".to_string()))?, + ); + let nf = Nullifier::from_slice(nf_bytes).map_err(|e| { + ZcoinStorageError::GetFromStorageError(format!("Invalid nullifier bytes error: {}", e)) + })?; + nullifiers.push((account_id, nf)); } } } diff --git a/mm2src/common/log.rs b/mm2src/common/log.rs index 41116073ca..f108f16987 100644 --- a/mm2src/common/log.rs +++ b/mm2src/common/log.rs @@ -176,6 +176,18 @@ macro_rules! covered_warn { }; } +#[macro_export] +/// A macro to log errors in production environment and panic in tests. +macro_rules! covered_error { + ($($arg:tt)+) => { + if cfg!(not(test)) { + common::log::error!($($arg)+) + } else { + panic!($($arg)+) + } + }; +} + /// Debug logging. /// /// This logging SHOULD be human-readable but it is not intended for the end users specifically. diff --git a/mm2src/db_common/src/sqlite.rs b/mm2src/db_common/src/sqlite.rs index f92707d2d5..3849799aec 100644 --- a/mm2src/db_common/src/sqlite.rs +++ b/mm2src/db_common/src/sqlite.rs @@ -1,6 +1,7 @@ #![allow(deprecated)] // TODO: remove this once rusqlite is >= 0.29 pub use rusqlite; +pub use rusqlite::types::Value as SqlValue; pub use sql_builder; use log::debug; @@ -322,7 +323,7 @@ pub fn run_optimization_pragmas(conn: &Connection) -> Result<(), SqlError> { Ok(()) } -pub fn execute_batch(statement: &'static [&str]) -> Vec<(&'static str, Vec)> { +pub fn execute_batch(statement: &'static [&str]) -> Vec<(&'static str, Vec)> { statement.iter().map(|sql| (*sql, vec![])).collect() } diff --git a/mm2src/mm2_bin_lib/Cargo.toml b/mm2src/mm2_bin_lib/Cargo.toml index 8d244c3fa6..e1decca01b 100644 --- a/mm2src/mm2_bin_lib/Cargo.toml +++ b/mm2src/mm2_bin_lib/Cargo.toml @@ -5,7 +5,7 @@ [package] name = "mm2_bin_lib" -version = "2.5.1-beta" +version = "2.5.2-beta" authors = ["James Lee", "Artem Pikulin", "Artem Grinblat", "Omar S.", "Onur Ozkan", "Alina Sharon", "Caglar Kaya", "Cipi", "Sergey Boiko", "Samuel Onoja", "Roman Sztergbaum", "Kadan Stadelmann ", "Dimxy", "Omer Yacine", "DeckerSU", "dragonhound ", "Devin AI"] edition = "2018" default-run = "kdf" diff --git a/mm2src/mm2_main/Cargo.toml b/mm2src/mm2_main/Cargo.toml index b2fe520cfb..696c611031 100644 --- a/mm2src/mm2_main/Cargo.toml +++ b/mm2src/mm2_main/Cargo.toml @@ -76,7 +76,6 @@ mm2_rpc = { path = "../mm2_rpc", features = ["rpc_facilities"] } mm2_state_machine = { path = "../mm2_state_machine" } trading_api = { path = "../trading_api" } num-traits.workspace = true -parity-util-mem.workspace = true parking_lot = { workspace = true, features = ["nightly"] } primitives = { path = "../mm2_bitcoin/primitives" } primitive-types.workspace = true diff --git a/mm2src/mm2_main/src/database.rs b/mm2src/mm2_main/src/database.rs index 6945204643..3b51a74692 100644 --- a/mm2src/mm2_main/src/database.rs +++ b/mm2src/mm2_main/src/database.rs @@ -5,10 +5,11 @@ pub mod my_swaps; pub mod stats_nodes; pub mod stats_swaps; +use crate::database::stats_swaps::fix_maker_and_taker_pubkeys_in_stats_db; use crate::CREATE_MY_SWAPS_TABLE; use common::log::{debug, error, info}; -use db_common::sqlite::run_optimization_pragmas; use db_common::sqlite::rusqlite::{params_from_iter, Result as SqlResult}; +use db_common::sqlite::{run_optimization_pragmas, SqlValue}; use mm2_core::mm_ctx::MmArc; use my_swaps::{fill_my_swaps_from_json_statements, set_is_finished_for_legacy_swaps_statements}; @@ -71,62 +72,68 @@ fn clean_db(ctx: &MmArc) { } } -async fn migration_1(ctx: &MmArc) -> Vec<(&'static str, Vec)> { fill_my_swaps_from_json_statements(ctx).await } +async fn migration_1(ctx: &MmArc) -> Vec<(&'static str, Vec)> { + fill_my_swaps_from_json_statements(ctx).await +} -async fn migration_2(ctx: &MmArc) -> Vec<(&'static str, Vec)> { +async fn migration_2(ctx: &MmArc) -> Vec<(&'static str, Vec)> { create_and_fill_stats_swaps_from_json_statements(ctx).await } -fn migration_3() -> Vec<(&'static str, Vec)> { vec![(stats_swaps::ADD_STARTED_AT_INDEX, vec![])] } +fn migration_3() -> Vec<(&'static str, Vec)> { vec![(stats_swaps::ADD_STARTED_AT_INDEX, vec![])] } -fn migration_4() -> Vec<(&'static str, Vec)> { +fn migration_4() -> Vec<(&'static str, Vec)> { db_common::sqlite::execute_batch(stats_swaps::ADD_SPLIT_TICKERS) } -fn migration_5() -> Vec<(&'static str, Vec)> { vec![(my_orders::CREATE_MY_ORDERS_TABLE, vec![])] } +fn migration_5() -> Vec<(&'static str, Vec)> { vec![(my_orders::CREATE_MY_ORDERS_TABLE, vec![])] } -fn migration_6() -> Vec<(&'static str, Vec)> { +fn migration_6() -> Vec<(&'static str, Vec)> { vec![ (stats_nodes::CREATE_NODES_TABLE, vec![]), (stats_nodes::CREATE_STATS_NODES_TABLE, vec![]), ] } -fn migration_7() -> Vec<(&'static str, Vec)> { +fn migration_7() -> Vec<(&'static str, Vec)> { db_common::sqlite::execute_batch(stats_swaps::ADD_COINS_PRICE_INFOMATION) } -fn migration_8() -> Vec<(&'static str, Vec)> { +fn migration_8() -> Vec<(&'static str, Vec)> { db_common::sqlite::execute_batch(stats_swaps::ADD_MAKER_TAKER_PUBKEYS) } -fn migration_9() -> Vec<(&'static str, Vec)> { +fn migration_9() -> Vec<(&'static str, Vec)> { db_common::sqlite::execute_batch(my_swaps::TRADING_PROTO_UPGRADE_MIGRATION) } -async fn migration_10(ctx: &MmArc) -> Vec<(&'static str, Vec)> { +async fn migration_10(ctx: &MmArc) -> Vec<(&'static str, Vec)> { set_is_finished_for_legacy_swaps_statements(ctx).await } -fn migration_11() -> Vec<(&'static str, Vec)> { +fn migration_11() -> Vec<(&'static str, Vec)> { db_common::sqlite::execute_batch(stats_swaps::ADD_MAKER_TAKER_GUI_AND_VERSION) } -fn migration_12() -> Vec<(&'static str, Vec)> { +fn migration_12() -> Vec<(&'static str, Vec)> { vec![ (my_swaps::ADD_OTHER_P2P_PUBKEY_FIELD, vec![]), (my_swaps::ADD_DEX_FEE_BURN_FIELD, vec![]), ] } -fn migration_13() -> Vec<(&'static str, Vec)> { +fn migration_13() -> Vec<(&'static str, Vec)> { vec![ (my_swaps::ADD_SWAP_VERSION_FIELD, vec![]), // Step 1: Add new column (my_swaps::SET_LEGACY_SWAP_VERSION, vec![]), // Step 2: Update old rows ] } -async fn statements_for_migration(ctx: &MmArc, current_migration: i64) -> Option)>> { +async fn migration_14(ctx: &MmArc) -> Vec<(&'static str, Vec)> { + fix_maker_and_taker_pubkeys_in_stats_db(ctx).await +} + +async fn statements_for_migration(ctx: &MmArc, current_migration: i64) -> Option)>> { match current_migration { 1 => Some(migration_1(ctx).await), 2 => Some(migration_2(ctx).await), @@ -141,6 +148,7 @@ async fn statements_for_migration(ctx: &MmArc, current_migration: i64) -> Option 11 => Some(migration_11()), 12 => Some(migration_12()), 13 => Some(migration_13()), + 14 => Some(migration_14(ctx).await), _ => None, } } diff --git a/mm2src/mm2_main/src/database/my_swaps.rs b/mm2src/mm2_main/src/database/my_swaps.rs index 91c2200bba..bf9893bc16 100644 --- a/mm2src/mm2_main/src/database/my_swaps.rs +++ b/mm2src/mm2_main/src/database/my_swaps.rs @@ -6,7 +6,7 @@ use common::log::debug; use common::PagingOptions; use db_common::sqlite::rusqlite::{Connection, Error as SqlError, Result as SqlResult, ToSql}; use db_common::sqlite::sql_builder::SqlBuilder; -use db_common::sqlite::{offset_by_uuid, query_single_row}; +use db_common::sqlite::{offset_by_uuid, query_single_row, SqlValue}; use mm2_core::mm_ctx::MmArc; use std::convert::TryInto; use uuid::{Error as UuidError, Uuid}; @@ -134,7 +134,7 @@ pub fn insert_new_swap_v2(ctx: &MmArc, params: &[(&str, &dyn ToSql)]) -> SqlResu /// Returns SQL statements to initially fill my_swaps table using existing DB with JSON files /// Use this only in migration code! -pub async fn fill_my_swaps_from_json_statements(ctx: &MmArc) -> Vec<(&'static str, Vec)> { +pub async fn fill_my_swaps_from_json_statements(ctx: &MmArc) -> Vec<(&'static str, Vec)> { let swaps = SavedSwap::load_all_my_swaps_from_db(ctx).await.unwrap_or_default(); swaps .into_iter() @@ -143,7 +143,7 @@ pub async fn fill_my_swaps_from_json_statements(ctx: &MmArc) -> Vec<(&'static st } /// Use this only in migration code! -fn insert_saved_swap_sql_migration_1(swap: SavedSwap) -> Option<(&'static str, Vec)> { +fn insert_saved_swap_sql_migration_1(swap: SavedSwap) -> Option<(&'static str, Vec)> { let swap_info = match swap.get_my_info() { Some(s) => s, // get_my_info returning None means that swap did not even start - so we can keep it away from indexing. @@ -154,7 +154,11 @@ fn insert_saved_swap_sql_migration_1(swap: SavedSwap) -> Option<(&'static str, V swap_info.other_coin, swap.uuid().to_string(), swap_info.started_at.to_string(), - ]; + ] + .into_iter() + .map(SqlValue::from) + .collect(); + Some((INSERT_MY_SWAP_MIGRATION_1, params)) } @@ -353,13 +357,13 @@ WHERE uuid = :uuid; "#; /// Returns SQL statements to set is_finished to 1 for completed legacy swaps -pub async fn set_is_finished_for_legacy_swaps_statements(ctx: &MmArc) -> Vec<(&'static str, Vec)> { +pub async fn set_is_finished_for_legacy_swaps_statements(ctx: &MmArc) -> Vec<(&'static str, Vec)> { let swaps = SavedSwap::load_all_my_swaps_from_db(ctx).await.unwrap_or_default(); swaps .into_iter() .filter_map(|swap| { if swap.is_finished() { - Some((UPDATE_SWAP_IS_FINISHED_BY_UUID, vec![swap.uuid().to_string()])) + Some((UPDATE_SWAP_IS_FINISHED_BY_UUID, vec![swap.uuid().to_string().into()])) } else { None } diff --git a/mm2src/mm2_main/src/database/stats_swaps.rs b/mm2src/mm2_main/src/database/stats_swaps.rs index 3322245f01..6e2feb5020 100644 --- a/mm2src/mm2_main/src/database/stats_swaps.rs +++ b/mm2src/mm2_main/src/database/stats_swaps.rs @@ -4,7 +4,7 @@ use crate::lp_swap::{MakerSavedSwap, SavedSwap, SavedSwapIo, TakerSavedSwap}; use common::log::{debug, error}; use db_common::{owned_named_params, sqlite::{rusqlite::{params_from_iter, Connection, OptionalExtension}, - AsSqlNamedParams, OwnedSqlNamedParams}}; + AsSqlNamedParams, OwnedSqlNamedParams, SqlValue}}; use mm2_core::mm_ctx::MmArc; use std::collections::HashSet; @@ -43,14 +43,9 @@ const INSERT_STATS_SWAP: &str = "INSERT INTO stats_swaps ( finished_at, maker_amount, taker_amount, - is_success, - maker_coin_usd_price, - taker_coin_usd_price, - maker_pubkey, - taker_pubkey + is_success ) VALUES (:maker_coin, :maker_coin_ticker, :maker_coin_platform, :taker_coin, :taker_coin_ticker, -:taker_coin_platform, :uuid, :started_at, :finished_at, :maker_amount, :taker_amount, :is_success, -:maker_coin_usd_price, :taker_coin_usd_price, :maker_pubkey, :taker_pubkey)"; +:taker_coin_platform, :uuid, :started_at, :finished_at, :maker_amount, :taker_amount, :is_success)"; pub const ADD_STARTED_AT_INDEX: &str = "CREATE INDEX timestamp_index ON stats_swaps (started_at);"; @@ -97,7 +92,7 @@ pub const ADD_MAKER_TAKER_GUI_AND_VERSION: &[&str] = &[ pub const SELECT_ID_BY_UUID: &str = "SELECT id FROM stats_swaps WHERE uuid = ?1"; /// Returns SQL statements to initially fill stats_swaps table using existing DB with JSON files -pub async fn create_and_fill_stats_swaps_from_json_statements(ctx: &MmArc) -> Vec<(&'static str, Vec)> { +pub async fn create_and_fill_stats_swaps_from_json_statements(ctx: &MmArc) -> Vec<(&'static str, Vec)> { let maker_swaps = SavedSwap::load_all_from_maker_stats_db(ctx).await.unwrap_or_default(); let taker_swaps = SavedSwap::load_all_from_taker_stats_db(ctx).await.unwrap_or_default(); @@ -121,6 +116,54 @@ pub async fn create_and_fill_stats_swaps_from_json_statements(ctx: &MmArc) -> Ve result } +pub async fn fix_maker_and_taker_pubkeys_in_stats_db(ctx: &MmArc) -> Vec<(&'static str, Vec)> { + let maker_swaps = SavedSwap::load_all_from_maker_stats_db(ctx).await.unwrap_or_default(); + let taker_swaps = SavedSwap::load_all_from_taker_stats_db(ctx).await.unwrap_or_default(); + + let mut result = Vec::new(); + + // Update all the `maker_pubkey`s using maker's `my_persistent_pub` field + for maker_swap in maker_swaps { + const UPDATE_MAKER_PUBKEY: &str = "UPDATE stats_swaps SET maker_pubkey = ?1 WHERE uuid = ?2;"; + match maker_swap.maker_pubkey() { + Ok(maker_pubkey) => { + result.push((UPDATE_MAKER_PUBKEY, vec![ + maker_pubkey.into(), + maker_swap.uuid.to_string().into(), + ])); + }, + Err(e) => { + covered_error!("Error {} on getting maker_pubkey for swap {}", e, maker_swap.uuid); + result.push((UPDATE_MAKER_PUBKEY, vec![ + SqlValue::Null, + maker_swap.uuid.to_string().into(), + ])); + }, + } + } + // Update all the `taker_pubkey`s using taker's `my_persistent_pub` field + for taker_swap in taker_swaps { + const UPDATE_TAKER_PUBKEY: &str = "UPDATE stats_swaps SET taker_pubkey = ?1 WHERE uuid = ?2;"; + match taker_swap.taker_pubkey() { + Ok(taker_pubkey) => { + result.push((UPDATE_TAKER_PUBKEY, vec![ + taker_pubkey.into(), + taker_swap.uuid.to_string().into(), + ])); + }, + Err(e) => { + covered_error!("Error {} on getting taker_pubkey for swap {}", e, taker_swap.uuid); + result.push((UPDATE_TAKER_PUBKEY, vec![ + SqlValue::Null, + taker_swap.uuid.to_string().into(), + ])); + }, + } + } + + result +} + fn split_coin(coin: &str) -> (String, String) { let mut split = coin.split('-'); let ticker = split.next().expect("split returns empty string at least").into(); @@ -145,14 +188,6 @@ fn insert_stats_maker_swap_sql(swap: &MakerSavedSwap) -> Option<(&'static str, O }, }; - let pubkeys = match swap.swap_pubkeys() { - Ok(p) => p, - Err(e) => { - error!("Error {} on getting swap {} pubkeys", e, swap.uuid); - return None; - }, - }; - let is_success = swap .is_success() .expect("is_success can return error only when swap is not finished"); @@ -173,28 +208,12 @@ fn insert_stats_maker_swap_sql(swap: &MakerSavedSwap) -> Option<(&'static str, O ":maker_amount": swap_data.maker_amount.to_string(), ":taker_amount": swap_data.taker_amount.to_string(), ":is_success": (is_success as u32).to_string(), - ":maker_coin_usd_price": swap.maker_coin_usd_price.as_ref().map(|p| p.to_string()), - ":taker_coin_usd_price": swap.taker_coin_usd_price.as_ref().map(|p| p.to_string()), - ":maker_pubkey": pubkeys.maker, - ":taker_pubkey": pubkeys.taker, }; Some((INSERT_STATS_SWAP, params)) } -fn update_stats_maker_gui_version(swap: &MakerSavedSwap) -> (&'static str, OwnedSqlNamedParams) { - const UPDATE_STATS_SWAP_GUI_AND_VERSION_MAKER: &str = - "UPDATE stats_swaps set maker_gui = :maker_gui, maker_version = :maker_version WHERE uuid = :uuid;"; - let params = owned_named_params! { - ":maker_gui": swap.gui.clone(), - ":maker_version": swap.mm_version.clone(), - ":uuid": swap.uuid.to_string(), - }; - - (UPDATE_STATS_SWAP_GUI_AND_VERSION_MAKER, params) -} - -fn insert_stats_maker_swap_sql_init(swap: &MakerSavedSwap) -> Option<(&'static str, Vec)> { +fn insert_stats_maker_swap_sql_init(swap: &MakerSavedSwap) -> Option<(&'static str, Vec)> { let swap_data = match swap.swap_data() { Ok(d) => d, Err(e) => { @@ -222,7 +241,11 @@ fn insert_stats_maker_swap_sql_init(swap: &MakerSavedSwap) -> Option<(&'static s swap_data.maker_amount.to_string(), swap_data.taker_amount.to_string(), (is_success as u32).to_string(), - ]; + ] + .into_iter() + .map(SqlValue::from) + .collect(); + Some((INSERT_STATS_SWAP_ON_INIT, params)) } @@ -242,14 +265,6 @@ fn insert_stats_taker_swap_sql(swap: &TakerSavedSwap) -> Option<(&'static str, O }, }; - let pubkeys = match swap.swap_pubkeys() { - Ok(p) => p, - Err(e) => { - error!("Error {} on getting swap {} pubkeys", e, swap.uuid); - return None; - }, - }; - let is_success = swap .is_success() .expect("is_success can return error only when swap is not finished"); @@ -270,27 +285,11 @@ fn insert_stats_taker_swap_sql(swap: &TakerSavedSwap) -> Option<(&'static str, O ":maker_amount": swap_data.maker_amount.to_string(), ":taker_amount": swap_data.taker_amount.to_string(), ":is_success": (is_success as u32).to_string(), - ":maker_coin_usd_price": swap.maker_coin_usd_price.as_ref().map(|p| p.to_string()), - ":taker_coin_usd_price": swap.taker_coin_usd_price.as_ref().map(|p| p.to_string()), - ":maker_pubkey": pubkeys.maker, - ":taker_pubkey": pubkeys.taker, }; Some((INSERT_STATS_SWAP, params)) } -fn update_stats_taker_gui_version(swap: &TakerSavedSwap) -> (&'static str, OwnedSqlNamedParams) { - const UPDATE_STATS_SWAP_GUI_AND_VERSION_TAKER: &str = - "UPDATE stats_swaps set taker_gui = :taker_gui, taker_version = :taker_version WHERE uuid = :uuid;"; - let params = owned_named_params! { - ":taker_gui": swap.gui.clone(), - ":taker_version": swap.mm_version.clone(), - ":uuid": swap.uuid.to_string(), - }; - - (UPDATE_STATS_SWAP_GUI_AND_VERSION_TAKER, params) -} - -fn insert_stats_taker_swap_sql_init(swap: &TakerSavedSwap) -> Option<(&'static str, Vec)> { +fn insert_stats_taker_swap_sql_init(swap: &TakerSavedSwap) -> Option<(&'static str, Vec)> { let swap_data = match swap.swap_data() { Ok(d) => d, Err(e) => { @@ -318,10 +317,79 @@ fn insert_stats_taker_swap_sql_init(swap: &TakerSavedSwap) -> Option<(&'static s swap_data.maker_amount.to_string(), swap_data.taker_amount.to_string(), (is_success as u32).to_string(), - ]; + ] + .into_iter() + .map(SqlValue::from) + .collect(); + Some((INSERT_STATS_SWAP_ON_INIT, params)) } +/// Constructs the update query for optional fields of the swap. +/// These are fields which are usually sent unilaterally from one side and combined together based on the shared UUID. +fn update_optional_info(swap: &SavedSwap) -> Option<(String, OwnedSqlNamedParams)> { + let mut extra_args = Vec::new(); + let mut params = OwnedSqlNamedParams::new(); + + if let Some(maker_pubkey) = swap.maker_pubkey() { + match maker_pubkey { + Ok(maker_pubkey) => { + extra_args.push("maker_pubkey = :maker_pubkey"); + params.push((":maker_pubkey", maker_pubkey.into())); + }, + Err(e) => { + covered_error!("[{}] Error on getting maker_pubkey for stats: {}", swap.uuid(), e); + }, + } + } + if let Some(taker_pubkey) = swap.taker_pubkey() { + match taker_pubkey { + Ok(taker_pubkey) => { + extra_args.push("taker_pubkey = :taker_pubkey"); + params.push((":taker_pubkey", taker_pubkey.into())); + }, + Err(e) => { + covered_error!("[{}] Error on getting taker_pubkey for stats: {}", swap.uuid(), e); + }, + } + } + if let Some(maker_coin_usd_price) = swap.maker_usd_price() { + extra_args.push("maker_coin_usd_price = :maker_coin_usd_price"); + params.push((":maker_coin_usd_price", maker_coin_usd_price.to_string().into())); + } + if let Some(taker_coin_usd_price) = swap.taker_usd_price() { + extra_args.push("taker_coin_usd_price = :taker_coin_usd_price"); + params.push((":taker_coin_usd_price", taker_coin_usd_price.to_string().into())); + } + if let Some(maker_gui) = swap.maker_gui() { + extra_args.push("maker_gui = :maker_gui"); + params.push((":maker_gui", maker_gui.clone().into())); + } + if let Some(maker_version) = swap.maker_mm_version() { + extra_args.push("maker_version = :maker_version"); + params.push((":maker_version", maker_version.clone().into())); + } + if let Some(taker_gui) = swap.taker_gui() { + extra_args.push("taker_gui = :taker_gui"); + params.push((":taker_gui", taker_gui.clone().into())); + } + if let Some(taker_version) = swap.taker_mm_version() { + extra_args.push("taker_version = :taker_version"); + params.push((":taker_version", taker_version.clone().into())); + } + + // If no updates were needed, return None + if extra_args.is_empty() { + return None; + } + + let update_query = format!("UPDATE stats_swaps set {} WHERE uuid = :uuid;", extra_args.join(", ")); + + params.push((":uuid", swap.uuid().to_string().into())); + + Some((update_query, params)) +} + fn execute_query_with_params(conn: &Connection, sql: &str, params: OwnedSqlNamedParams) { debug!("Executing query {} with params {:?}", sql, params); if let Err(e) = conn.execute_named(sql, ¶ms.as_sql_named_params()) { @@ -357,12 +425,9 @@ pub fn add_swap_to_index(conn: &Connection, swap: &SavedSwap) { }, }; - let (sql, params) = match swap { - SavedSwap::Maker(maker) => update_stats_maker_gui_version(maker), - SavedSwap::Taker(taker) => update_stats_taker_gui_version(taker), - }; - - execute_query_with_params(conn, sql, params); + if let Some((sql, params)) = update_optional_info(swap) { + execute_query_with_params(conn, &sql, params); + } } #[test] diff --git a/mm2src/mm2_main/src/lp_ordermatch.rs b/mm2src/mm2_main/src/lp_ordermatch.rs index 9f57101d42..15b5738506 100644 --- a/mm2src/mm2_main/src/lp_ordermatch.rs +++ b/mm2src/mm2_main/src/lp_ordermatch.rs @@ -2543,17 +2543,8 @@ fn order_pair_root_mut<'a>(state: &'a mut HashMap, } } -/// `parity_util_mem::malloc_size` crushes for some reason on wasm32 -#[cfg(target_arch = "wasm32")] -fn collect_orderbook_metrics(_ctx: &MmArc, _orderbook: &Orderbook) {} - -#[cfg(not(target_arch = "wasm32"))] fn collect_orderbook_metrics(ctx: &MmArc, orderbook: &Orderbook) { - use parity_util_mem::malloc_size; - - let memory_db_size = malloc_size(&orderbook.memory_db); mm_gauge!(ctx.metrics, "orderbook.len", orderbook.order_set.len() as f64); - mm_gauge!(ctx.metrics, "orderbook.memory_db", memory_db_size as f64); } struct Orderbook { diff --git a/mm2src/mm2_main/src/lp_swap.rs b/mm2src/mm2_main/src/lp_swap.rs index 7744b555d8..b43537063e 100644 --- a/mm2src/mm2_main/src/lp_swap.rs +++ b/mm2src/mm2_main/src/lp_swap.rs @@ -1624,11 +1624,6 @@ pub fn detect_secret_hash_algo_v2(maker_coin: &MmCoinEnum, taker_coin: &MmCoinEn } } -pub struct SwapPubkeys { - pub maker: String, - pub taker: String, -} - /// P2P topic used to broadcast messages during execution of the upgraded swap protocol. pub fn swap_v2_topic(uuid: &Uuid) -> String { pub_sub_topic(SWAP_V2_PREFIX, &uuid.to_string()) } diff --git a/mm2src/mm2_main/src/lp_swap/maker_swap.rs b/mm2src/mm2_main/src/lp_swap/maker_swap.rs index b74953f42b..cf295c339f 100644 --- a/mm2src/mm2_main/src/lp_swap/maker_swap.rs +++ b/mm2src/mm2_main/src/lp_swap/maker_swap.rs @@ -8,7 +8,7 @@ use super::{broadcast_my_swap_status, broadcast_p2p_tx_msg, broadcast_swap_msg_e taker_payment_spend_deadline, tx_helper_topic, wait_for_maker_payment_conf_until, AtomicSwap, LockedAmount, MySwapInfo, NegotiationDataMsg, NegotiationDataV2, NegotiationDataV3, RecoveredSwap, RecoveredSwapAction, SavedSwap, SavedSwapIo, SavedTradeFee, SwapConfirmationsSettings, SwapError, SwapMsg, - SwapPubkeys, SwapTxDataMsg, SwapsContext, TransactionIdentifier, INCLUDE_REFUND_FEE, NO_REFUND_FEE, + SwapTxDataMsg, SwapsContext, TransactionIdentifier, INCLUDE_REFUND_FEE, NO_REFUND_FEE, TAKER_FEE_VALIDATION_ATTEMPTS, TAKER_FEE_VALIDATION_RETRY_DELAY_SECS, WAIT_CONFIRM_INTERVAL_SEC}; use crate::lp_dispatcher::{DispatcherContext, LpEvents}; use crate::lp_network::subscribe_to_topic; @@ -2039,31 +2039,14 @@ impl MakerSavedSwap { } } - // TODO: Adjust for private coins when/if they are braodcasted - // TODO: Adjust for HD wallet when completed - pub fn swap_pubkeys(&self) -> Result { - let maker = match &self.events.first() { + pub fn maker_pubkey(&self) -> Result { + match &self.events.first() { Some(event) => match &event.event { - MakerSwapEvent::Started(started) => started.my_persistent_pub.to_string(), - _ => return ERR!("First swap event must be Started"), - }, - None => return ERR!("Can't get maker's pubkey while events are empty"), - }; - - let taker = match self.events.get(1) { - Some(event) => match &event.event { - MakerSwapEvent::Negotiated(neg) => { - let Some(key) = neg.taker_coin_htlc_pubkey else { - return ERR!("taker's pubkey is empty"); - }; - key.to_string() - }, - _ => return ERR!("Swap must be negotiated to get taker's pubkey"), + MakerSwapEvent::Started(started) => Ok(started.my_persistent_pub.to_string()), + _ => ERR!("First swap event must be Started"), }, - None => return ERR!("Can't get taker's pubkey while there's no Negotiated event"), - }; - - Ok(SwapPubkeys { maker, taker }) + None => ERR!("Can't get maker's pubkey while events are empty"), + } } } @@ -2156,7 +2139,6 @@ pub async fn run_maker_swap(swap: RunMakerSwapInput, ctx: MmArc) { subscribe_to_topic(&ctx, swap_topic(&swap.uuid)); let mut status = ctx.log.status_handle(); let uuid_str = swap.uuid.to_string(); - let to_broadcast = !(swap.maker_coin.is_privacy() || swap.taker_coin.is_privacy()); macro_rules! swap_tags { () => { &[&"swap", &("uuid", uuid_str.as_str())] @@ -2223,10 +2205,8 @@ pub async fn run_maker_swap(swap: RunMakerSwapInput, ctx: MmArc) { error!("!mark_swap_finished({}): {}", uuid, e); } - if to_broadcast { - if let Err(e) = broadcast_my_swap_status(&ctx, uuid).await { - error!("!broadcast_my_swap_status({}): {}", uuid, e); - } + if let Err(e) = broadcast_my_swap_status(&ctx, uuid).await { + covered_error!("!broadcast_my_swap_status({}): {}", uuid, e); } break; }, diff --git a/mm2src/mm2_main/src/lp_swap/saved_swap.rs b/mm2src/mm2_main/src/lp_swap/saved_swap.rs index 158843dadb..5a048399b2 100644 --- a/mm2src/mm2_main/src/lp_swap/saved_swap.rs +++ b/mm2src/mm2_main/src/lp_swap/saved_swap.rs @@ -6,6 +6,7 @@ use coins::lp_coinfind; use derive_more::Display; use mm2_core::mm_ctx::MmArc; use mm2_err_handle::prelude::*; +use mm2_number::BigDecimal; use rpc::v1::types::H256 as H256Json; use uuid::Uuid; #[cfg(target_arch = "wasm32")] @@ -143,6 +144,13 @@ impl SavedSwap { if let Some(ref mut event) = swap.events.first_mut() { if let MakerSwapEvent::Started(ref mut data) = event.event { data.secret = H256Json::default(); + // Remove the taker's pubkey. Let the stats node get it from the taker directly. + data.taker_pubkey = Default::default(); + // If we are using a spun up private key for this swap, then we probably want to hide our + // persistent pubkey as well. + if data.p2p_privkey.is_some() { + data.my_persistent_pub = Default::default(); + } data.p2p_privkey = None; } } @@ -150,6 +158,13 @@ impl SavedSwap { SavedSwap::Taker(swap) => { if let Some(ref mut event) = swap.events.first_mut() { if let TakerSwapEvent::Started(ref mut data) = event.event { + // Remove the maker's pubkey. Let the stats node get it from the maker directly. + data.maker_pubkey = Default::default(); + // If we are using a spun up private key for this swap, then we probably want to hide our + // persistent pubkey as well. + if data.p2p_privkey.is_some() { + data.my_persistent_pub = Default::default(); + } data.p2p_privkey = None; } } @@ -163,6 +178,62 @@ impl SavedSwap { SavedSwap::Taker(taker) => taker.fetch_and_set_usd_prices().await, } } + + pub fn taker_pubkey(&self) -> Option> { + match self { + SavedSwap::Taker(swap) => Some(swap.taker_pubkey()), + SavedSwap::Maker(_) => None, + } + } + + pub fn maker_pubkey(&self) -> Option> { + match self { + SavedSwap::Maker(swap) => Some(swap.maker_pubkey()), + SavedSwap::Taker(_) => None, + } + } + + pub fn maker_usd_price(&self) -> Option<&BigDecimal> { + match self { + SavedSwap::Maker(swap) => swap.maker_coin_usd_price.as_ref(), + SavedSwap::Taker(swap) => swap.maker_coin_usd_price.as_ref(), + } + } + + pub fn taker_usd_price(&self) -> Option<&BigDecimal> { + match self { + SavedSwap::Maker(swap) => swap.taker_coin_usd_price.as_ref(), + SavedSwap::Taker(swap) => swap.taker_coin_usd_price.as_ref(), + } + } + + pub fn maker_gui(&self) -> Option<&String> { + match self { + SavedSwap::Maker(swap) => swap.gui.as_ref(), + SavedSwap::Taker(_) => None, + } + } + + pub fn taker_gui(&self) -> Option<&String> { + match self { + SavedSwap::Taker(swap) => swap.gui.as_ref(), + SavedSwap::Maker(_) => None, + } + } + + pub fn maker_mm_version(&self) -> Option<&String> { + match self { + SavedSwap::Maker(swap) => swap.mm_version.as_ref(), + SavedSwap::Taker(_) => None, + } + } + + pub fn taker_mm_version(&self) -> Option<&String> { + match self { + SavedSwap::Taker(swap) => swap.mm_version.as_ref(), + SavedSwap::Maker(_) => None, + } + } } #[async_trait] diff --git a/mm2src/mm2_main/src/lp_swap/taker_swap.rs b/mm2src/mm2_main/src/lp_swap/taker_swap.rs index 1fdb9e728f..1b1f894c20 100644 --- a/mm2src/mm2_main/src/lp_swap/taker_swap.rs +++ b/mm2src/mm2_main/src/lp_swap/taker_swap.rs @@ -8,7 +8,7 @@ use super::{broadcast_my_swap_status, broadcast_swap_message, broadcast_swap_msg check_other_coin_balance_for_swap, get_locked_amount, recv_swap_msg, swap_topic, wait_for_maker_payment_conf_until, AtomicSwap, LockedAmount, MySwapInfo, NegotiationDataMsg, NegotiationDataV2, NegotiationDataV3, RecoveredSwap, RecoveredSwapAction, SavedSwap, SavedSwapIo, - SavedTradeFee, SwapConfirmationsSettings, SwapError, SwapMsg, SwapPubkeys, SwapTxDataMsg, SwapsContext, + SavedTradeFee, SwapConfirmationsSettings, SwapError, SwapMsg, SwapTxDataMsg, SwapsContext, TransactionIdentifier, INCLUDE_REFUND_FEE, NO_REFUND_FEE, WAIT_CONFIRM_INTERVAL_SEC}; use crate::lp_network::subscribe_to_topic; use crate::lp_ordermatch::TakerOrderBuilder; @@ -350,31 +350,14 @@ impl TakerSavedSwap { } } - // TODO: Adjust for private coins when/if they are braodcasted - // TODO: Adjust for HD wallet when completed - pub fn swap_pubkeys(&self) -> Result { - let taker = match &self.events.first() { + pub fn taker_pubkey(&self) -> Result { + match &self.events.first() { Some(event) => match &event.event { - TakerSwapEvent::Started(started) => started.my_persistent_pub.to_string(), - _ => return ERR!("First swap event must be Started"), - }, - None => return ERR!("Can't get taker's pubkey while events are empty"), - }; - - let maker = match self.events.get(1) { - Some(event) => match &event.event { - TakerSwapEvent::Negotiated(neg) => { - let Some(key) = neg.maker_coin_htlc_pubkey else { - return ERR!("maker's pubkey is empty"); - }; - key.to_string() - }, - _ => return ERR!("Swap must be negotiated to get maker's pubkey"), + TakerSwapEvent::Started(started) => Ok(started.my_persistent_pub.to_string()), + _ => ERR!("First swap event must be Started"), }, - None => return ERR!("Can't get maker's pubkey while there's no Negotiated event"), - }; - - Ok(SwapPubkeys { maker, taker }) + None => ERR!("Can't get taker's pubkey while events are empty"), + } } } @@ -467,7 +450,6 @@ pub async fn run_taker_swap(swap: RunTakerSwapInput, ctx: MmArc) { subscribe_to_topic(&ctx, swap_topic(&swap.uuid)); let mut status = ctx.log.status_handle(); let uuid_str = uuid.to_string(); - let to_broadcast = !(swap.maker_coin.is_privacy() || swap.taker_coin.is_privacy()); let running_swap = Arc::new(swap); let swap_ctx = SwapsContext::from_ctx(&ctx).unwrap(); swap_ctx.init_msg_store(running_swap.uuid, running_swap.maker_pubkey); @@ -524,10 +506,8 @@ pub async fn run_taker_swap(swap: RunTakerSwapInput, ctx: MmArc) { error!("!mark_swap_finished({}): {}", uuid_str, e); } - if to_broadcast { - if let Err(e) = broadcast_my_swap_status(&ctx, running_swap.uuid).await { - error!("!broadcast_my_swap_status({}): {}", uuid_str, e); - } + if let Err(e) = broadcast_my_swap_status(&ctx, running_swap.uuid).await { + covered_error!("!broadcast_my_swap_status({}): {}", uuid_str, e); } break; },